ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Integrating Macromedia Flex with Java
Pages: 1, 2

Integrating Flex with the Business Layer

Now that we have addressed some presentation layer concerns let's discuss how other layers in our application architecture are affected. We have repositioned our presentation layer components; how do we integrate with our business layer?

Flex is an extensible RIA framework that provides several ways to communicate with your J2EE components. Flex offers HTTP communication, Web service communication, and Macromedia's proprietary AMF (ActionScript Messaging Format) gateway. The AMF gateway is a high-performance binary protocol that is synonymous with the Flash remoting protocol. Remote objects that are sent through the AMF gateway use the HTTP protocol. Flex offers MXML tags for each of these communication protocols, which significantly reduces the coding complexities. Furthermore, Flex allows you to invoke remote calls to your business tier in either an asynchronous or synchronous manner. By using an asynchronous remote call, the user has the ability to perform some action on the client and not be blocked as happens in traditional web applications. You can block the user from interacting with the UI using synchronous calls where appropriate.

Let's consider how Flex might be integrated with our business/integration layer. For this discussion we will use the Spring framework as our integration layer, but there are no restrictions to the integration layer you choose to implement. Let's assume you have your services in objects that operate in a Spring microcontainer, and you need to make remote object calls from Flex.

Since Flex knows nothing about Spring directly you might consider adding a separate, thin layer that acts as a delegate to your service components. Also, since Spring makes good use of Java interfaces it might be a good idea to build delegate objects that implement the same interfaces as your Spring services. These delegate objects will provide a decoupled gateway from Flex to the integration layer. The only thing you need to do is configure these objects in the Flex configuration file so they can interoperate with the AMF gateway. Here is an example of how a delegate object can be configured inside the server-side flex-config.xml Flex configuration file:


<object name="OrderBusinessDelegate">
   <source>
      com.meagle.flexro.FlexBusinessDelegate
   </source>
   <type>stateless-class</type>
   <use-custom-authentication>
      true
   </use-custom-authentication>
   <allow-unnamed-access>
      false
   </allow-unnamed-access>
   <roles>
      <role>OrderUser</role>
      <role>Admin</role>
   </roles>
</object>

At first glance you can see some additional capabilities of Flex such as configuring security and determining if the delegate object is stateful or stateless. When a remote object call is made from Flex to the integration layer it will be intercepted in a Flex delegate Java object. Delegates will be responsible for making the call to the integration, or service, layer (in our case, Spring). Resultant objects are sent back through the AMF gateway to the Flex client where they can be interpreted as ActionScript objects. Here is an example of the MXML code that will be used by the Flex client to make the remote call invocation and store results in a data model:


<mx:RemoteObject id="soapro"
   named="OrderBusinessDelegate"
   protocol="https"
   showBusyCursor="true">
   <mx:method name="saveNewOrder"
              result="saveNewOrder_result(event)"
              fault="faultHandler(event.fault)"/>
   <mx:method name="findOrderById"
              result="findOrderById_result(event)"
              fault="faultHandler(event.fault)"/>
   <mx:method name="updateOrder"
              result="updateOrder_result(event)"
              fault="faultHandler(event.fault)"/>
</mx:RemoteObject>

<mx:Model id="roModel" >
   <!-- The object graph for the Order object
           will be stored here -->
   <Order/>
</mx:Model>

Domain objects written in Java with ActionScript equivalents are passed back and forth through the AMF gateway. This process starts with a request from the Flex client through the AMF gateway to other layers in the application. A resultant object graph will be sent back through the other Java layers and eventually through the AMF gateway back to the client. Once the objects pass through the gateway they are converted back to ActionScript equivalents. Figure 3 shows what this looks like:

Overview of the AMF gateway
Figure 3. Overview of the AMF gateway.

One more note about passing objects back and forth between Flex and your Java tier: Since ActionScript 2.0 is an object-oriented language, it is possible to create ActionScript objects that have Java equivalents. This makes things easier and consistent when passing these objects back and forth over the AMF gateway. The ActionScript objects that are sent back to the Flash plug-in resemble data transfer objects (DTO). This is necessary because the Flash plug-in does not have any Java runtime components. Here is a familiar example of an Order domain object using Java:


package com.meagle.bo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * This object represents an order.
 * @hibernate.class table="TestOrder"
 * @author meagle
 */
