Prana enabled Cairngorm Store

ActionScript, Cairngorm, Flex, Inversion of Control, Prana Add comments

Following up on Douglas McCarroll's modified Cairngorm Store update, I thought I'd take this a step further and add a Prana application context to configure the business delegates and the service locator. This example has support for mock delegates that contain hardcoded local data and is also able to connect to php services using Remote Objects and AMFPHP.

This examples replaces the older Cairngorm Store example that was configured to work with AMF0 and Renaun Erickson's RemoteObjectAMF0. It now uses the latest beta version of AMFPHP and the AMF3 protocol. The services are hosted on this domain so you don't need to setup AMFPHP in order to see this in action.

The code is currently in svn and can be checked out at http://prana.svn.sourceforge.net/viewvc/prana/trunk/samples/PranaCairngormStore/. This sample will also be included in the next release.

Here's a snippet from the readme file:

***

The following files have been added/changed in order to add Prana configuration support for business delegates and service locator:

* Main.mxml: added application context loader and forced compilation of configured classes

package com.adobe.cairngorm.samples.store.business
* BaseBusinessDelegateMock.as: implements IResponderAware, removed responder constructor argument
* CreditCardDelegate.as: extends AbstractRemoteObjectDelegaten, implements ICreditCardDelegate
* CreditCardDelegateMock.as: implements ICreditCardDelegate
* ICreditCardDelegate.as: interface for credit card delegates
* IProductDelegate.as: interface for product delegates
* ProductDelegate.as: extends AbstractRemoteObjectDelegaten, implements IProductDelegate
* ProductDelegateMock.as: implements IProductDelegate

package com.adobe.cairngorm.samples.store.commands
* GetProductsCommand.as: added delegate lookup via ShopModelLocator
* ValidateCreditCardCommand.as: added delegate lookup via ShopModelLocator

package com.adobe.cairngorm.samples.store.model
* ShopModelLocator.as: added creditCardDelegate and productDelegate variables to configure business delegates

***

As a result, we can now lookup the implementation of our business delegates in the commands instead of instantiating new ones. The commands are completely unaware of the implementation of the business delegates. One note though: since we are not creating new delegate instances, we need to set the responder as a property of the delegate before calling its methods.

Actionscript:
  1. var delegate:IProductDelegate = ShopModelLocator.getInstance().productDelegate;
  2. delegate.responder = this;
  3. delegate.getProducts();

Here's how the application is configured in the application context to use the mock delegates:

XML:
  1. <object id="shopModelLocator" class="com.adobe.cairngorm.samples.store.model.ShopModelLocator" factory-method="getInstance">
  2.     <property name="creditCardDelegate">
  3.         <object class="com.adobe.cairngorm.samples.store.business.CreditCardDelegateMock"/>
  4.     </property>
  5.     <property name="productDelegate">
  6.         <object class="com.adobe.cairngorm.samples.store.business.ProductDelegateMock"/>
  7.     </property>
  8. </object>

And here's how the remote object delegates and the service locator are configured:

XML:
  1. <object id="endPoint" class="String">
  2.     <constructor-arg value="http://www.herrodius.com/amfphp/gateway.php"/>
  3. </object>
  4.  
  5. <object id="serviceLocator" class="org.pranaframework.cairngorm.CairngormServiceLocator" factory-method="getInstance">
  6.     <property name="productService">
  7.         <object class="mx.rpc.remoting.mxml.RemoteObject">
  8.             <property name="destination" value="GenericDestination"/>
  9.             <property name="endpoint">
  10.                 <ref>endPoint</ref>
  11.             </property>
  12.             <property name="source" value="com.adobe.cairngorm.samples.store.business.ProductService"/>
  13.         </object>
  14.     </property>
  15.     <property name="creditCardService">
  16.         <object class="mx.rpc.remoting.mxml.RemoteObject">
  17.             <property name="destination" value="GenericDestination"/>
  18.             <property name="endpoint">
  19.                 <ref>endPoint</ref>
  20.             </property>
  21.             <property name="source" value="com.adobe.cairngorm.samples.store.business.CreditCardService"/>
  22.         </object>
  23.     </property>
  24. </object>
  25.  
  26. <object id="shopModelLocator" class="com.adobe.cairngorm.samples.store.model.ShopModelLocator" factory-method="getInstance">
  27.     <property name="creditCardDelegate">
  28.         <object class="com.adobe.cairngorm.samples.store.business.CreditCardDelegate"/>
  29.     </property>
  30.     <property name="productDelegate">
  31.         <object class="com.adobe.cairngorm.samples.store.business.ProductDelegate"/>
  32.     </property>
  33. </object>


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

