Accessibility

Flex Article

 

Developing Flex RIAs with Cairngorm microarchitecture – Part 5: Server-side integration


Table of Contents

Comments

Locating services with the Service Locator

When several developers build against the same server-side infrastructure, they run the risk of developing convoluted code sprinkled with identical RemoteObject tags. For example, when a developer realizes he needs to make a call to a Java class, he may place deep within his component a RemoteObject tag pointing at the Java class. Meanwhile, three other developers on the team do exactly the same thing with their components, resulting in code that is difficult to understand and maintain.

The Service Locator pattern addresses this challenge by providing a repository for all services that the RIA requires. Within it, you can centralize and reuse your service tags.

The Service Locator supports each type of data access service. Application developers can fetch their services by using the correct get method (e.g. getRemoteObject), invoke methods on the service, and handle the results however they are shipped over the wire. This process allows each service to be treated in a consistent manner.

Cairngorm provides a base class, ServiceLocator, which is a singleton for service access. In a Cairngorm application, you typically extend this base class through MXML. By convention this is done with a file called Services.mxml in the business package of your application.

Here is an example Services.mxml:

<cairngorm:ServiceLocator
        xmlns:mx="http://www.adobe.com/2006/mxml" 
        xmlns:cairngorm="/2006/cairngorm">
 
    <mx:RemoteObject 
        id="productService" 
        destination="productServiceImpl" 
        showBusyCursor="true">
    </mx:RemoteObject>
 
    <mx:RemoteObject 
        id="creditCardService" 
        destination="creditCardServiceImpl" 
        showBusyCursor="true">
    </mx:RemoteObject>
 
</cairngorm:ServiceLocator>

As you can see, two services are used. You use productService to fetch products from the server-side database. You use creditCardService to validate credit card information on the server before approving orders.

Both services are implemented as destinations. This means that information about the actual Java class is held in the remoting-config.xml descriptor file on the server; it is not exposed in any client-side code. This is a security best practice. It is best not to reveal information such as class names that might give a determined hacker who decompiles the Flex RIA any information about the implementation of your server-side code.

Because the Service Locator expects its services to be used multiple times in many different ways, it makes no assumptions about how to handle any results that are returned. Instead, the Service Locator assumes that the result handler and the fault handler will belong to the class calling the service.

Invoking services on the Service Locator

After declaring services to reside on the Service Locator, you will want to invoke them.

In Cairngorm Store, when the application starts, it executes the GetProductsCommand command to fetch all products from the server-side database. As you may recall, you use the creationComplete event on the main Application tag to fire a GetProductsEvent event, which ensures that the application executes the Command class.

In the above Service Locator, productService is a Java class that has a method called getProducts(). Calling the getProducts() method returns an array list of ProductVO value objects, which represents all the products that the middleware has pulled out of the underlying database.

In the entry-point for Cairngorm Store, Main.mxml, you instantiate your Service Locator as follows:

<business:Services id="services" />

Here the business namespace is declared and specifies the package in which Services.mxml resides: com.adobe.cairngorm.samples.store.business.

Having declared your Service Locator, you could then place the following code into your GetProductsCommand command if you so desired:

public class
GetProductsCommand implements ICommand, IResponder
{
 
   public
function execute( event : CairngormEvent ): void
   {
      var
service:RemoteObject = ServiceLocator.getInstance().getRemoteObject(
"productService" );service.getProducts();
   }
}

In this code, you can see how to use the Service Locator to fetch a Java service by name and then invoke methods on the service. This same approach could also be followed if the service was a web service or an HTTP service.

Now you could refine this code further, so that it specifies the result handler on the Command class as a method belonging to GetProductsCommand. This would allow the Command class to invoke the service and handle the result in the context of the Command class.

While this would be an acceptable solution, there is a final layer of abstraction that the Cairngorm team has found very useful. We recommend using the final pattern that Cairngorm advocates, the Business Delegate pattern, as a starting point for any Cairngorm application.