Monday 16 August 2010

Cairngorm 3 Module Library

At work recently I have been looking at the Cairngorm 3 Module Library. It does some pretty cool things for example:

  • Skinnable ModuleLoader that displays loading and error states for a module
  • Lazy loads modules when parsley events are dispatched
  • Passes events to modules when they have loaded

The last item is what I was trying to get to work. We wanted to dispatch a loadSomeData event. The services that would load that data however are not initially available and need to be loaded in a module. Using a lazy load policy this module would be loaded and the event would then be passed to the module so that the loadSomeData Command would fire. Our CommandResult handler in the main application would then fire when the data had loaded.

To set this you need to set a few things up. You need a ParsleyModuleDescriptor in your application context:

<cairngorm:parsleymoduledescriptor
    url="SampleModule.swf"
    objectid="sampleModule"
    />

A lazy load policy in your context:

<cairngorm:LazyModuleLoadPolicy
    objectId="lazyLoadPolicy"
    type="{ ModuleInitialisationEvent }"
    />

And a ModuleViewLoader in your application:

<module:ModuleViewLoader
    moduleManager="{ moduleManager }"
    skinClass="{ ModuleViewLoaderSkin }"
    loadPolicy="{ lazyLoadPolicy }"
    />

This is enough to load the module when the ModuleInitialisationEvent is dispatched but the event will not be passed to the module as when the event is dispatched the module context is not yet initialised.

To solve this problem we need a ModuleMessageInterceptor tag, again in our application context:

<cairngorm:ModuleMessageInterceptor
    type="{ ModuleInitialisationEvent }"
    moduleRef="sampleModule"
    />

Now this should all work but as you can see from the sample app here it doesn’t. The module loads but the event does not get passed to the module (a working version of the sample app is here).

To fix this I had to patch the Cairngorm Module Library. There are actually 2 separate problems that I have reported in the 2 bugs listed here and here.

If you want to get your lazy loading modules to work correctly without patching Cairngorm then you need to make sure that your messageHandler or Command in the module is locally scoped. This does however mean that global CommandResult handlers won’t work for any results from the call.

You also need to make sure that your ModuleViewLoader has a moduleID and that your initialisation event has the same moduleId in and has the ModuleId Meta Data Tag.

I hope that my 2 patches for these fixes will be incorporated into trunk soon so that they will be available without patches.

Saturday 22 May 2010

Google IO Announcements

Over the past few days there have been a lot of announcements from Google at their IO event. There has been a lot of good news for the flash community and good news for android phone owners. As I am a Flex developer and have an android phone this has been exciting times!

The most exciting announcement for me was the fact that the AIR pre-release for android is now open:

http://blogs.adobe.com/air/2010/05/air_android_prerelease.html

A while ago I tried a bit of android development and started to think about writing a cycle computer application for my android phone. Now that we get AIR on Android though I can write this application much quicker in Flex. I can still get the geo-location and accelerometer data which is all I need.
The other advantage of course is that the application will work on any other device that supports AIR.

I am also very excited by all the cool new features coming in the next version of Android. I just hope it’s not too long before it’s released.

Thursday 18 February 2010

Setting up Apache and IIS on the same machine

Just a quick note to myself more than anything so I remember in the future.

I am currently trying to get both IIS and Apache running on my web server. The reason for this is because I want to move my SVN server from my home server to my remote server. This will mean that my SVN server can have it’s own static IP and run with apache on port 80 as a http server.

The problem was that by default IIS binds to all the IP addresses available to the server so that Apache was not able to bind to any.

I found this blog post very helpful.

To summarise:

  • Make sure httpcfg is installed – you might need to download the support tools
  • type the following command for each IP address that you want IIS to listen on:
    httpcfg set iplisten –i XXX.XXX.XXX.XXX
  • confirm the IP list you have created with:
    httpcfg query iplisten
  • restart http service:
    net stop http /y
    net start w3svc

That’s it. I now have Apache and IIS running on my server, both on port 80 but on different IPs. Now all I have to do is link Apache up to SVN and copy my dump of my local repository across.

Thursday 11 February 2010

SWCInspector v 0.2

I’ve uploaded a new version of SWCInspector. People at work, including myself, are already finding this pretty useful even with this early set of features.

The new version is here. I’ll update this html page to point at new versions as I upload them.

New features / fixes:

  • Big improvements to the renderers – they were very dodgy on scrolling before
  • Added a label to the selected asset indicating class name and swc that it came from
  • Added the ability to draw a box to display the asset bounds
  • Display bounds in the property pane so you can check 0,0 registration
  • Improved the width and height adjustment
  • Improvements to model wiring – more parsley based

If you find this useful let me know. I’ve got a lot more features that I want to implement but if you have any suggestions let me know.

