hibernate4gwt
http://hibernate4gwt.sourceforge.net
hosted by
SourceForge.net Logo
| Home | News | Getting started | OverviewHibernate-GWT issues | FAQ | Thanks |

Overview

Introduction

This page describes the basic concepts used by hibernate4gwt to handle Hibernate beans and send them outside the JVM, to the GWT client side. 

Note that you do not need to have a complete understanding of how hibernate4gwt works to use it and the "Getting started" section is sufficient to use it.

Clone and merge operations

To work properly with Hibernate beans, GWT needs them to be  real POJO, ie without any instrumented class and basic collection implementations. Removing proxies and replacing persistent collections is the job of the clone operation.
Symetrically, Hibernate needs associations to be set with proxies when property was not loaded, and persistence information on collections (for dirty state checking and so on...). Rebuild such instrumented and persistent beans is the goal of the merge operation.

Lazy Properties

hibernate4gwt needs to store persistent informations (such as proxies and collections) in order to rebuild the bean properly during the merge operation.

Such informations can be stored in two ways : 

  • in the entity bean : that's the goal of the LazyPojo abstract class. It handles a list of properties that have not been set by Hibernate (the famous proxies). Because the persistence information is hold by the entity, the merge operation can be run on any server, that's why we call this mode stateless
  • on the server (HTTPSession, in-memory hashmap, ...) : in this case, the whole object graph is kept by the server and modifications made on the client side are just reported on it. In this case, only the server that stores such persistence information can perform the merge operation (stateful mode)
The "POJO store" concept is used to implement such storage strategy.

Proxy generation

In some case, none of the two solutions presented above are accpetable : no technical inhéritance is allowed, and the server must remain purely stateless.
In order to solved such an issue, the library supports the dynamic proxy mode, which is an extension to the stateless mode. The only difference is that the LazyPojo inheritance is just needed. By using GWT generator for client-side and Javassist on the server one, a symetric proxy is created to handle persistence information by adding the ILazyPojo implementation.

In order to make GWT generator work, the model POJO must implement the java.io.Serializable interface. This one acts as a marker for the Proxy generator.

Hibernate Bean Manager

The HibernateBeanManager class is the heart of the library. It is based on a “Lazy killer” class and a “POJO store” (see above).

The LazyKiller class removes Hibernate proxies, convert persistent collections to their regular counterparts and store lazy properties information for the merge operation.

HibernateRemoteService

On the top of all this, the HibernateRemoteService handles the underlying mechanisms and provides the following methods:

  • clone(Object hibernatePojo)
  • merge(Object gwtPojo)
  • remove(Object gwtPojo)
It allows you to send the Hibernate query result to the GWT and sent modifications back to the persistance layer.

HibernateRemoteService

The HibernateRemoteService overrides the GWT RemoteServiceServlet to seamlessly clone and merge Hibernate POJO before and after method invocation.

Basically, HibernateRemoteService overrides the processCall method like this :

Service class, for example as following :

public String processCall(String payload) throws SerializationException
{       
// Decode request
//
RPCRequest rpcRequest = RPCCopy.getInstance().decodeRequest(payload, this.getClass(), this);

// Merge input parameter
//
if ((rpcRequest != null) &&
(rpcRequest.getParameters() != null))
{
Object[] parameters = rpcRequest.getParameters();
for (int index = 0 ; index < parameters.length; index ++)
{
if (parameters[index] != null)
{
parameters[index] = _beanManager.merge(parameters[index], true);
}
}
}
//  Invoke method
//
Object returnValue = RPC.invoke(this, rpcRequest.getMethod(),
rpcRequest.getParameters(),
rpcRequest.getSerializationPolicy());
 
// Clone result
//
if (returnValue != null)
{
returnValue = _beanManager.clone(returnValue, true); 
}
//    Encode response
// 
return RPC.encodeResponseForSuccess(rpcRequest.getMethod(),
returnValue,
rpcRequest.getSerializationPolicy());
}

Of course, the inheritance on HibernateRemoteService is not mandatory: you can use the HibernateLazyManager by yourself… In this case, you would have to explictly clone and merge Hibernate beans by yourself (as it is the case in GWT1.4-Java5 support mode)

Class Mapper

The class mapper is used to for cloning and merging from one Domain class to a different one (Java5 class to DTO, or proxy class to Domain)

hibernate4gwt currently handles different "class mapping" strategies via the DirectoryClassMapper or ExplicitClassMapper implementations : they generally translate the Domain class name to DTO class name by replacing package name and add a DTO suffix if declared.

For particular needs, you can implement your own IClassMapper class, with custom class mapping strategy.

Copyright 2007. All Rights Reserved
 Last updated : 06 August 2007