11 Responses to “Prana enabled Cairngorm Store”

  1. Douglas McCarroll Says:

    Very interesting, Christophe.

    It might make the first example a bit clearer to do it thus:

    In GetProductsCommand:

    We say this:

    var delegate:IProductDelegate = ShopModelLocator.getInstance().productDelegate;
    delegate.responder = this;
    delegate.getProducts();

    Rather than this:

    var delegate : ProductDelegateMock = new ProductDelegateMock( this );
    delegate.getProducts();

    Also, a few words on why Inversion of Control makes it easier to write and maintain code might be a useful addition. At first glance people unfamiliar with this pattern might say, “What’s the payoff?”

    Or, you could just link to http://en.wikipedia.org/wiki/Inversion_of_control. It’s got a nice succinct section on advantages and disadvantages.

    On second thought, I guess I just did. :)

  2. Hagen Aedtner Says:

    Hi Christophe,

    i’ve connection problems to your svn. Could you add a download link here? Thanks Hagen

  3. Christophe Says:

    Hi Hagen,

    please see the nightly builds at http://prana.herrodius.com/

    regards,
    Christophe

  4. Roberto Says:

    Hi!
    Doesn’t this cause a concurrencty isssue?

    var delegate:IProductDelegate = ShopModelLocator.getInstance().productDelegate;
    delegate.responder = this;
    delegate.getProducts();

    If the user is hyperactive and clicks on several buttons calling the product delegate he will overwrite the responder property, causing some actions not to be executed properly!

  5. Christophe Says:

    Hi Roberto,

    that would indeed be a problem. This approach hence needs to be used when you can make sure only 1 call to the delegate will be made, for instance by disabling the UI until the response is received.

    The best thing would be to have a delegate factory that is configured and stored in the modellocator and is then used inside the command to create a new delegate every time you need one.

  6. Roberto Says:

    Blocking the user interface is as you know against the principle of a remote application so I do think that an other approach must be taken.

    What is not clear to me using cairngorm/prana is which objects are meant to be reused and which one are not. In order to keep performance to the maximum, I guess that it would be nice to have the command and business delegates as singletones (this is btw coherent with the patterns used in spring). They do not need to keep any state. Besides, defining more than one method on a business delegate will need to set, through a property or through constructor, a lot of delegates. In my opinion is much simpler to accept a responder as argument of the business delegate call (altough it clutters the interface). It will solve all the concurrency problems and make more explicit how the result will be handled.

  7. Christophe Says:

    Hi Roberto,

    it depends on what you see as blocking the UI. If you are firing a remote call that will load a big chunk of data, then I think it is perfectly acceptable to show a loading screen which informs the user and at the same time prevents the UI from being used.

    About object reusability: I’m not sure if we should see commands and delegates as singletons. As you say, you would have to alter the interfaces so that responders can be passed in to the delegate methods. I think that a event/command/delegate sequence should really be handled by some sort of a factory mechanism that creates a new command and delegate each time. I don’t think performance will be an issue here. That way the concurrency problems would also be solved.

    I like discussing this with you (and others). Would you mind subscribing to the mailinglist – if you haven’t already – so we can also get input from other developers? Thx for your time and interest! https://lists.sourceforge.net/mailman/listinfo/prana-user

  8. Roberto Says:

    You are right, I’ll move to the mailing list!

  9. Dennis Says:

    Changes with AbstractRemoteObjectDelegate seem to corupt this project.

  10. Karthik Says:

    Hi,
    I’m using Prana framework with Flex application(Flex Builder3). I have problem but its not consisitant, service object is null sometimes.

    service = CairngormServiceLocator.getInstance().getRemoteObject(“bgwpmMetadateService”);
    and my xml

    Any idea to solve this issue?

    Thanks,
    karthik

  11. Christophe Says:

    Hi Karthik,

    the xml seems the have disappeared, so I have no idea what is going on. Please join our forum at http://forum.springframework.org/forumdisplay.php?f=60 and repost your question there.

    thx,
    Christophe

Leave a Reply

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in