The wife is away this weekend so hopefully there’ll be another version before Monday!

Sunday 7 February 2010

SwcInspector

At work all the assets that we use to create the applications are contained in swcs. These swcs are created in Flash and are used like any other library in Flex.

There can be a lot of assets and it can be hard to find the one that you are looking for. It is also handy to be able to test the asset before it actually gets into the application – see what states are defined and how it looks when it is re-sized to make sure the slice-9 is set up properly.

As we’re just getting to a point on my current project where we’re getting lots of assets delivered I put SwcInspector together this weekend. It is not finished yet but there is already quite a bit of useful functionality in there:

  • The ability to load multiple swcs into the application
  • Filtering of loaded asset list
  • Visibility of states defined for each asset
  • Resizing of assets to test slice-9
  • Adjustment of background color for white / light assets

As I said it’s not finished. The existing functionality needs some tweaking and there is some more functionality that I want to implement.

Unfortunately I can’t let you have a copy of the assets we use at work for obvious reasons. I found this swc courtesy of this blog for you to download and try out with the application if you so want to.

You can have a look at the application here. Using it with a swc with only 1 asset isn’t really a very good example but that’s all I’ve got I’m afraid! If you use swcs yourself give it a try and let me know how it goes – I have only been able to test it on a few so  wouldn’t be surprised if there are issues.

I’ll post again when I’ve made some progress. I can make the code available to anyone who’d like a look. If you want a copy please e-mail me.

Saturday 6 February 2010

AsyncTokenWrapper is Dead, Long Live AsyncTokenWrapper

As I said in the comments of my last post about AsyncTokenWrapper I didn’t like the way I was wrapping AsyncToken and handling the response.

A much neater solution to this is to create and register a custom command factory. You register a command based on the return type of your function. In my case I am returning a ProcessingAsyncToken so I go about registering my factory like this:

GlobalFactoryRegistry.instance.messageRouter.addCommandFactory( 
ProcessingAsyncToken,
new ProcessingCommandFactory()
);

I do this in a support class that implements ContextBuilderProcessor so that I can set this up when I create my context:





My command factory looks like this:

public class ProcessingCommandFactory implements CommandFactory
{
public function createCommand(
returnValue : Object,
message : Object,
selector : * = null
) : Command
{
return new ProcessingCommand( returnValue,
message,
selector
);
}
}

And just returns a new instance of my ProcessingCommand:

public class ProcessingCommand extends AbstractCommand
{

//-------------------------------------------------
//
// Constructor
//
//-------------------------------------------------

public function ProcessingCommand(
returnValue : *,
message : Object,
selector : *
)
{
super( returnValue, message, selector );

_processingToken = ProcessingAsyncToken( returnValue );

_processingToken.token.addResponder(
new Responder( complete, error )
);

start();
}

//-------------------------------------------------
//
// Private Variables
//
//-------------------------------------------------

private var _processingToken : ProcessingAsyncToken;

//-------------------------------------------------
//
// Overridden Methods: AbstractCommand
//
//-------------------------------------------------

protected override function selectResultValue(
result : *,
targetType : ClassInfo
) : *
{
return ( targetType.getClass() != ResultEvent && result is ResultEvent )
? ResultEvent( result ).result
: result;
}

protected override function selectErrorValue(
result : *,
targetType : ClassInfo
) : *
{
return ( targetType.getClass() == Fault && result is FaultEvent )
? FaultEvent( result ).fault
: result;
}

override protected function complete( result : * = null ) : void
{
var argumentsArray : Array;

if ( _processingToken.resultProcessingFunction != null )
{
try{
argumentsArray = _processingToken.resultProcessingArguments.concat();
argumentsArray.unshift( result.result );
result = _processingToken.resultProcessingFunction.apply(
this,
argumentsArray );
}
catch( e : Error )
{
error( e );
}
}

super.complete( result );
}

override protected function error( result : * = null ) : void
{
var argumentsArray : Array;

if ( _processingToken.faultProcessingFunction != null )
{
argumentsArray = _processingToken.faultProcessingArguments.concat();
argumentsArray.unshift( result.fault );
result = _processingToken.faultProcessingFunction.apply(
this,
argumentsArray );
}
super.error( result );
}

}

We just extend AbstractCommand and override the complete and error functions to apply the functions defined in ProcessingAsyncToken before passing the result on. In the constructor we add a responder to the AsyncToken in the return Value.

I call the function as follows:

[Command( type="com.pricklythistle.picasa.event.ListPicasaAlbumsEvent", messageProperties="userID,kind" )]
public function loadUserAlbums(
userID : String,
kind : String = null
) : ProcessingAsyncToken
{
url = StringUtil.substitute( BASE_URL, userID );

return loadUserEntries( kind );
}

