SQL Zone is brought to you in partnership with:

Shashank has posted 2 posts at DZone. View Full User Profile

Effectively combining Flex and Hibernate: The basics

03.29.2010
| 29590 views |
  • submit to reddit

Flex and Java can be combined effectively to create robust and scalable rich internet applications. Flex enables the creation of an interactive and engaging user interface. Java provides a robust platform for a number of server centric features including data persistence, interaction with disparate systems, compute intensive algorithmic manipulation and integration with the underlying devices and network resources.

If you are a Java programmer and work with data centric applications you are likely to be very familiar with databases, especially relational databases. A majority of modern-day applications store persistent data in popular data storage engines like databases, most of which are relational in nature. The relational databases may not be the most popular option in future though. The advent of NoSQL and BigTable style datastores is posing a challenge to its ubiquitous supremacy.

Relational databases store entities in tables and establish inter-relationship among tables through referential constraints. Java, on the other hand, is an object-oriented programming language and as such applications built using it, model domain entities as objects. Objects encapsulate data and behavior together and provide the familiar real-world semantics to interact with it.

The world of objects and the world of relational entities view the same context from different perspectives, so mismatches exist between them. I will illustrate a select few problems related to this mismatch in this article. However, indulging in a thorough discussion on this topic here is out of scope.

While I wouldn’t explain much about object relational mismatch, I can certainly state that the most widely accepted solution to the problem comes from the breed of tools classified under the Object Relational Mapping (ORM) category. Such tools reduce the impedance to the flow and data interchange between the object and the tabular formats. However, ORM tools aren’t the only forms of bridges between the object and relational worlds. Alternatives like the use of the 1“active record” pattern is also a viable option. Hibernate is a popular open source Java-based ORM solution.

Hibernate forms the basis for the Java Persistence API, which is standard persistence architecture for enterprise Java applications.  Hibernate’s position in a typical Java EE stack is clearly understood but its place in an application with a Flex front-end and a Java server-side is not always that clear. Opinions on its usability range from it being the critical persistence layer to an extraneous layer of disintermediation. While I don’t explicitly take either stand, I hope that after reading this article, you will be able to decide for yourself the pros and cons of including it.

Flex applications are programmed in ActionScript 3 (AS3) and MXML, the declarative language which translates to AS3. AS3, like Java, is an object-oriented language. Therefore, the object/relational impedance mismatch becomes relevant in Flex applications as well, although Flex applications almost never access databases directly. Flex applications connect to data stores through a Java middle tier where most of the bridging between the two worlds of objects and relational data is the responsibility of the Java layer. Therefore, Flex applications, with a Java middle tier or service layer, can leverage Hibernate as an ORM solution. When Flex domain objects closely model Java model objects the mappings stay relevant from the ORM to the user interface layer. Combining Flex and Hibernate then provides great advantages in terms of reuse, scalability and effective persistence. Combining effectively isn’t always trivial though, it has its own set of challenges. You will learn about a few of these challenges and their possible solutions in this article.

With that said, let’s explore a few things about object relational mismatch, the very reason for Hibernate’s existence.

Object Relational Mismatch

To understand where and how the mismatches arise, let’s look at a few examples. Say you decide to build an application to catalog all the published computer books. You then need information on the published books, authors who wrote those books and companies that published the books. In addition, you need to establish the appropriate relationships among these three entities: books, authors and publishers.

The first mismatch that arises pertains to the granularity of the entity definitions.

Coarse-grained versus Fine-grained

Specifically, let’s consider the publisher. A publisher is likely to have a name and contact information, which could include a physical address, a phone number, a fax number and an email address. Using object oriented principles one could model a publisher as follows:

public class Publisher
{
private int publisherId;
private String name;
private ContactInfo contactInfo;

//accessor methods
}

public class ContactInfo
{
private Address address;
private String phone;
private String fax;
private String email;

//accessor methods
}

public class Address
{
private String street;
private String unit;
private String city;
private String state;
private int zip;

//accessor methods

}

 

The same publisher data in the database could be persisted in a single de-normalized table for optimal read and write operations. The DDL for such a table could be as follows:

create table publishers (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(100),
street VARCHAR(75),
unit VARCHAR(75),
city VARCHAR(75),
state VARCHAR(75),
zip INT,
phone VARCHAR(75),
fax VARCHAR(75),
email VARCHAR(75)
);
 