public class Order {
   private int id;
   private double total;
   private int version;
   private String userName;
   private List orderLineItems = new ArrayList();

  // other fields and getter/setter methods not
  // shown to save space
}

Here is the ActionScript equivalent:


/**
 * Generated Action Script Object
 * for com.meagle.bo.Order. Do not edit!
 */
class com.meagle.bo.Order extends Object {

   public function Order(){}

   public static var regClass =
      Object.registerClass("com.meagle.bo.Order",
                            com.meagle.bo.Order);

   var id : Number;
   var orderLineItems : Array = new Array();
   var total : Number;
   var userName : String;
   var version : Number;

   // other fields and getter/setter methods not
   //shown to save space
}

You should notice a special method in the ActionScript Order object called Object.registerClass. This Object.registerClass method is used by the AMF gateway to know how to marshal and unmarshal objects between Java and ActionScript. This method registers the client-side ActionScript classes to the server-side Java classes. Since these objects are so similar it is understandable that you would not want to rewrite your domain objects in a slightly different format. Tools such as XDoclet and Ant allow you to generate these ActionScript objects automatically rather than hand code them. Now you can manipulate your Java objects as ActionScript equivalents in the Flex client.

Integrating Flex with the Persistence Layer

In applications that use a well defined decoupled architecture over the Web you do not communicate with your persistence layer directly. Using Flex should not change this architecture. The integration layer typically will communicate to your persistence layer in most cases. This is usually done using a Data Access Object (DAO) that is responsible for accessing data in a persistent store such as a database. The Flex client should not communicate directly to the persistence layer or even know about this layer because it forms a tight coupling. Let's use Hibernate as an example of our persistence layer.

There are a couple of pitfalls when using Hibernate and remote objects with Macromedia's AMF gateway. Hibernate users know you cannot access a lazy loaded collection that has not been initialized with a Hibernate Session object. Accessing a collection of dynamic proxy objects that has not been initialized will result in a runtime exception. The AMF gateway does not know how to specifically look for Hibernate dynamic proxy objects. A potential solution is an aspect-oriented programming (AOP) interceptor that can take the object that is about to be sent over the AMF gateway in the delegate object and remove the dynamic proxies. This process involves sending the resultant object through the interceptor class, which recursively looks for proxy objects that use reflection and that are not initialized. If any lazy proxy objects or collections are found then they are set to null. This is a cross-cutting concern that can be applied as an aspect using an AOP language such as JBoss AOP, AspectJ, Spring AOP, and so on. The AOP interceptor should be applied to objects in the business delegate layer. Figure 4 shows what this looks like in the application architecture:

Introducing AOP interceptors/advice to delegate objects before they pass through the AMF gateway
Figure 4. Introducing AOP interceptors/advice to delegate objects before they pass through the AMF gateway. This further reduces coupling from components in higher layers such as the integration layer, persistence layer, and so on.

The good news is the AMF gateway does know how to cache bidirectional objects so infinite recursion does not occur when transforming the objects. Therefore, you can keep these relationships intact when transmitting them back and forth over the AMF gateway. Also, because the objects are disconnected and made into copies, you will need to use the Session.saveOrUpdateCopy(Object object) method to persist results into the database. This method has to be used because the object that will be sent back through the AMF gateway will not have any enhanced bytecode information that Hibernate can take advantage of.

Authentication

Typical J2EE web applications have some kind of authentication scheme. This might be a container-based authentication scheme or it might be some custom code that authenticates the user. RIA servers such as Flex allow you to use custom authentication forms on the Flash client and container-based authentication in most application servers. Furthermore, if you look at the business delegate configuration in the example above you will notice that you can assign roles to these objects for security. There are even hooks in the AMF gateway that allow developers to grab the HttpRequest, HttpResponse, and ServletConfig objects to refine the security you want to use within a method of a delegate object.

Summary

This article introduced a number of concepts with the intention of exposing you to some of the tradeoffs and potential pitfalls when using a RIA such as Flex. Whether you use Flex or another RIA implementation, there are major considerations to take into account when architecting an application with this technology. When evaluating an RIA framework make sure it is extensible enough to meet the demands of the application. Furthermore, carefully evaluate integration issues that might need attention when transmitting objects between and RIA and a Java backend.

Resources

Mark Eagle is a Senior Software Engineer at MATRIX Resources, Inc. in Atlanta, GA.


Return to ONJava.com