Interactive psychological testing with Google Web Toolkit

I recently helped a friend set up on online psychology test. Not being at all familiar with psychological experiments I was directed to an existing software suite for inspiration – PEBL Test Battery.

Any of these tests could be converted into an online version with some nifty Javascript or Flash. But thanks to Google Web Toolkit and HTML5′s canvas feature it’s even easier to create interactive tests.

Although GWT makes it so easy to write web applications it doesn’t help you follow any design patterns (e.g. MVC or MVP).  I used GWTP to implement a Model-View-Presenter front-end (following an MVP pattern with this framework is much easier and it’s well documented). Although GWT now has an API to handle HTML5 canvas it doesn’t seem to be documented anywhere (well I couldn’t find anything other than Javadoc). So I used Vaadin’s GWTGraphics library which is documented. I think it’s also more cross-browser (or to be more precise it fights all the different versions of Internet Explorer – Microsoft like to keep themselves and everyone else busy).

Trail-making task demo here »

JVM Future Memory

Get the heap space to within an inch of its life and the JVM goes into “Quantum” mode.

JVM Future Memory

JVM Future Memory

As I understand it, the JVM will detect a PermGen dump before it even happens! This will be able in Java v5000.

Sorting a paginated DataGrid

Ever had the problem of a paginated DataGrid only sorting on the page that is currently being viewed? Yeah, pretty useless I know. I needed the whole set of data to be sorted and a quick search on tinernet suggested quite a few other people did too. Unfortunately none of the blogs I read seemed to have the exact answer. So here is the full working solution – I did this quickly so it may not be perfect. The pagination was done using this chaps implementation so if you’re not using that the below bit of code may not make much sense. A little bit of inspiration was taken from stackoverflow.

After sorting the ArrData list I realised that the refreshDataProvider method doesn’t even use it and instead uses some source property which is an Array representation of the list. Amazingly this has to be sorted separately! I don’t understand why ActionScript has this “feature”.


private var lastIndex:int = -1;
private var sortDesc:Boolean = false;

private function createNavBar(pages:uint = 1,intSet:uint = 0):void
{
   ...

   styleSortArrow();
}

private function refreshDataProvider(start:uint):void
{

   myData = new ArrayCollection( ArrData.source.slice((start * pageSize),(start * pageSize) + pageSize) );

   viewingAlertsLabel1.text = 'Page ' + (start+1).toString() + ' of ' + intPages.toString();
   viewingAlertsLabel2.text = 'Total items ' + orgData.length.toString();
}

/**
 *  Make the headerRelease attribute on the DataGrid call this function
 */
private function handleheaderReleaseEvt(event:DataGridEvent):void
{
	event.preventDefault();
	if(ArrData != null && ArrData.length > 0)
	{
		if( event.columnIndex == lastIndex )
		{
			sortDesc = !sortDesc;
		}
		else
		{
			sortDesc = false;
			lastIndex = event.columnIndex;
		}

		var sort:Sort = new Sort();
		var sortField:SortField = new SortField(event.dataField, true, sortDesc);
		sort.fields = [sortField];
		ArrData.sort = sort;

		// Sorted! ...oh wait there's some internal representation of the list as an array which also needs to be sorted!
		var sortDir:uint = sortDesc ? Array.DESCENDING : 0;
		var colToSort:DataGridColumn = DataGridColumn(theDataGrid.columns[event.columnIndex]);
		var colSortFunc:Function = colToSort.sortCompareFunction;
		if(colSortFunc != null)
		{
			// Column has a sort function so use that
			ArrData.source.sort(colSortFunc, sortDir);
		}
		else
		{
			// Column doesn't have a sort function so workout whether it's a numeric sort
			if(!isNaN(Number(ArrData.source[0][event.dataField])))
			{
				ArrData.source.sortOn(event.dataField, Array.NUMERIC | sortDir );
			}
			else
			{
				ArrData.source.sortOn(event.dataField, Array.CASEINSENSITIVE | sortDir );
			}
		}

		ArrData.refresh();
		refreshDataProvider(currentPageIndex);
		styleSortArrow();
	}
}

/**
 * Overriding the sorting loses the arrows so we have to do this manually
 */
private function styleSortArrow():void
{
	if(lastIndex != -1) {
		theDataGrid.sortIndex = lastIndex;
		if(sortDesc) {
			theDataGrid.sortDirection = "DESC";
		} else {
			theDataGrid.sortDirection = "ASC";
		}
		theDataGrid.invalidateDisplayList();
	}
}

Cairngorm: Tread carefully

A popular choice of framework when working with Flex is Cairngorm which has a nice tutorial to get you started. The reason I’m writing this blog is because of some code I came across recently. A developer had read the Cairngorm guide, taken it as gospel and then implemented it exactly. The only problem is that he wasn’t writing an application for an online shop which required a shopping cart. In particular the unnamed developer should have ignored the advice on the singleton model and in particular how one implements the IResponder interface.