I think this is a much neater solution that wrapping an AsyncToken inside another Async token – that had a really bad smell about it!

Saturday 30 January 2010

Android Development – emulator problems

I just had my first go at android development. SO far I have managed to get Hello World running on my phone in debug mode but unfortunately I can’t get the emulator running which is going to make development harder.

I’ve posted a question on stack overflow so hopefully some helpful person will be able to help me out.

Thursday 21 January 2010

AsyncTokenWrapper

I have to confess that I lied ever so slightly in that last post. I said that the service code was exactly the same as it was without using the Command metadatatag.

This isn’t strictly true – I had to write a wrapper for AsyncToken to handle the xml translation. I was hoping that I would be able to use an interceptor to intercept the result event, translate the xml and then re-dispatch the event. Jens said that this wasn’t possible though so I needed a neat and tidy way to translate the results of the async call before it made it back to the model.

I did this by wrapping the async token that I get from whatever async operation I am performing. I can then pass this token to parsley so my code can do what it likes to the result before parsley routes it to it’s destination.

AsyncTokenWrapper does just that, it extends AsyncToken and wraps another AsyncToken. When it gets a result or a fault from the original token it applies an optional function to the result or fault before passing this new ResultEvent or FaultEvent onto it’s responders.

Code Below:

package com.pricklythistle.common.service
{
import mx.core.mx_internal;
import mx.messaging.messages.IMessage;
import mx.rpc.AsyncToken;
import mx.rpc.Fault;
import mx.rpc.IResponder;
import mx.rpc.Responder;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;

use namespace mx_internal

public class AsyncTokenWrapper extends AsyncToken
{

//---------------------------------
//
// Constructor
//
//---------------------------------

public function AsyncTokenWrapper(
token : AsyncToken,
resultProcessingFunction : Function = null,
faultProcessingFunction : Function = null )
{
super();

_token = token;

addResponders();

this.resultProcessingFunction = resultProcessingFunction;
this.faultProcessingFunction = faultProcessingFunction;
}

//---------------------------------
//
// Private Variables
//
//---------------------------------
private var _token : AsyncToken;

//---------------------------------
//
// Properties
//
//---------------------------------

public var resultProcessingFunction : Function;
public var faultProcessingFunction : Function;

//---------------------------------
//
// Public Methods
//
//---------------------------------
private function onResult( data : Object ) : void
{
var originalResultEvent : ResultEvent = ResultEvent( data );
var result : Object = originalResultEvent.result;
if( resultProcessingFunction != null )
{
result = resultProcessingFunction( result );
}

var newResultEvent : ResultEvent = new ResultEvent(
ResultEvent.RESULT,
originalResultEvent.bubbles,
originalResultEvent.cancelable,
result,
this,
originalResultEvent.message );

applyResult( newResultEvent );

}

private function onFault( info : Object ) : void
{
var originalFaultEvent : FaultEvent = FaultEvent( info );
var fault : Fault = originalFaultEvent.fault;
if( faultProcessingFunction != null )
{
fault = faultProcessingFunction( fault ) as Fault;
}

var newFaultEvent : FaultEvent = new FaultEvent(
FaultEvent.FAULT,
originalFaultEvent.bubbles,
originalFaultEvent.cancelable,
fault,
this,
originalFaultEvent.message
);

applyFault( newFaultEvent );
}

//---------------------------------
//
// Private Functions
//
//---------------------------------
private function addResponders() : void
{
_token.addResponder(
new Responder( onResult, onFault ) );
}
}
}

Sorry for the way the code gets mashed up there but you can click on the little button top right to get it in a new window.

Asynchronous Commands in Parsley 2.2

I’ve been working with the latest version of parsley at work over the last few days and it’s got a really nice new feature borrowed from Cairngorm 3.0. It makes it much easier to deal with asynchronous operations. Previously if I was going to load something I might need all these files:

  • model that wants the data
  • loadData event – possibly with payload
  • Action to receive load event
  • service
  • ResultEvent
  • FaultEvent

Now we can get rid of a lot of these classes and end up with:

  • model that wants the data
  • loadDataEvent
  • service

You don’t actually need a custom event for the load either as you can just use a normal event and use string based matching but I prefer to match on class rather than string.

Let me give an example. In my Picasa API demo I had the following code in my LoadPicasaAlbumList action:

[MessageHandler]
public function loadAlbumList( event : ListPicasaAlbumsEvent ) : void
{
var token : AsyncToken = service.loadUserEntries( event.userID, PicasaService.KIND_ALBUM );
token.addResponder( this );
}
public function result( data : Object ) : void
{
var resultEvent : ResultEvent = ResultEvent( data );

var collection : ArrayCollection = PicasaTranslator.desearialiseXML( XML( resultEvent.result ) );

dispatchEvent( new ResultEvent( LIST_ALBUM_RESULT, false, true, collection, resultEvent.token, resultEvent.message ) );
}

