Basic Architecture of a PureMVC Application: Part II

0

In PureMVC, the Mediator design pattern is used to mediate between the view and the framework. This reduces coupling, as the view knows nothing about the framework (if you’re importing any org.puremvc classes into your view, you’re doing it wrong), and knowledge of the view’s public API is limited to the Mediator which manages it. To kick things off we pass the view component to the Mediator, and register it with the framework:

public class ViewPrepCommand extends SimpleCommand
{
	facade.registerMediator( new TagCloudViewMediator( new TagCloudView ) );
}

The Mediator itself should provide limited functionality. It should advertise which notifications it’s interested in (via its listNotifications method, which is queried when the Mediator is registered via the facade), and respond to those same notifications by manipulating the view it mediates for. For instance, in our tag cloud example, we want to know when data about the tags has been received, and then retrieve this data from the relevant proxy and pass it to the view:

override public function listNotificationInterests():Array
{   
    return [ Notify.TAGS_LOADED ];
}   

override public function handleNotification( note:INotification ):void
{   
    var name:String = note.getName();

    switch( name )
    {   
        case Notify.TAGS_LOADED:
            view.setData( getTags() );
           break;
    }   
}   

private function getTags():Array
{   
    return remoteProxy.getTags();
}   

private function get view():TagCloudView
{   
    return TagCloudView( viewComponent );
}

private function get remoteProxy():RemoteProxy
{
    return facade.retrieveProxy( RemoteProxy.NAME ) as RemoteProxy;
}

As you run through this example, you’ll see that there isn’t much to our TagCloudMediator. That should be true of most mediators, if you find yours are much heavier than this or rely on a variety of private setup functions you should seriously consider moving this application logic to a command. We’ve already touched on the listNotificationInterests method, so moving on you can see that the handleNotification method determines how to act based on the name of the notification. In our case we’re only interested in Notify.TAGS_LOADED, and once this occurs, we pass the relevant data to the view.

One style we’ve settled on is to use an implicit getter called view() to cast the viewComponent Object to the specific type and return it. ‘tagCloudView’ is perhaps more descriptive, but there are certainly benefits in only having to locate and parse ‘view’ as you work across multiple mediators within an application.

You’ll notice we get tags via the RemoteProxy, so it’s a good time to back up, and look at the ModelPrepCommand we skipped over a little earlier:

public class ModelPrepCommand extends SimpleCommand
    {   
        override public function execute( notification:INotification ):void
        {   
            super.execute( notification );

            facade.registerProxy( new RemoteProxy() );
        }   
    }   
}

Here we register a new RemoteProxy with the facade, which is reasonably straightforward. We’re calling it the RemoteProxy because in this simple example it is the one and only proxy for accessing remote data. In the next post I’ll run through our RemoteProxy in detail.

Basic Architecture of a PureMVC Application: Part I

0

I previously went through setting up a RubyAMF gateway to provide AMF responses, and the next step was to build a Rich Client to consume this service. A simple tag cloud on its own does not demand the overhead of a framework, but explaining how to use a framework sensibly is often suited to simple examples, so that’s how we’ll start.

If you haven’t used PureMVC before, I’d recommend visiting http://www.puremvc.org and reading through the excellent Best Practices [pdf] documentation. The following notes should reflect some of these best practices along with some we’ve settled on at LBi.

Our app, like all PureMVC apps, will begin with the ApplicationFacade. Based on the Facade design pattern, the name already gives an indication of its purpose. In the case of PureMVC, the ApplicationFacade provides a single interface to work with the core Model, View, and Controller actors without a developer having to worry about dealing with them directly. Once we instantiate the ApplicationFacade in the main class we call its startup method which sends a Notify.STARTUP notification to kick the app into life:

public function startup( app:* ):void
{
	sendNotification( Notify.STARTUP, app );
}