One of the motivations for keeping such data de-normalized is that the structure then lends itself to efficient querying. Selecting data kept in different tables connected through relations imposes the overhead of joins, which you would preferably avoid as much as you can.

Objects thus have a concept of coarse and fine-grained definitions but the world of tables doesn’t have a parallel. The concept of granularity can be at best be implemented in tables using the concept user defined data types. However, custom types or user-defined types are not supported by all databases and certainly not portable across them.

Apart from granularity, the other big issues relate to the absence of object-oriented concepts of inheritance and polymorphism in the relational world.

Inheritance and Polymorphism

Consider the author this time. Say an author’s name could be his or her real name or a pseudo or pen name. In the world of objects, one could represent this as a AuthorName type and have RealName and PenName as two specific types that extend from it. Then one could define behavior and attributes based on specific subtype and therefore include polymorphic aspects to this relationship.

In tables though, there is no concept of inheritance or polymorphism. Inheritance would imply the concept of super and sub tables, which doesn’t exist. Even though views could create a sense of hierarchy among tables, it doesn’t really represent the concept of types or sub-types. Besides inheritance, polymorphism isn’t easy to implement either. In polymorphic relations, one of would need to simultaneously establish foreign key constraints on all relevant sub-types. This is typically only possible with the help of stored procedures, which again pose challenges of applicability and portability across databases.

The next big disconnect arises in the case of many-to-many relationships.

Many-to-many relationships

This time lets take into account the relationship between authors and books. An author can write more than one book and a single book can be the work of collaboration of multiple authors. In the world of objects, things don’t change much whether the relationship is one-to-one, one-to-many or many-to-many. For example, a one-to-one relationship between Author and Book would be as follows:

class Author
{
private Book aBook;
//getters and setters for the aBook attribute
//other attributes and methods
}

class Book
{
private Author anAuthor;
//getters and setters for the anAuthor attribute
//other attributes and methods
}

 

A many-to-many relationship between Author and Book would mean changing from a single entity to a collection. The Author and Book class could then be as follows:

class Author
{
private Set<Book> books;
//getters and setters for the books attribute
//other attributes and methods
}

class Book
{
private Set<Author> authors;
//getters and setters for the authors attribute
//other attributes and methods
}

 

In the relational world though the changes aren’t so easy. Relationships that are one-to-one or one-to-many can be implemented using foreign key constraints but many-to-many relationships ask for creation of a separate table for the purpose. These tables, called mapping or link tables, have no counterparts in the world of objects.

So far we have seen three cases of divergence between the world of objects and the world of relational entities. While the list could go on for sometime, I will restrict it to just one more case and that is of identity.

The concept of Identity

Relational tables identify each entity as a row in the table. Each row typically is uniquely identified using a primary key. In objects though things are not that clear. Objects can have two different ways of looking at identity. Two objects pointing to the same object reference could be considered equal. At the same time equality could be established if two objects matched each other in terms of the values of its attributes.

The question then is how do you map the different types identities and create a common sense of uniqueness? Hibernate and other ORM tools take care of this. Hibernate also bridges the gaps I mentioned earlier.

Having seen a few discrepancies between the world of objects and relational databases, lets see Hibernate smoothens things out for us.

Hibernate basics

To start talking about Flex and Hibernate integration, lets prepare ourselves by looking together at a few essential concepts and ways of Hibernate. This isn’t an introduction to Hibernate. If you want to first get to a basic tutorial on Hibernate, I would recommend you browse to www.hibernate.org and read through the first few tutorials available on that site.

At this stage it might be a good idea to download a copy of Hibernate Core from www.hibernate.org. At the time of writing this article, the latest stable version is version 3.3.2.GA. Hibernate consists of a suit of products that extend the core ORM features to include Java 5 annotation support, entity manager support for JPA, validation and search, among others. For the purposes of this article, you only need Hibernate Core.

Hibernate expects its entities to be Plain Old Java Objects (POJOs). The only requirement is that the POJOs define a no argument constructor and define getters and setters for its private attributes. The no argument constructor is used to instantiate Hibernate entities using Java reflection.

Once you define a Hibernate entity object, you need to tell hibernate how the entity maps to a table in your database. In addition, you also need to configure Hibernate to connect to the database so that it can persist objects. As much as you need to store objects, you also need to query objects. Hibernate allows for exhaustive querying mechanisms to select individual or collection of entities.

