Cairngorm Getting Started Part Five : Delegates and Responders
We’ve created our LoadXMLEvent, created our FrontController and that has linked the event with the command to get the XML. Now we need to create our next set of classes. The Delegate class deals with retriving the data, it does this by using another Cairngorm class called the ServiceLocator. As the Delegate is getting some data we need to create a Responder to recieve and deal with the data. As this is a simple application we could make the Command the Responder too, but as I want this to be a pucker representation of how Cairngorm works I’m going to go ahead and create the Responder.
So – lets create the ServiceLocator. The ServiceLocator is a ModelLocator really, and is where you keep all of the data calls for the application. This is a great thing to do as the service locator is where you call the server side code, or as in this case load the XML. This means that if you’d developed an application with a ColdFusion backend and needed to port it over to AMFPHP then you should only need to swap out this class and it should all function as expected. (Note the use of the word ’should’)
Anyway lets have a look at it.
<?xml version="1.0" encoding="utf-8"?> <cairngorm:ServiceLocator xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:cairngorm="com.adobe.cairngorm.business.*"> <mx:HTTPService id="xmlService" resultFormat="e4x" showBusyCursor="true"/> </cairngorm:ServiceLocator>
So to create this right click on the business folder and select new -> MXML component. It doesn’t matter what you choose as the component as you can see from above we are going to use our own tag to identify it. Add the xmlns declaration so we can reference the com.adobe.cairngorm.business package. Once you’ve done that pop the HTTPService tag in. This is what will load the XML and we’ve set the result format to e4x so we can use the e4x syntax to work with the XML returned.
Right one down. Now we’ll create the responder. Right click on the responder folder…..actually, by now I think you’ve got the hang of creating classes. I’ll just describe them. The responder classes live in the responder folder need to implement the IResponder interface.
package com.worthyashes.simpleCairngorm.responder
{
import com.worthyashes.simpleCairngorm.model.MemoryModelLocator;
import mx.rpc.IResponder;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
public class LoadXMLResponder implements IResponder
{
public function LoadXMLResponder()
{
}
public function result(data:Object):void
{
var resultEvent:ResultEvent = data as ResultEvent;
trace("XML loaded");
}
public function fault(info:Object):void
{
var faultEvent:FaultEvent = info as FaultEvent;
trace("Fault at [LoadXMLResponder] " + faultEvent.message);
}
}
}
The result and fault events are called by either a -er- result or fault. To implement the interface correctly they have Objects passed in as parameters, but they are actually ResultEvents and FaultEvents respectively. This is why I’ve immediately created a local variable of type either ResultEvent or FaultEvent and cast the objects into it. If you’ve been hunting for tutorials on Cairngorm you’ll probably have seen something similar to “Fault at [LoadXMLResponder] “. I can’t remember which tutorial uses this, I’ll pop a link in when I find it, but this has been a lifesaver a number of times for debugging.
OK now we create the Delegate class that sticks this all together. The delegate also lives in the business folder, but doesn’t extend or implement anything.
package com.worthyashes.simpleCairngorm.business
{
import com.adobe.cairngorm.business.ServiceLocator;
import mx.rpc.AsyncToken;
import mx.rpc.IResponder;
import mx.rpc.http.mxml.HTTPService;
public class LoadXMLDelegate
{
private var responder:IResponder;
private var service:HTTPService;
public function LoadXMLDelegate(responder:IResponder)
{
this.responder = responder;
this.service = ServiceLocator.getInstance().getHTTPService("xmlService") as HTTPService;
this.service.url = "xml/example.xml";
}
public function loadXML():void
{
var token:AsyncToken = service.send();
token.addResponder(responder);
}
}
}
There we go. The delegate holds a referenced to the responder and the service to call. Then when called to load the XML it triggers the load on the service and adds the responder to the service. This is why the Responder needs to implement IResponder and have the result and fault events. Now we get the Command to create the Delegate and trigger it.
package com.worthyashes.simpleCairngorm.commands
{
import com.adobe.cairngorm.commands.ICommand;
import com.adobe.cairngorm.control.CairngormEvent;
import com.worthyashes.simpleCairngorm.business.LoadXMLDelegate;
import com.worthyashes.simpleCairngorm.events.LoadXMLEvent;
import com.worthyashes.simpleCairngorm.responder.LoadXMLResponder;
public class LoadXMLCommand implements ICommand
{
public function LoadXMLCommand()
{
}
public function execute(event:CairngormEvent):void
{
var e:LoadXMLEvent = event as LoadXMLEvent;
var delegate:LoadXMLDelegate = new LoadXMLDelegate(new LoadXMLResponder());
delegate.loadXML();
trace("Getting the XML");
}
}
}
All we’ve added is
var delegate:LoadXMLDelegate = new LoadXMLDelegate(new LoadXMLResponder()); delegate.loadXML();
Finally we need to instantiate the ServiceLocator, otherwise we won’t be able to use it. Back in the main application file add the xml name space in the opening tag of
xmlns:business=”com.worthyashes.simpleCairngorm.business.*”
and add this MXML tag
<business:Services id=”services”/>
That’s it. If you run the code now all being well you’ll get a trace to tell you the XML is loaded.
So now we’ve got the data loaded we need somewhere to put it, which takes us all the way back to the discussion of singletons. Next we are going to create a ModelLocator to hold the data.