The Cairngorm example is simple and the singleton model binding to your mxml pages is simple – it’s the quickest way to make Flex’s asynchronous behaviour work easily. If your application is a little more complicated then this simplicity becomes highly inflexible. To make my point a little clearer look at how the result method sets properties on the model.

public function result( event : Object ) : void
{
   var products : ICollectionView = ICollectionView( event.result );
   var model : ShopModelLocator = ShopModelLocator.getInstance();

   // sort the data
   var sort :Sort = new Sort();
   sort.fields = [ new SortField( "name", true ) ];
   products.sort = sort;
   products.refresh();

   // set the products on the model
   model.selectedItem = products[ 0 ];
   model.products = products;
   model.workflowState = ShopModelLocator.VIEWING_PRODUCTS_IN_THUMBNAILS;
}

Ok fine. But let’s imagine a user could have more than one shopping basket (unlikely I know but just to make my point). Or even better, what if your model had separate products for his and her shops. With this pattern you’re now stuffed because the model can only handle one set of products or one shopping basket. Yes, you could change the model so it can handle multiple sets of products, multiple shopping carts but that wouldn’t be the right way to fix the problem.

To overcome this inflexibility all you need to do is ditch the singleton model. Ok maybe don’t ditch the singleton model but only store truly global properties in it – the logged in user, a list of countries etc. Now how do you get your changes from an asynchronous service call to show up in your UI? Well without sounding too radical you could just implement MVC/MVP and pass the result of the event to you controller/presenter class.

I’m not entirely sure what Cairngorm’s Command classes are supposed to do. But my Command classes do virtually nothing and I let the Controller classes manipulate any result before setting it in the view.

/** The method that is invoked on the Controller when the result method is called */
private var _onSuccess:Function;

public function execute( event : CairngormEvent ): void
{
   _onSuccess = (event as MySpecialEvent).onSuccess;   

   if( ShopModelLocator.getInstance().products == null )
   {
       var delegate : ProductDelegate = new ProductDelegate( this );
       delegate.getProducts();
   }
   else
   {
      Alert.show( "Products already retrieved!" );
      return;
   }
}

//------------------------------------------------------------

public function result( event : Object ) : void
{
   _onSuccess(event.result);
}

Your controller class can then set the result on your mxml page (not very MVC but no bindings required) or you can bind the mxml page to a property on your controller class (the MVC way).

Why is this more flexible? The simple reason is that you have a Controller class for every mxml page. So if you 2 shopping baskets you have 2 ShoppingBasket controller classes. If you have his and her shops you have HisOnlineShopController and HerOnlineShopController – whatever granularity works best. It also stops you using the powerful but ultimately horrendous [Bindable] property on loads of properties in one class which every mxml page is looking at. In MVC the view should only be looking for properties where it needs to be – i.e. the controller/presenter that is handling the display of data in it. That way when you’re trying to find a null reference exception you only need to look at one mxml page (plus any nested pages) and one Controller class to work out where it is. I find this much better than putting a finger in the air and hazarding a guess as to which of the million [Bindable] properties in my singleton model is being set to null and which mxml page is bound to it.

And even better ActionScript is a functional language so it’s really easy to invoke a function after an asynchronous call finishes. Java can only achieve this by using interfaces which is not quite as neat (though the flow is quite clear).

 

Synchronise Events with Bindings in Flex

I have recently had to delve into the world of Adobe Flex and ActionScript and wanted to share some of my trials and tribulations with it. As I’m not a massive fan of Flash or proprietary technologies I had to assume the work had been assigned to me as a punishment for crimes committed in a previous life. In fact, 2 months in, I’m not entirely convinced what embedded Flash has to offer over conventional html and javascript – especially considering the features available in HTML5. “Meh” pretty much sums up my feelings for Flex – perhaps I’ve been doing too much Java.

Having previously been programming JSF I found Flex quite … different. One notable difference being it’s easy approach to the Observer Pattern with Bindings and another being it’s asynchronous behaviour. As JSF does not have any features comparable to these so this was all unchartered territory for me. In particular, I was experiencing some difficulty with asynchronous calls and the ViewStack. Basically the application was Single-Sign-On and I didn’t want the home view to show until they had been authenticated. Simple right? All you have to do is a bind a Boolean which is set by a CairngormEvent when authentication succeeds. Next problem was that there was some data to show on the home screen. But because every service call is asynchronous the screen would load with a blank area which would only be filled-in once the service call had completed. Well, what’s the point in showing a page unless it’s ready to be shown. I now have 2 conditions that must be true and ChangeWatchers seem to be the only thing that are going to help me.

