Migrating Java EE Web Applications to Adobe Flex and Granite Data Services

DZone 's Guide to

Migrating Java EE Web Applications to Adobe Flex and Granite Data Services

· Java Zone ·
Free Resource

One of the original goals of the Granite Data Services project (current version is 1.2.0 GA) was to make easier the migration of existing J2EE applications to Adobe Flex RIA technology. The reference framework used in our applications was rather classical: JSF + EJB + Hibernate.

The easy way was obviously to keep as is the service layer (EJB + Hibernate), working only on the Web layer (JSF) implementation. With Flex server technologies provided by Adobe (LCDS and BlazeDS), it is unlikely that you can keep your service layer as is: LCDS promotes is own concepts of service and persistence, while BlazeDS does not support one the most important feature of JPA engines: lazy-loading.

With GraniteDS, you get full JPA support and you can easily integrate not only with EJB but also with Seam, Spring and even Guice services. Basically, most of the work consists in migrating your JSF managed beans (or Struts beans) and views to the Flex client and GraniteDS will help you a lot with code generation tools and the Tide client framework.

For example, suppose that you have a simple data model like this one:

public class Brand {

@Id @GeneratedValue
private int id;

private String name;

(1) @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="brand")
private Set<Car> contacts = new HashSet<Car>();

// getters/setters...

public class Car {

@Id @GeneratedValue
private int id;

private Brand brand;

private String model;

// getters/setters...

(1) Note the FetchType.LAZY parameter on the cars collection.

Migrating your Web layer to Flex requires that you have an ActionScript3 representation of your entity beans. With the help of the Gas3 code generator (available as an Ant task or an Eclipse builder), this data model is automatically replicated in ActionScript3: by running the generator you'll get a Brand.as and a Car.as classes, whose implementation includes all necessary code required for data serialization from your Java services to your Flex client application and vice-versa (and the necessary lazy loading support implementation).

That's it for your data model, with no limitation in terms of complexity (inheritance, mapped superclass, embedded beans, inner enum declarations, etc.) You just use the code generator in order to mirror your Java model in its ActionScript3 equivalent.

Let's now say you have an EJB session bean with a basic find operation like this one:

public class CarServiceBean implements CarService {

protected EntityManager manager;

public findAllBrands() {
return manager.createQuery("select b from Brand b").getResultList();

With Tide, to access this EJB from within your Flex application, you'll need a Flex services-config.xml configuration file like this one:

<service id="granite-service"
(1) <destination id="ejb">
<channel ref="my-graniteamf"/>
(2) <factory>tideEjbFactory</factory>
(3) <entityManagerFactoryJndiName>java:/DefaultEMF</entityManagerFactoryJndiName>

<factory id="tideEjbFactory" class="org.granite.tide.ejb.EjbServiceFactory">

<!-- skipped channel definition -->

The important parts in this config are:

(1) Only one destination is used and must be named "ejb" (this destination id will be automatically recognized and used by Tide for EJB without any further configuration).

(2) The destination is bound to the tideEjbFactory and this factory will manage to lookup the session bean based on a String pattern where {capitalized.component.name} will be replaced at runtime by the name of the service your are calling in your client code (see MXML code below).

(3) Because Tide must be able to access an EntityManager for transparent lazy-loading operations, you must also provide a valid JNDI name for retrieving an EntityManagerFactory instance.

Finally, we may write a very basic MXML application like this one:

(1) creationComplete="creationComplete()">

import mx.collections.ListCollectionView;

import org.granite.tide.ejb.Ejb;
import org.granite.tide.ejb.Context;
import org.granite.tide.events.TideResultEvent;

private var brands:ListCollectionView;

(2) private var tideContext:Context = Ejb.getInstance().getEjbContext();

(3) function creationComplete():void {

(4) function findResult(event:TideResultEvent):void {
brands = event.result;

<mx:HBox width="100%" height="100%">
(5) <mx:DataGrid id="dgBrands" dataProvider="{brands}"/>

(6) <mx:DataGrid dataProvider="{dgBrands.selectedItem.cars}"/>


(1) When the Flex application is fully initialized, it calls a function named "creationComplete" (see (3)).

(2) Before the above call, the private variable tideContext is assigned with a singleton Context that allows services calls on the "ejb" destination.

(3) Then, the creationComplete function is executed and calls the findAllBrands method on our above CarServiceBean session EJB. The additional parameter is the name of a handler function called when the result will be available (all server calls are asynchronous).

(4) When the result is available, the "brands" variable is assigned with the collection of all brands available in the database. This collection contains instances of the previously generated Brand.as class that replicate corresponding Java entity beans loaded by the EntityManager.

(5) The first DataGrid ("dgBrands") is populated with Brand objets, whose cars collection is uninitialized (remember the the FetchType.LAZY parameter in the Brand Java class).

(6) Whenever you click on a brand in the first DataGrid, the selectedItem property is assigned with the selected Brand. Because the cars collection is accessed in order to populate the second DataGrid, this uninitialized collection is transparently loaded by Tide by issuing a server call with the selected brand: with the help of the EntityManager, the unitialized cars collection is fully loaded and returned to the Tide client context. Then, the second DataGrid is populated with all cars registered for the selected brand.

This quick overview of the GraniteDS framework doesn't give you the big picture of all GraniteDS capabilities: security services for Tomcat, Jetty, GlassFish and (soon) WebLogic servers (with specific implementations for the Spring and Seam frameworks), support of Hibernate, TopLink, EclipseLink and (soon) OpenJPA persistence engines, tight integration with the Seam framework (conversation and bijection support), data paging, injection and outjection in your Tide beans on Flex side (with specific ActionScript3 annotations), etc.

You may see more on Granite Data Services 1.2.0 GA release in GDS forum here.

Comments are welcome!


Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}