With the latest release of the Prana Framework came some great new features. One of them is support for templates in an application context. It came to our attention that when defining services, most of the application context was actually doing the same thing, namely defining let's say a remote object, but each time with a different service class.
Consider the following:
-
<object id="serviceLocator" class="org.pranaframework.cairngorm.CairngormServiceLocator" factory-method="getInstance">
-
<property name="assetService">
-
<object class="mx.rpc.remoting.mxml.RemoteObject">
-
<property name="destination" value="GenericDestination"/>
-
<property name="endpoint" ref="remoteGateway"/>
-
<property name="source" value="ApplicationDomain.Services.AssetService"/>
-
</object>
-
</property>
-
<property name="packageService">
-
<object class="mx.rpc.remoting.mxml.RemoteObject">
-
<property name="destination" value="GenericDestination"/>
-
<property name="endpoint" ref="remoteGateway"/>
-
<property name="source" value="ApplicationDomainDomain.Services.PackageService"/>
-
</object>
-
</property>
-
<property name="userService">
-
<object class="mx.rpc.remoting.mxml.RemoteObject">
-
<property name="destination" value="GenericDestination"/>
-
<property name="endpoint" ref="remoteGateway"/>
-
<property name="source" value="ApplicationDomainDomain.Services.UserService"/>
-
</object>
-
</property>
-
</object>
We're defining our ServiceLocator here with 3 services. You can quickly see that there is a lot of repetitive code in there, and we only have defined 3 services. Adding other services makes the application context really big and harder to read. (On a sidenote: notice the support for inner object/bean declarations).
The problem was solved by introducing template definitions. It allows you to create a template object and set some variables in it, using ant style parameters. You can then create a new object, tell the container that it must be based on a template and pass in the necessary parameters.
Here's an alternative application context to the previous one, but this time using a template for the remote object definition.
-
<template id="remoteObject">
-
<object class="mx.rpc.remoting.mxml.RemoteObject">
-
<property name="destination" value="GenericDestination"/>
-
<property name="endpoint" ref="remoteGateway"/>
-
<property name="source" value="ApplicationDomain.Services.${serviceClass}"/>
-
</object>
-
</template>
-
-
<object id="serviceLocator" class="org.pranaframework.cairngorm.CairngormServiceLocator" factory-method="getInstance">
-
<property name="assetService" template="remoteObject">
-
<param name="serviceClass" value="AssetService"/>
-
</property>
-
<property name="packageService" template="remoteObject">
-
<param name="serviceClass" value="PackageService"/>
-
</property>
-
<property name="userService" template="remoteObject">
-
<param name="serviceClass" value="UserService"/>
-
</property>
-
</object>
So we create a new template using the "template" tag with inside of it the object definition. Notice that the object definition has a variable ${serviceClass} defined. This variables will be filled in by the container when instantiating objects from a template definition. In the service locator, we create our services and tell them that they are based on the "remoteObject" template. We pass in the correct parameter and off we go.
Of course with small application contexts that only define 1 or 2 services, it might not really be worth using templates, although it could improve readability.
Hope you find this a valuable addition to Prana. We are allows eager to find out about new ideas that could benefit us all. So if you have any, be sure to contact us.
Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
Christophe Herreman is a software developer living in Belgium. He's working on high-end Flex and AIR solutions at 
December 21st, 2007 at 12:04 am
When I run an example using this using Flex Builder 3, I get an error:
A class with the name ‘mx.rpc.remoting.mxml.RemoteObject’ could not be found.
Have you run into this?
December 21st, 2007 at 8:52 am
Hey Tony,
have you referenced the RemoteObject class in your code so it gets compiled? I haven’t tried it with Flex Builder 3, but I don’t think it will result in different behavior than Flex Builder 2.
December 27th, 2007 at 5:50 pm
That’s a good point, Christophe. I bet that’s it. I’ll post back if it works.
January 3rd, 2008 at 2:24 pm
Hi Christophe,
I’m trying to configure my ServiceLocator using Prana and got into some troubles. My application context contains the following lines:
getDiscussionTopicsService
referencing an HTTPService (getDiscussionTopicsService).
My Services.mxml is inheriting the CairngormServiceLocator which is part of the prana framework.
Whenever i start the app it tells me that: Error: C0001E: Only one ServiceLocator instance can be instantiated
Thanks in advance for any hint
January 3rd, 2008 at 2:27 pm
Meh, my XML got killed: “getDiscussionTopicService” should be the following code:
{object id=”serviceLocator” class=”org.pranaframework.cairngorm.CairngormServiceLocator” factory-method=”getInstance”}
{property name=”getDiscussionTopicsService”}
{ref}getDiscussionTopicsService{/ref}
{/property}
{/object}
January 3rd, 2008 at 2:50 pm
Hi Norbert,
you no longer need a Services.mxml in your code if you use the CairngormServiceLocator class. Just define all your services in your application context file and remove the Services.mxml file (or its reference in your application).
The only thing to make sure is that the CairngormServiceLocator class and the ones of the services (e.g. RemoteObject) are compiled in your application.
Let me know if this works out for you.
regards,
Christophe
January 3rd, 2008 at 3:54 pm
Hey Christophe,
its working now and it also makes sense
. It’s the first time that I’m using Dependency Injection but I think I got the idea. Instead of a hard coded ServiceLocator we get an external and variable one. Of course there’s other stuff we can configure externally using Prana/DI.
Im also interested in feature driven development and want to be able to enable/disable features (for example a feature could be a “Remember me” option in an login screen, which can be enabled or disable for different customers) and I hope/think that should be possible using Prana.
What it makes somewhat hard to start with Prana is the missing or not up to date documentation. As you can see I used your older examples with the newest version and it didn’t work out as expected
.
Maybe it would help if there would be a wiki on pranaframework.org which could be kept up to date by the users. With topics like “Setting up Cairngorm Service Locator using Prana”
, hehe.
Anyway, thanks for the hint.
Greeting,
Norbert
January 3rd, 2008 at 9:18 pm
Hi Norbert,
I’m glad it’s working now.
You are absolutely right about the documentation. I’m aware of that fact that there should be some updates here and there. I’ll try my best to address these issues in the coming days/weeks.
A wiki would actually be a great idea. I’ll see what I can do. Thanks for your comments and suggestions!
March 12th, 2008 at 7:07 am
when i click play in .swf file i get an error like Error: C0001E: Only one ServiceLocator instance can be instantiated plz help
March 12th, 2008 at 8:32 am
Hi biju,
this is probably because you are still instantiating the ServiceLocator via the Service.mxml file. If you still have the problem, please get on the prana user mailinglist or e-mail at info [at] herrodius [dot] com.