Archive for the 'Remoting' Category

Dynamic RemoteObject endpoints in Cairngorm

Tuesday, May 27th, 2008

I’m still trying to get the hang of how the Cairngorm framework uses RemoteObjects. For the uninitiated (and you do get initiated, kind of like a beat-in) Cairngorm is a Model-View-Controller framework used to organize and structure your ActionScript code in Flex.

When using RemoteObjects in Cairngorm and Flex, everything is fine if you know the URL of your endpoints beforehand. You configure your services-config.xml file, setup some RemoteObject tags in your Services.mxml file, and away you go.

But what if you want to select an endpoint at runtime? In my application, when a user logs in they can select from a number of servers.

The user can select from a number of servers before logging in.

This list of servers is downloaded from a main “Admin” server when the user first launches the app (it’s a desktop application composed of a swf wrapped in Multidmedia’s Zinc program).

As I mentioned above, setting up your RemoteObjects with Cairngorm and Flex takes a couple steps. First, you describe the endpoints of your services in the services-config.xml file. I won’t go into the whole format of this .xml file here; the important point for this discussion is that the endpoint information is placed in an <endpoint> tag.

<endpoint uri="http://myCrazyRailsApplicationWithWebOrb.org:3000/weborb" class="flex.messaging.endpoints.AMFEndpoint"/>

You’ll notice in the URL that I’m using WebORB, a remoting gateway that connects Flex to my Rails app.

Next, you use the Cairngorm convention of creating RemoteObject tags in a Services.mxml file in order to make them available to your application through the Cairngorm ServiceLocator class.

Here’s a portion of my Services.mxml file with one service that handles login:

<cairngorm:ServiceLocator   xmlns:mx="http://www.adobe.com/2006/mxml"
                            xmlns:cairngorm="http://www.adobe.com/2006/cairngorm">

    <mx:RemoteObject   id="UserService"
                        destination="UserService"
                        showBusyCursor="true"
                        result="event.token.resultHandler( event );"
                        fault="event.token.faultHandler( event );">
                                               

    </mx:RemoteObject>

</cairngorm:ServiceLocator>

Now, whenever I need to call my service, I create an instance of the service and issue the calls. In Cairngorm, this usually happens in a Delegate object.

myService= ServiceLocator.getInstance().getRemoteObject( "ScenarioService" )

However, here’s problem: the Cairngorm ServiceLocator returns a Remoting object of type mx.rpc.remoting.RemoteObject. Unfortunately, with this class there isn’t (I think) a way to change the endpoint parameter to a different URL.

There is another RemoteObject class, extended directly from mx.rpc.remoting.RemoteObject. It’s mx.rpc.remoting.mxml.RemoteObject! (Thanks to Temujin for making this clear to me.)

This class does allow you to set the endpoint parameter. Since the RemoteObjects held by the Cairngorm ServiceLocator are actually of this type, all you need to do is cast the returned RemoteObject to it and then set the new endpoint:

myService = mx.rpc.remoting.mxml.RemoteObject (ServiceLocator.getInstance().getRemoteObject("ScenarioService" ))
service.endpoint = myNewEndpointURL

I’m probably misunderstanding how the framework should be used. Why would Cairngorm return the more generic superclass of RemoteObject? Alas, my app is working now so that ugly friggin’ cast is staying there.