If you were to use Hibernate to persist the Author object from the computer book catalog application that I intend to use through this article, you would first define a mapping file to tell hibernate how this Author object relates to the corresponding tables in the database. The Author class is as follows:

class Author
{
public Author()
{
}
private int authorId;
private String name;
private String email;
//getters and setters for the attributes
}

 

The corresponding table (represented here using its DDL) is as follows:

create table authors (
author_id INT NOT NULL PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(75)
);

 

Mapping files in hibernate follow a standard naming convention. A mapping file for the entity Author would be Author.hbm.xml. You can use an alternative naming convention but if you do so make sure to configure Hibernate appropriately for it. The contents of Author.hbm.xml is as follows:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Author" table="authors">
<id name="authorId" column="author_id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="email" />
</class>
</hibernate-mapping>

 

This is an extremely simple example of mapping but complex relationships can easily be depicted in these files as well.  In addition, you could use annotations instead of these mapping files to achieve the same goal.

Once you have defined the Author, Book and Publisher classes, their underlying tables and established the relationships using the Hibernate mapping files, you are ready to configure Hibernate itself and get it to work. Hibernate can be configured via hibernate.properties or hibernate.cfg.xml. You can also programmatically configure Hibernate, if that’s what you prefer.

I will configure Hibernate using hibernate.cfg.xml. The hibernate.cfg.xml in our specific case is as follows:

<?xml version=’1.0’ encoding=’utf-8’?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>

<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/
book_catalog</property>
<property name="connection.username">root</property>
<property name="connection.password">specify the password here</property>

<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>

<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>

<!-- Enable Hibernate’s automatic session context management -->
<property name="current_session_context_class">thread</property>

<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.
NoCacheProvider</property>

<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>

<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping resource="Author.hbm.xml"/>
<mapping resource="Book.hbm.xml"/>
<mapping resource="Publisher.hbm.xml"/>

</session-factory>
</hibernate-configuration>

 

You will notice that MySQL is in use and Hibernate has been configured to show all the underlying SQL it generates and runs on our behalf. Once the resources are configured, you can load and store entities.

Hibernate transactions that involve loading and storing of objects involve the concept of a session. A static SessionFactory class in Hibernate can be used to instantiate a session. A session can then be used to start a transaction and load and store objects. Its usually a good idea to create a utility to provide access to a configured SessionFactory instance. You could do this by creating a utility class called HibernateUtil, which could be as follows:

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

private static final SessionFactory sessionFactory = buildSessionFactory();

private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
return new Configuration().configure().buildSessionFactory();
}
catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}

}
 

Its assumed you have the Hibernate Core jar installed and added to your classpath for the above class to compile. At this stage you can load and store objects. If you had to write code to store a new Author entity, whose name and email was known to you, you could potentially do the following:

import org.hibernate.Session;
import java.util.*;
import somepackage.Author;
import org.hibernate.tutorial.util.HibernateUtil;

public class AuthorManager {

public static void main(String[] args) {
AuthorManager mgr = new AuthorManager();

if (args[0].equals("store")) {
mgr.createAndStoreAuthor("an author", "author@emailprovider.com");
}
HibernateUtil.getSessionFactory().close();
}

private void createAndStoreEvent(String name, String email) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Author anAuthor = new Author();
anAuthor.setName(name);
anAuthor.setEmail(email);
session.save(anAuthor);
session.getTransaction().commit();
}
}

 

While a discussion on Hibernate could go on for much longer I will stop right here. If you need to learn more about Hibernate, which you will need to if you are a newbie, then its worthwhile for you to read through the Hibernate tutorials that I pointed to earlier in this article.

Next, I illustrate how Flex and Hibernate can be used together.

Integrating Flex and Hibernate

The first essential component needed to integrate Flex and Hibernate is a remoting intermediary that would facilitate the exchange of objects from Java to AS3 and back, translating them appropriately as it moves across the wire. This means if you are a fan of loose coupling via JSON or XML data interchange over REST based endpoints then true Flex and Hibernate integration wouldn’t play well with your preferences.

There are a number of commercial and open source remoting libraries available for the Java platform, prominent among them are:

  • LifeCycle Data Services (LCDS) – commercial product from Adobe
  • BlazeDS – open source alternative to LCDS from Adobe
  • GraniteDS – open source remoting library
  • WebORB – another open source remoting library