The Notification system within PureMVC is based on the Observer design pattern, and is a straightforward approach to enabling commmunication between the various actors within the framework. We prefer to define Notification constants in a separate Notify class instead of directly within the ApplicationFacade, and in a more complex application you might want to think about logically breaking notifications into separate classes, and in the case of Models, defining them on the associated Proxies which send the Notifications (more on this later).

The Notify.STARTUP Notification triggers activity because in the same ApplicationFacade class we’ve mapped this particular notification to a specific Command:

override protected function initializeController():void
{
	super.initializeController();
	registerCommand( Notify.STARTUP, StartupCommand );

The Command design pattern involves creating stateless objects which execute actions in response to specific events. PureMVC provides both simple commands, which have an execute method, and macro commands, which list a number of simple commands which should be executed in order. Because a number of commands may be required at application startup, StartupCommand is defined as a macro command:

public class StartupCommand extends MacroCommand
{
	override protected function initializeMacroCommand():void
	{
		addSubCommand( ModelPrepCommand );
		addSubCommand( ViewPrepCommand );
	}
}

I’ll detail how these commands are used in the next post.

Setting up RubyAMF for Flash and Flex

0

As I’ve previously mentioned, RubyAMF gives you render:amf so you can send controller responses as binary AMF streams to Flash / Flex applications (also known as Flash remoting).

Setting it up for rails is reasonably straightforward. You just need to script/install http://rubyamf.googlecode.com/svn/trunk/rubyamf to install the plugin. If you’re developing locally you’ll want to restart your webserver, and then you should be able to browse to http://localhost:3000/rubyamf_gateway/ which will return an http response with a logo of RubyAMF.

Once that’s done the class mappings need to be specified, so that (for instance) a Tag class in ActionScript returned by a client swf is automatically deserialised into the appropriate Tag class within the Rails application.

Over a few posts I’m going to demonstrate putting together a Flex-based tag cloud which uses RubyAMF, so the mapping (which is defined in config/rubyamf_config.rb) would be this:

ClassMappings.register(:actionscript => 'Tag', :ruby => 'Tag', :type => 'active_record',
:attributes => ["id", "name", "count"])

(There’s plenty of examples in the config file along with other options worth looking at.)

Once that’s defined you’ll want to specify a controller method which returns your tag cloud data and also responds to AMF requests. As I mentioned earlier I’m using acts_as_taggable_on_steroids at the moment, and this plugin gives me a method which returns all tags and their counts, so the method (defined in my posts_controller.rb file) is as simple as this:

def tag_counts
	@tags = Post.tag_counts
	respond to do |format|
		format.html # If you'd like to do something in html
		format.amf { render:amf => @tags }
	end
end

At this point you’ll have an AMF gateway and a method which will return a complex datatype serialised as AMF. The next step is to build a Rich Client in Flex to consume this service.

Flex Builder 3.01 Plugin In Eclipse Ganymede 3.4 on OSX

0

Yes it works, but on OSX there’s a potential Java hitch to be aware of.

Download Eclipse Ganymede 3.4. Unzip Eclipse to a directory (normally Applications).

Download Flex Builder 3.01 Plugin.

BEFORE you run the Flex Builder Plugin installer on OSX, check that your java version is set to 1.5. However a simple java -version is not enough to satisfy the installer. You also have to cd /System/Library/Frameworks/JavaVM.framework/Versions/ and ls -al to check that CurrentJDK → 1.5.0.

I’d previously installed Java 1.6 on Mac, and although java -version gave me 1.5, the CurrentJDK → 1.6.0. This seems to have caused my install to fail with the error: ‘This installation can still be configured manually as a Product Extension’ and soon after an alert with ‘a newer file named “com.adobe.flexbuilder.debug.e33_3.0.205647.jar” already exists at “/Applications/Adobe Flex Builder 3 Plug-in/eclipse/plugins” Do you want to overwrite this file?’ Trying to follow the instructions offered is a fruitless exercise I won’t bother recounting because someone else already has (Borg – no permalinks for comments on that site).

Anyway ensuring you have 1.5.0 all the way should guarantee a successful install.