Logging / debugging is often used in unit tests and that is no exception when working with AngularJS. In Angular we mostly use $log.debug (or $log.whatever), however in unit tests $log.debug doesn’t work and we’re forced to use javascript’s console.log. $log.debug is actually just AngularJS’ wrapper around this.

And then we often fill our tests and the source code with $log.debug‘s and feel compelled to comment all these out.

Outside of unit tests we can use the $logProvider to turn off debugs:


angular.module('app', [])
	.config(['$logProvider', function($logProvider){
		$logProvider.debugEnabled(false);
	}])

But this has no affect on console.log.

My requirements were:

  • Use $log.debug in my unit tests
  • Be able to turn logging (debug) on and off in my unit test (irrespective of $logProvider)

And this is how I did it (this using Jasmine for unit testing).


	describe('tooltipService', function () {
		// Set up logging
		var $log;
		var mockLog = {debug:function(){}}; // turn local logging off
		// var mockLog = {debug:console.log}; // turn local logging on

		...

		beforeEach(module(function ($provide) {
			mockResourceService = {getTooltips: jasmineNG.createPromiseReturningSpy(sampleTooltips)};
			$provide.value('resourceService', mockResourceService);
			$provide.value('$log', mockLog);
		}));

		beforeEach(inject(function ($rootScope, $q,_$log_, tooltipsService) {
			$log=_$log_;
			...

It may be nice to be able to set this globally for all tests in a project and override locally but haven’t yet tried that.

Now I can use $log.debug in my unit tests and can easily turn off ALL LOGGING by reversing the commented-out lines. Ie. changing the above lines to:


		// var mockLog = {debug:function(){}}; // turn local logging off
		var mockLog = {debug:console.log}; // turn local logging on

Also as an added bonus in this blog post, notice the mockResourceService and in particular the jasmineNG. This is part of a brilliant and clean way for testing services called by services and which return promises (as they should). I found this at http://decodify.blogspot.com.au/2013/10/angularjs-unit-testing-helper-for.html. For your reading pleasure the test setup and the first test that uses this is included below for your reading pleasure:


'use strict';

describe('tooltipService', function () {
    // Set up logging
    var $log;
    var mockLog = {debug:function(){}};         // turn local logging off
//    var mockLog = {debug:console.log};        // turn local logging on

    var mockResourceService;
    var jasmineNG = {};
    var scope;
    var service;
    var sampleTooltips = {
        'common': {'Global Unique ID': 'Globally unique identifier for the borehole (eg. a URI like http://pir.sa.gov.au/borehole/AZW74652526'},
        'petroleum': {'hydrocarbons': 'The summary of hydrocarbons encountered in the well'}
    };

    //set $q in your test
    jasmineNG.$q = undefined;
    jasmineNG.createPromiseReturningSpy = function (retval) {
        return jasmine.createSpy().andCallFake(function () {
            var res = jasmineNG.$q.defer();
            res.resolve(retval);
            return res.promise;
        });
    };

    beforeEach(module('gaBh.Module.App.dataService.tooltipsService'));

    // Mock service
    beforeEach(module(function ($provide) {
        mockResourceService = {getTooltips: jasmineNG.createPromiseReturningSpy(sampleTooltips)};
        $provide.value('resourceService', mockResourceService);
        $provide.value('$log', mockLog);
    }));

    beforeEach(inject(function ($rootScope, $q,_$log_, tooltipsService) {
        $log=_$log_;
        jasmineNG.$q = $q;
        scope = $rootScope.$new();
        service = tooltipsService;
    }));

    describe('getTooltip', function () {
        it('"common, global Unique ID" should return "Globally unique identifier for the borehole ..."', function () {
            var expected = 'Globally unique identifier for the borehole';
            var section = 'common';
            var elements = ['Global Unique ID'];
            var theData = '';
            $log.debug('this is debug');
            service.getTooltip(section, elements).then(function (data) {
                theData = data;
            }, function (error) {
                $log.debug('ERROR - ', error);
            });
            // force the promise to resolve
            scope.$apply();
            expect(theData).toContain(expected);
        });

Comments Off on AngularJS, unit testing and $log, Written on June 29th, 2014 , AngularJS, Uncategorized, Unit Testing Tags: , , , , , ,

I came up with some neat code for data preparation today. For unit testing you often have to prepare data. Unit tests should act as documentation for how the code works and thus it should be as easy to quickly read and digest as possible.

I’ll walk though several attempts at coming up with unit testing data.

First run


Alert a1 = new Alert();
a1.setText("test text");
a1.setTimestamp(new Date());
a1.setToken("token1");
interestedInThisToken.add("token1");

Alert a2 = new Alert();
a2.setText("test text");
a2.setTimestamp(new Date());
a2.setToken("token2");

Alert a3 = new Alert();
a3.setText("test text");
a3.setTimestamp(new Date());
a3.setToken("token1");
interestedInThisToken.add("token3");

Second Run

Run one was reasonably readable, but when you are building a lot of data or setting more fields there ends up being a fair bit of gruff you need to wade through to see the pertinent details. Lets clean that up a bit by introducing a helper function.


addAlert("test text", new Date(), "token1");
interestedInThisToken.add("token1");
addAlert("test text", new Date(), "token2");
addAlert("test text", new Date(), "token3");
interestedInThisToken.add("token3");

That’s much better. But we can go one better to get rid of that extra line. One problem with that line is you are repeating text and may get it wrong and thus make bad data. Obviously this is something you want to avoid when creating test data that is meant to prove your code is correct. So you could do this:


String tokenText = "token1";
addAlert("test text", new Date(), tokenText);
interestedInThisToken.add(tokenText);

But now an extra line has been added. Surely we can inline this by passing a flag.


addAlert("test text", new Date(), "token1", ADD_TOKEN_TO_INTERESTED_LIST);

We just overload addAlert() to take a boolean.

That’s not too bad. But let’s complicate the matter. Say we want to output the list of tokens we collect sometimes, and other times we just want the text. Easy, add another argument and overload addAlert() again:


addAlert("test text", new Date(), "token1", ADD_TOKEN_TO_INTERESTED_LIST, OUTPUT_AS_LIST);

But now we need 4 methods:


addAlert(....)
addAlert(boolean)
addAlert(int)
addAlert(boolean, int)

If we add another argument then we need another 4 methods. Its not a very scalable idea.

Third Run

There are a number of solutions and I’d like to write about the one I’ve developed.


public abstract class BaseArg {
	private static BaseArg instance = null;
	private List baseArgs = new ArrayList<>();
	private String lastBaseArg;

	private BaseArg() {
	}

	private static void make() {
		if (instance == null) {
			instance = new BaseArg();
		}
	}

	/**
	 * Clear the list of args (the list has been around since the JVM started).
	 */
	public static void clear() {
		if (instance != null) {
			instance.baseArgs.clear();
			instance.lastBaseArg = null;
		}
	}

	/**
	 * Add subsequent arg after the first one is added through {@link #create(String)}
	 * 
	 * @param arg
	 */
	public void add(String arg) {
		this.lastBaseArg = arg;
		this.baseArgs.add(arg);
	}

	/**
	 * 
	 * @return the arg just added
	 */
	public String out() {
		return lastBaseArg;
	}

	/**
	 * 
	 * @return the list of all args added (ie. since the JVM started). Call {@link #clear()} to clear the list of
	 *         args.
	 */
	public List outAsList() {
		return baseArgs;
	}

	/**
	 * This is the first method to call.
	 * 
	 * @param arg
	 *            we are saving.
	 * @return the new instance we can call other methods on.
	 */
	public static BaseArg create(String arg) {
		make();
		instance.add(arg);
		return instance;
	}

	/**
	 * We don't want the added arg to be added to the List since we only want to add ones that are of interest to us.
	 */
	public BaseArg noList() {
		baseArgs.remove(baseArgs.size() - 1);
		return instance;
	}
}

Some of you may recognise the Singleton pattern.

Just create the class for the type you want to pass in as arguments. This one is just for Strings, however you could easily create a Generics version for any type:


public class Token extends BaseArg {
}

Now you can write your data building code more succinctly and with infinite possible ways to modify how the data is being worked:


# token1 is added to the list
addAlert("test text", new Date(), Token.create("token1").outAsList());

outAsList() says to output the full list


# token2 is NOT added to the list
addAlert("test text", new Date(), Token.create("token2").noList().out());

noList() says not to add the argument to the list
out() says to output just the text ie. ‘token2’

I can spot 2 potential problems here but they are easily fixed, and this is code only developers are going to work with anyway:

  1. What if you want to have 2 lists – 1 for things interested in, the other for the list of tokens. ANS: No problems just update the baseArg class or even a subclass if that is better
  2. What if you don’t make the fix as per point 1 and and then still say .noList().outAsList(); Although not a bug it seems silly that you’d pass a new token in but not do anything with it. If you do want to prevent this problem then you could update outAsList() to only output the list if the last item is the same as lastBaseArg.

Happy testing!

Comments Off on Unit test data preparation, Written on August 31st, 2013 , Java, Unit Testing Tags:

I followed Markus Eisele’s great article on creating a JDBCRealm in Glassfish – jdbc-realm-glassfish312-primefaces342.html.

However I tried getting this to work by building in Eclipse instead of Netbeans and it proved not so straight-forward. It turns out that the extra work was minimal; it just took me a little effort to work this out.

Increase log levels

My first advice when you have no idea of what is going on with your JEE deployed application is to increase the log levels on your application server – Glassfish in this case. Find them at:

Glassfish > Configurations > Server-config > Logger Settings > Log Levels (tab)

Differences between Netbeans and Eclipse

Netbeans ‘just works’, but at the cost of some flexibility and power. Eclipse is Fucken awesome, with awesome (or large) being the operative word.

For example is this case (and which is the main difference I’m discussing).

The deployment descriptor glassfish-resources.xml is used to setup the JDBC Connector and Resource. Unfortunately, as I learnt, its not a deployment descriptor in the sense that it is read by the Application Server (Glassfish here) when its in the WEB-INF or META-INF directory.

What Netbeans does is run the following under-the-hood.


asadmin add-resources WEB-INF/glassfish-resources.xml

And that precisely is what you need to do when developing this using Eclipse. Either that or define the JDBC Connector and Resource manually in Glassfish. However its better to move such actions to a file that can be replayed (which you need to do after you remove and re-add the Glassfish server in Eclipse which I seem to need to do every now and then).

Other gotchas

Other steps needed as modifications to Markus’ article are:

  • Database configuration can’t be done through the IDE to the same extent – use MySQL Workbench or just the mysql command-line for MySQL, or whatever tools for your database of choice.
  • The section on JDBC Connector and Resource and Extract from Existing Connection to creaqte the glassfish-resources.xml doesn’t have a counterpart in Eclipse. Instead either do in Netbeans and copy the contents to a new xml file in the WEB-INF directory, or create the same file from an example on the web (eg. http://javahowto.blogspot.com.au/2011/02/sample-glassfish-resourcesxml.html) and populate with your values.
  • The Additionally we still need Primefaces part doesn’t need a fancy wizard with a checkbox. Simply add Primefaces as a dependency in your Maven pom. Group=org.primefaces, Artifact=primefaces, Version=3.4.2 (current)
  • For the jsf / xhtml files, just create html files and select the Facelets Composite Page (WTP needs to be installed). Or simply create a file called whatever.xhtml in the appropriate directory. Then just populate with what’s in Markus’ article.
  • The New > Other > GlassFish > GlassFish Descriptor” section just requires you create a WEB-INF/glassfish-web.xml file and populate with the given <security-role-mapping>
Comments Off on JDBC Realm and Form Based Authentication with GlassFish 3.1.2.2 and Primefaces 3.4 and built with Eclipse, Written on June 13th, 2013 , authentication, Java, JSF Tags: , ,

I’ve had a Raspberry Pi sitting around for a while. I had some initial attempts to install XBMC and it worked out ok, but not convincing enough to replace my Mac Mini as an Media Centre. Well now the logic card seems to be failing on the Mac Mini (main problem is that the network just stops working every now-and-then), and so I’m looking to transition the apps off it.

So the Raspberry Pi now seems to be appropriate.

I decided on XBian and it all went smoothly. However I couldn’t access my Videos on another server. I could have ditched the Mac-way and setup a SMB share (or rather, connect to the Samba share), but then I’d lose all the Mac-Bonjour discovery nicety of the Mac.

Anyway I found some a simple solution:

  1. ssh xbian:raspberry@<ip_address> # default
  2. sudo apt-get install libafpclient0
  3. http://gettingstartedwithraspberrypi.tumblr.com/post/24398167109/file-sharing-with-afp-and-auto-discovery-with-bonjour should be followed to enable the XBian being seen over AFP (ie. is a Share)
    sudo apt-get install netatalk
Comments Off on XBian, XBMC on Raspberry Pi; On a Mac AFP network, Written on April 4th, 2013 , XBMC Tags: , ,

Are you a git user that wants analytics. http://githalytics.com/ does just this.

  1. Simply create a Google Analytics account, adding a new Property for the new github site. This will give you a Property Id.
  2. Complete the web form at githalytics with a URL of the github site and the Google Analytics property id.

This will return some .md formatted markup to add to your github site’s readme.md file. But what if you don’t use the .md format? http://flexion.org/posts/2012-10-github-analytics.html is a post about changing the output for the reStructuredText format. If you use textile format, which I mostly do then read on …

GitHalytics will return this (such as):

[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/abcde01234567890 "githalytics.com")](http://githalytics.com/oehm-smith/Spritzer)

Change it to:


"!https://cruel-carlota.pagodabox.com/abcde01234567890(githalytics.com alpha)!":http://githalytics.com/oehm-smith/Spritzer

Both these translate to:


<a href="http://githalytics.com/oehm-smith/Spritzer"><img src="https://cruel-carlota.pagodabox.com/abcde01234567890" title="githalytics.com alpha" alt="githalytics.com alpha" style="max-width:100%;"></a>

Comments Off on Githalytics – .textfile format, Written on March 25th, 2013 , git, github Tags: , ,

I just received a mail from Apple about the new MacBook Pro. I’m wondering which will be phased out – the MacBook Air or this? What about the iBook – does it exist? I spose it will become the lower-spec look-a-like.

Comments Off on New MacBook Pro, Written on November 8th, 2012 , Apple, Macintosh Tags: ,

*Next task* – adding a license-based header (template) to Netbeans 7 Maven-based projects.

This dzone article seems to relate to Ant based projects as I cannot see an Important Files (Smart) folder, nor can I see a nbproject/project.properties file.

However I found this netbeans forum discussion on the topic and it says that you modify the pom.xml adding this:

<name>My Application</name>

<licenses>
  <license>
    <name>The Apache Software License, Version 2.0</name>
    <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
    <distribution>repo</distribution>
    <comments>A business-friendly OSS license</comments>
  </license>
</licenses>

<properties>
  ...

To the pom.xml (I added it as a top-level element as a child of and an adjacent sibling to <name> and <properites>.

If the URL is one of the following then the appropriate template (Tools > Templates) is used.

Don’t forget to set the properties such as user as discussed in the dzone article.

Comments Off on Netbeans 7, Maven, Template, Licenses, Written on October 31st, 2012 , My Projects, netbeans, Spritzer Tags: , ,

I’ve been on holidays, leaving the evening after updating my Mac to the latest Java.

This update essentially (for 10.7 and 10.8) users, removed Apple’s involvement in Java for the platform completely by removing Java Preferences and making the default Java 7. More info at Cnet.com / Java Preferences missing after latest OS X Java update.

Anyway, I was receiving emails from Crash Plan telling me I haven’t backed up for days. Mmm I thought, I wonder what my wife has done :).

I got home and sure enough the CP menu-bar icon was grayed out and there was a message saying “Unable to connnect to the local backup engine”. My wife was not the cause (not that I really thought that anyway but still gotta wonder).

I opened Console and I found it saying:

26/10/12 11:07:59.610 PM com.apple.launchd: (com.crashplan.engine[2566]) Tried to setup shared memory more than once

Suggestions were that CrashPlan needed to up the -Xmx Java max memory setting. Made no difference.

I then looked a bit deeper and found /Library/Logs/CrashPlan, and in particular the engine_error.log.

It said:

java.lang.ExceptionInInitializerError
at com.code42.os.mac.io.IOPolicy.setIoPolicy(IOPolicy.java:69)
at com.backup42.service.CPService.start(CPService.java:383)
at com.backup42.service.CPService.main(CPService.java:1622)
Caused by: com.jniwrapper.LibraryNotFoundException: Cannot find JNIWrapper native library (libjniwrap.jnilib) in java.library.path: /var/root/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.:/Applications/CrashPlan.app/Contents/Resources/Java/lib

java -version

tells me its Java 1.7 which made me thing something was odd since I set 1.6 as the default.

I tried to open Java Preferences, which on the Mac let you set which version of Java is the default. It no longer existed. I found the cnet article liked to above (Cnet.com / Java Preferences missing after latest OS X Java update) telling me the Java ecosystem on the Mac is changing.

I searched on “Crash Plan mac osx java 7” and I found this java.dzone article. It said to change the version of Java used for the Crash Plan service back to 1.6 in the /Library/LaunchDaemons/com.crashplan.engine.plist Launch Daemon file. See that article for precise instructions.

Following this remedy fixed the problem. As a bonus I can drop my Java max memory (back to the 512k)!

Comments Off on Mac OS X & latest Java update – Crash Plan no longer working, Written on October 26th, 2012 , Java, Mac OS X Tags: , ,

I’ve added code I’ve put into my portfolio. I’ve just started growing this as its never seemed important in the past. Check out what I’ve done and let me know what you think.

See http://tintuna.com/drupal/ProjectsAndCode

Comments Off on Code me – my development portfolio, Written on October 22nd, 2012 , Portfolio

I saw InjectionPoint mentioned breifly by Adam Bien in his JavaOne 2011 Presentation JavaEE 6 Cool Parts (around about 0:50).

There wasn’t much information about it though I found the Javadoc at http://docs.oracle.com/javaee/6/api/javax/enterprise/inject/spi/InjectionPoint.html and it had all I needed to know.

For example, the following producer method creates injectable Loggers. The log category of a Logger depends upon the class of the object into which it is injected.

@Produces
Logger createLogger(InjectionPoint injectionPoint) {
return Logger.getLogger( injectionPoint.getMember().getDeclaringClass().getName() );
}

And it works!

//index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">
  <h:head>
    <title>Facelet Title
  </h:head>
  <h:body>
    Hello from Facelets
    <h:form>
      <h:commandButton value="Injector seat!" action="#{messenger.hello}"/>
    </h:form>
  </h:body>
</html>
// Messenger.java
package boundary;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;

/**
 *
 * @author bsmith
 */
@Named
public class Messenger {
    @Inject String data;
    @Inject Logger log;

    public void hello() {
        System.out.println("Hello!  I want: "+data);
        log.log(Level.SEVERE, "("+log.getName()+") I am logging some data: "+data);
    }
}
// Configuration.java
package control;

import java.util.logging.Logger;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;

/**
 *
 * @author bsmith
 */
public class Configuration {
    @Produces
    public String getData(InjectionPoint ip) {
        System.out.println("ip.toString: "+ip.toString());
        System.out.println("ip.getAnnotated: "+ip.getAnnotated());
        System.out.println("ip.getBean: "+ip.getBean());
        return "data";
    }

    @Produces
    public Logger getLogger(InjectionPoint ip) {
        return Logger.getLogger( ip.getMember().getDeclaringClass().getName() );
    }
}

INFO: com.tintuna_Injection_war_1.0-SNAPSHOT was successfully deployed in 398 milliseconds.
INFO: ip.toString: [field] @Inject boundary.Messenger.data
INFO: ip.getAnnotated: [field] @Inject boundary.Messenger.data
INFO: ip.getBean: Managed Bean [class boundary.Messenger] with qualifiers [@Any @Default @Named]
INFO: Hello!  I want: data
SEVERE: (boundary.Messenger) I am logging some data: data
Comments Off on Java EE 6 and javax.enterprise.inject.spi.InjectionPoint, Written on October 13th, 2012 , EJB, Java Tags: , ,

Brooke Smith is proudly powered by WordPress and the Theme Adventure by Eric Schwarz
Entries (RSS) and Comments (RSS).

Brooke Smith

Portfolio and site of a software engineer