public function fault( info : Object ) : void
{
var faultEvent : FaultEvent = FaultEvent( info );

dispatchEvent( new FaultEvent( LIST_ALBUM_FAULT, false, true, faultEvent.fault, faultEvent.token, faultEvent.message ) );
}

Along with a load of meta data tags at the top of the class. This class is no longer required – which is good as it’s a load of boring boilerplate code that doesn’t really do very much and is tedious to write.

Now we have the following:

Model:

protected function loadFeed() : void
{
albums = null;
dispatchEvent( new ListPicasaAlbumsEvent( userID.text ) );
}

Service:

[Command( type="com.pricklythistle.picasa.event.ListPicasaAlbumsEvent", messageProperties="userID,kind" )]
public function loadUserEntries( userID : String, kind : String = null ) : AsyncToken
{
if( !kind )kind = KIND_ALBUM;

if( ArrayUtil.getItemIndex( kind, KIND_ARRAY ) < 0 )
{
throw new Error( "kind must be found in KIND_ARRAY" );
}

url = StringUtil.substitute( BASE_URL, userID );

return new AsyncTokenWrapper( send( { kind : kind } ), PicasaTranslator.desearialiseXML );
}

Which is exactly the same code I had in the service originally except for the Command metadata tag. It instructs parsley to fire that function when an event of the correct type is received and tells parsley what properties to pass into the function.

Model:

[CommandResult]
public function onAlbums( albums : ArrayCollection, event : ListPicasaAlbumsEvent ) : void
{
this.albums = albums;
}

[CommandError]
public function onAlbumsFault( fault : FaultEvent, event : ListPicasaAlbumsEvent ) : void
{
trace( "fault" );
}
}

Parsley calls these functions when the command completes or fails and passes either a ResultEvent or your data in according to how you type the arguments.

And the really clever bit:

[Bindable]
[CommandStatus( type="com.pricklythistle.picasa.event.ListPicasaAlbumsEvent" )]
public var loadingAlbum : Boolean;

This populates the property with a Boolean value of true when the data is loading so that you can disable buttons / show a loader or do whatever you want.

For more details about the Command tags take a look here.

Sunday 17 January 2010

Picasa API Implementation v 0.1

Today I finally managed to get some time to carry on working on the Picasa API that I started in October or whenever it was (ok, I had to get up at about 5:00 but I couldn’t sleep!).

You can have a look at progress so far here. At the moment it only lists albums and allows you to click on them to go through the Picasa page. Put your own username in at the top and you’ll get your albums listed.

The next stage is to load the images for each album and display them.

I am pretty pleased with the progress I made today. Most of it was spent writing the translators for the XML which I did with some stub data and TDD which worked pretty well. In the past writing tests for xml translation didn’t work especially well and they always broke – but that was because the service layer changed. I am hoping that the Google APIs will be a bit more stable.

The UI code here is pretty ugly with no presentation models or anything like that, just enough to get what you see displayed. At the moment the effort is going into the API code.

I am hoping to eventually add support to this for other photo hosting services such as flickr. The model that I am using here is closely based on the xml format that comes back from Picasa. When I move to include other services there might have to be a few tweaks to make it work with more than one service.

Sunday 3 January 2010

Implementing Lazy Loading of XML with ArrayCollection

I am still gradually working through my implementation of the Picasa public API to load images into Flex. One of the first apps I want to build is a simple signature app for forums that will loop through images in a Picasa album and display them one by one.

A Picasa album can contain 1000 images and the xml is pretty verbose so this would be a very large download. This would download each time the signature appeared on a page and every time the page was refreshed so downloading the whole lot is really bad idea.

I want to mimic the fill method of DataService. I would ask for an ArrayCollection to be filled but only the first 5 or however many records are specified would initially be loaded. The length of the collection would be reported as the number of items in the album and not the number of items downloaded. Additional items would be loaded as they are required.

Looking at ArrayCollection the getItemAt method has a prefetch argument specifying the number of items to fetch if the item is not local. There is also the ItemPendingError that is despatched if the item that is requested is not local but there isn’t much documentation about this and it’s not clear exactly how this is handled.

I had hoped that List and DataGroup for example would listen for ItemPendingError and add responders but they don’t seem to so it might not be as useful to implement the behaviour in this way.

If anyone has any clues as to how all this holds together I’d be very interested to hear them. I am particularly interested in how the DataService class interacts with ListCollectionView. Somehow DataService has to get ListCollectionView to report the length of the remote list and not the local list.
Unfortunately the source for DataService doesn’t seem to be available.

I could possibly implement this with some specific implementation of IList that is passed to a ListCollectionView but I would rather do it a similar way to the framework.

Any help much appreciated.