A capability to synchronise asynchronous events is all I could think of to achieve the desired result. So I created a SynchronisedChangeWatcher class. WARNING – this is an over-engineered solution so I’m not sure if I would recommend using it:

public class SynchronisedChangeWatcher {

// Function to call once all watched properties are true
private var _callFunc : Function;
// List<{host, property}>
private var watchedProperties : ArrayCollection = new ArrayCollection();
// Map<Object{host, property}, ChangeWatcher>
private var propertyChangeWatchers : Dictionary = new Dictionary();
// Flag to indicate whether _callFunc has already been called - stops duplicate invocations
private var functionCalled : Boolean = false;

public class SynchronisedChangeWatcher(func : Function = null) {
_callFunc = func;
}

/**
*
* @param host the object where the property being watched resides
* @param property the name of the property to watch - must be <tt>public</tt> and <tt>[Bindable]</tt>.
* @param customCondition an optional function to perform a custom conditional operation. This function MUST return a <tt>Boolean</tt>. As it may be called repeated times
*      is should contain simple, read-only logic.
*/
public function watchPropertyWithCustomCondition(host : Object, property : String, customCondition : Function):BindingSynchroniser
{
if(host == null)
{
throw new ArgumentError("'host' object cannot be null");
}

if(customCondition == null && !(host[property] is Boolean))
{
throw new ArgumentError("Property '" + property + "' must be of type boolean");
}

if(!ChangeWatcher.canWatch(host, property))
{
throw new ArgumentError("Property '" + property + "' must be bindable");
}

watchedProperties.addItem({host: host, property: property, customcondition: customCondition});

return this;
}

/**
*
* @param host the object where the property being watched resides
* @param property the name of the property to watch - must be <tt>public</tt>, <tt>[Bindable]</tt> and <tt>Boolean</tt> .
*/
public function watchProperty(host : Object, property : String):BindingSynchroniser
{
return watchPropertyWithCustomCondition(host, property, null);
}

/**
* This starts watching properties or calling a function if all properties are true.
*/
public function start(arg : PropertyChangeEvent = null):void {
if(_callFunc == null) {
throw new Error("'callFunc' property cannot be null");
}

var allPropertiesTrue : Boolean = true;

for(var i : uint; i < watchedProperties.length; i++) {

var item : Object = watchedProperties.getItemAt(i);

// Either call the item's funtion to perform conditional logic or use item's property directly
if((item.customcondition != null && !Boolean(item.customcondition.call()))
|| (item.customcondition == null && !Boolean(item.host[item.property])) ) {

// Property is false so start watching
var cw : ChangeWatcher = ChangeWatcher.watch(item.host, item.property, start);
propertyChangeWatchers[item] = cw;
allPropertiesTrue = false;

} else if(propertyChangeWatchers[item] != null) {
// Property is true so stop watching
ChangeWatcher(propertyChangeWatchers[item]).unwatch();
propertyChangeWatchers[item] = null;
}
}

// Don't call function again if it has already been called - ChangeWatchers that are still running will cause this
if(!functionCalled && allPropertiesTrue) {
functionCalled = true;
unwatchAll();
_callFunc();
}
}

/**
* @param func the function to call once all watched properties are true
*/
public function set callFunc(func : Function):void {
_callFunc = func;
}

/**
* This method ensures any outstanding ChangeWatchers are stopped (this should have already happened in start() method).
*/
private function unwatchAll():void {
for each(var cw : ChangeWatcher in propertyChangeWatchers) {
if(cw && cw.isWatching()) {
cw.unwatch();
}
}
}
}

And it’s usage:

var scw : SynchronisedChangeWatcher = new SynchronisedChangeWatcher();
scw.callFunc = function():void{ doStuff(); scw = null; };
scw.watchProperty(_model, "UserLoggedIn");
scw.watchProperty(_model, "_CreationComplete");
scw.start();

So doStuff() will be called when both UserLoggedIn and _CreationComplete properties change – Simplz!

Yet Another tech blog

In my day-to-day activities of fighting evil, feeding the hungry and trying to make the world a better place I do some coding. How my time is divided between each activity I wouldn’t like to say. But when it comes to coding I’ll be honest and admit I don’t know everything. Quite often I have to turn to my friend Google for assistance. I seem to spend as much time reading other people’s personal musings on technology as I do any official documentation. The quality of people’s technology blogs is pretty varied, to say the least. Some are excellent, pioneering, golden examples of what a technology has to offer. Others are a complete and utter worthless pile of crap and I wonder why they took the time to write something (and waste my time reading). Some people have more free time than intelligence I guess.

In an effort to add something of worth to this vast worldwide internet I have decided to start this blog (if other people insist on adding their thoughtless tripe to the internet then why can’t I add my own).