LCDS is a great choice for Flex and Hibernate integration as it’s a powerful scalable product that includes a robust Hibernate Assembler to provide support for most desired features including the following:

  • Lazy loading
  • Incremental updating
  • Adherence to standard JPA and Hibernate semantics
  • Non-invasive value addition

 However, LCDS is commercial software and you need to procure a license for the product to use it in a large production environment. An alternative to LCDS is BlazeDS, its open source alternative. BlazeDS provides the same benefits as LCDS as far support for remoting goes but it does not include a built-in adapter for Hibernate. That’s not the end of the road though as a few open source adapter for Hibernate are available for BlazeDS. In this article, I take up one such adapter with BlazeDS and use it to illustrate the case of effective Flex and Hibernate integration. This would allow you to easily download the pieces of software and play with it after you read this article. (You can also download and play with LCDS for experimentation).

The naïve integration pattern

 A number of developers approach the Flex and Hibernate integration problem with a service layer in mind. What they plan for is a Java service layer that sits on top of the Hibernate layer to interact with the Hibernate objects.  The service layer in turn pushes the objects, or worse off its alternative representations, to the Flex client.

When a service layer as described in involved the benefits of Hibernate, especially lazy loading are compromised. Either all data set is loaded proactively or all the logic of managing the lazy loading is managed via explicit markers and references somewhere in the service layer.

In some situations the service layer classes become the Flex remoting endpoints and are configured as such with BlazeDS or other remoting products. With BlazeDS, this means the default JavaAdapter mean’t to exchange POJOs with AS3 counterparts handles the Hibernate entities. The JavaAdapter is unaware that a specific POJO is a Hibernate entity so it does not apply any special rules while marshaling them across the wire. Hibernate returns persistent entities and their collections with built-in proxy, which as its name suggests sits in place of the real data. The proxy helps lazily load data sets and provides for efficient management of entities and their collections. These entities and their collections lie within a JVM. When you integrate these persistence layers into a Flex application, you expose these entities and their collections to a language and environment beyond what they are scoped for.

The POJOs when intercepted by the serializer are converted from Java objects to AMF representations before they are sent across the wire. When these AMF representations reach the Flash Player they are reconstructed into AS3 objects. During serialization from Java to AMF, the serializer eagerly fetches all the Hibernate persistent objects and sends them across the wire. The Hibernate proxies are replaced with the data that they stand in place of. This breaks the lazy loading semantics, rendering the idea of proxies useless. Therefore a special adapter for Hibernate is required.

 

Clone and Merge Transfer Pattern

‘‘Clone and Merge Transfer Pattern’’ is a common design pattern involved in creating an ideal Hibernate adapter. It preserves the proxy characteristics of Hibernate entities and their collections while keeping the standard behavior of the essential serialization and de-serialization mechanism between Flex and Java intact. Diagram 1 shows the “Clone and Merge Transfer Pattern” pictorially.

 

Diagram 1: Clone and Merge Transfer Pattern

 

The main idioms in this pattern are the clone and merge operations. On the way from the Java server side to the Flex client, a persistent object with proxy-based references is cloned, and the clone is sent to the serializer-deserializer, which in turn converts it into an AS3 object. This object reaches the Flex client. In the reverse direction, an AS3 object, after being converted to Java, is merged back to the original persistent object. One important requirement for the merge operation to work successfully is that you keep a copy of the original object when it’s cloned. This copy can be maintained on the server or within the class locally.

When the copy of the object is stored on the server, the HTTP session seems like the best place for it. Keeping an application scoped and shared areas may make the object visible beyond its legitimate owners.

When the copy is maintained locally, you need to have a structure within the class for it. This is where you require entities to extend specific classes that accommodate for this structure. One could leverage

Aspect-Oriented Programming (AOP) to induce such behavior at runtime and keep persistent objects from extending a specific class or have them adhere to a specific API.

With that said, let’s look at one such open source adapter that can be leveraged for effective integration of Flex and Hibernate. The one I choose for this article is called Gilead.

Using Gilead

Gilead, as a project existed as ‘‘hibernate4gwt’’ for a while. From late 2008, it has included adapters for both GWT and BlazeDS (for Flex). To explore Gilead-specific features, let’s download and configure the adapter. To download the latest Gilead build, go to the project’s site on SourceForge. You can also navigate to this website form the Gilead home page, which points to http://noon.gilead.free.fr/gilead.

The latest stable release of Gilead, at the time of writing this article, is version 1.3.0.1169.

In order to use Gilead add its blazeds related jars to the classpath of your Flex and Java application. When using Flash Builder, opt for the joint Java/Flex project and point to the blazeds.war file as the Flex WAR file. Copy the Gilead Flex BlazeDS Hibernate adapter jar files to the WEB-INF/lib folder.

Then configure the adapter in remoting-config.xml as follows:

<adapters>
<adapter-definition id="persistent-adapter"
class="net.sf.gilead.blazeds.adapter.PersistentAdapter" >
<properties>
<persistence-factory>
<class>net.sf.gilead.sample.server.ApplicationContext</class>
<singleton>true</singleton>
<method>getSessionFactory</method>
</persistence-factory>
</properties>
</adapter-definition>
</adapters>

 

Gilead also has a PersistentMessagingAdapter that extends the ActionScriptAdapter, a messaging adapter.

The persistence adapter needs to get hold of a Hibernate session during the course of its operations. Hibernate sessions are created using a session factory, as shown earlier in this example. The preceding adapter configuration shows one way to specify the session factory. Within the persistence-factory property the following elements are specified:

  • singleton — A Boolean flag, which when true, appends a call to getInstance() before a call to the factory method is made
  • method — The factory method that instantiates or returns an existing session instance

 

Alternatively, within Java EE environments you could leverage JNDI. Gilead also supports JPA and allows for the additional elements for configuring the entity manager. First, you create the entities on the server side.

Once Gilead is configured you are ready to use it. The next step in to create your server side entities. The server side entities could be POJOs as shown earlier. When you want to restrict persistent objects to Java bean–style POJOs only, you need to either save a copy of the class on the server before it’s cloned or use the dynamic proxy, available in Gilead. Gilead uses the HTTP session to save the object copy when you choose to go with a server-centric stateful way of saving this information. This could pose scalability challenges as increasing number of entities are saved in the session.

An alternative to storing persistent objects in the session or using dynamic proxies, is to save a copy in the class itself. This requires persistent Hibernate entities to extend specific classes, which according to purists imposes unnatural contracts on the POJOs. When using this option the persist entity needs to extend Gilead’s LightEntity as follows:

import net.sf.gilead.pojo.java5.LightEntity;

class Author extends LightEntity implements Serializable
{
public Author()
{
}
//private static final long serialVersionUID = <generate one>;

private int authorId;
private String name;
private String email;
//getters and setters for the attributes
}

 

For Gilead’s LightEntity to be recognizable on the Flex client, you need to extend the corresponding AS3 object with Gilead’s client side LightEntity class, which is as follows:

package
{
import net.sf.gilead.pojo.actionscript.LightEntity;
[RemoteClass(alias="Author")]
[Managed]
public class Author extends LightEntity
{
public int authorId;
public String name;
public String email;
}
}

 

At this point, we could go on to create the entire application and see Gilead in use but I would leave that for a later exercise. The basic concepts are established and that is what we had set out to understand.

Conclusion

Although this article touches a number of different topics, I hope you are well grounded in the fundamentals of effective Flex and Hibernate integration. Using Flex and Hibernate together has its advantages and could be a way to achieve effective persistence in Rich Internet Applications (RIA). While commercial products like LCDS have robust built-in solutions to make Flex and Hibernate work together, options like BlazeDS could be combined with open source adapters for it to achieve the same. Gilead is one such option. Another exists in dpHibernate  and yet another is in the making and accessible at http://code.google.com/p/dsadapters/.

Besides, the style of integration depicted in this article, there is additional scope of creating managed data managers and client side entity managers for ORM and server agnostic semantics. That could possibly be a topic for a following discussion.

Also, lazy loading has its advantages especially when a network of objects is accessed but remember that it imposes more round tripping the server for population of the proxy objects with their real counterparts. Therefore it is advisable that you leverage lazy loading but with prudence and avoid it when you suspect the added benefits are minimal.

I understand many of you desire, more than the fundamentals that this article offers and prefer to have complete working examples. If that is the case, then hold on for a bit, till my new free ebook on Flex and Hibernate becomes available. Keep an eye on www.justflexup.com/flexandhibernate. If you don’t have the patience for it possibly buy my book on BlazeDS: Professional BlazeDS (Wiley, 2009) for some additional details.

 

References

1 Active record pattern -- http://en.wikipedia.org/wiki/Active_record_pattern

 

AttachmentSize
Diagram 1.png51.96 KB
Published at DZone with permission of its author, Shashank Tiwari.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Ryan Gardner replied on Mon, 2010/03/29 - 12:03pm

Why do you feel the need to point to the dsadapters project - which has no code, no releases, no updates, and nothing more than two wiki pages? The article feels well written up until you abruptly finish. You mention gilead, then dump one short example using LightEntity, and then finish. It feels like you still had your pencil on the paper when the teacher called "Ok, time is up" and you then scrambled to finish. Gilead offers stateless / stateful and dynamic modes. (And yes, dynamic they say is experimental) There are a few more issues involved with flex / blazeds remoting that aren't addressed here. For instance, how do you say how much information to send down to the client? How does the client ask for more information when it wants a property that wasn't initially included (lazy loading)? How do you specify which properties or collections should be sent down? Is there an easy way to handle paging of data? One downside to the gilead approach is the specific way it handles creating the objects you are sending down the wire. In your denormalized example, lets assume you have a hibernate entity that is set up using @Embedded properties so when is loaded from the database you get an entity with the address, phone numbers, etc (say 20 or 30 fields of info) - gilead will include all those properties and send them down since they are already initialized. Lets say you have a set of a few thousand users for a simple directory - you have three screens where their data is displayed - a browse listing showing them all sorted by name (or something else), a detail listing where you see all their detail, and a search results page where a user can search and it shows more than the browse listing but not quite as much as the full detailed listing. With any approach, you will have to handle these challenges differently. In gileads case you will design your hibernate queries to load the properties you want and make sure the ones you don't want loaded aren't initialized, so you still have to get nitty gritty. Not horrible, but still has to be done. This is probably one of the best written articles dealing with the topic, but it definitely feels incomplete. What would have been helpful is more focus on the benefits / drawbacks of some of the different approaches. Perhaps a mention of doing this kind of assembly without using a helper adapter but using something like Dozer to help map the entities to DTOs would also be worth considering. The most interesting approach I've seen comes from the GraniteDS camp. Their implementation of remote lazy loading, data paging, etc seems quite compelling. The downside of it is that it's very flex specific and so if you are planning to reuse some of the same nuts-and-bolts to expose your services to other kinds of clients (gwt, web services, etc) you're going to have to end up going with something like gilead anyway - so there are tradeoffs. In any case, great article, just wish it went a few steps beyond the trivial implementation and discussed some of the points that are the actual sticking points when doing a real app using flex remoting.

William Draï replied on Mon, 2010/03/29 - 6:59pm in response to: Ryan Gardner

@Ryan Thanks for mentioning GraniteDS here because combining Flex and Hibernate (and other JPA providers) is one of the main goals of project, but I'd like to clarify a few things, because the GraniteDS approach of handling Hibernate/JPA detached objects is quite different from the existing BlazeDS adapters and also from LCDS.

1. Instead of pre and post-processing the objects before and after AMF serialization, GraniteDS implements a custom AMF serialization that is able to understand the underlying implementation of the JPA provider. This is completely transparent on the server-side, the Java services have absolutely no dependency on GraniteDS and can be used from any other technology. On the contrary this requires client-side support, that's why GraniteDS provides a code generator to generate the AS3 model from the JPA entities (that you would need anyway if you want to keep strong typing in AS3), and a Flex client library that includes ActionScript 3 counterparts for JPA persistent collections and some Java-specific elements like enums. We really think that it's a lot less important to have this (limited) dependency on GraniteDS in the presentation layer than in the service layer.

2. The objects available to the Flex application can be considered as 'real' detached JPA entities, almost exactly as if they had been serialized using Java serialization to a JavaFX client. You can just call EntityManager.merge() on any object received from Flex.

3. As GraniteDS operates at serialization time and understands Hibernate proxies and persistent collections, it does not need to have access to the Hibernate SessionFactory or EntityManager. That means it can work with remote EJB or multi-layer server applications. It is also completely stateless and very performant as it serializes only what is needed to correctly restore the detached state of the objects.

4. GraniteDS supports not only Hibernate but also EclipseLink, OpenJPA and DataNucleus.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.