Tuesday, December 23, 2008

Convenient Disconnected Mode in your Rich Java Application with Hibernate Offliner

In EL4J, we have recently published the open-source Hibernate Offliner, a lightweight layer above Hibernate that supports 2 modes: online and offline (=disconnected) mode. In the online mode the application works on objects that lie in a remote database and that are served via an application server. In the offline mode, the application works on objects that lie in a local database that runs on the client node. The transitions between online and offline mode are handled almost transparently for the application.
A typical use-case of the Hibernate Offliner is a salesforce-support application that runs both when connected to the application server AND when the sales representative is disconnected from the network.

Under the hood
As in traditional database applications, we use the DAO pattern to abstract details of the database access. When switching from online to offline mode, we use a different DAO instance that uses the local database instead and records deleted objects (currently with an interceptor). A DAO registry (a factory for DAO instances) makes the right DAO selection transparent for the application. In order to make an application offline-capable as transparently as possible, a service-layer can be duplicated in the local application. This avoids that the service-layer needs to be fully aware of the offline-capability. All object-operations are done on the level of Hibernate. This means the Hibernate Offliner adds no dependency to the underlying database brand.

Going offline
When switching between the online and the offline mode, you use a set of hibernate queries to indicate what parts of your data you want to replicate on your local database. From this moment on, all future database accesses go to the local database.

Synchronizing data with the master database & going online again
Once you are reconnected to the application server, the local changes (detected via a newer object id/version pair and the recorded deletes (either delete locally only or delete in master db)) get committed in chunks (for scalability) to the master database. What if someone else has changed a same object instance in parallel (e.g. optimistic locking failures)? When going online again, the Offliner indicates conflicts in a data structure that can then be handled by the application (there is no generic conflict handling approach that works in all cases).

Transparency of the offline-capability for your application
For your application it can be to a large extent transparent that it supports online and offline mode: Data accesses work in exactly the same way, whether your application is offline or not. When you adapt an application to support offlining, it just needs to treat the 2 transitions: “go offline” and “go online” (this includes handling of potential conflicts). These two transitions typically require a few calls to the Offliner that can be nicely separated from the rest of the application. In other words, the concern “offlining” is nicely separated from other concerns.
The 2 pictures "Before" and "After" indicate a possible scenario:







Architecture constraints & open issues
What do you need to take into consideration when using this infrastructure? The following limitations exist:
  • Currently only support for primary keys (PKs) of type int, long and String are implemented. The PKs on entity objects are also used to identify whether they are local or remote: so the PKs of the local and the remote database must be distinct.
  • Between online and offline mode, the application mustn't keep objects (as their PKs change).
  • At the moment, the Hibernate Offliner intercepts DAO-access (for deleted objects) on the EL4J generic DAO infrastructure (this is a convenience support that provides DAO with basic CRUD operations without coding). The core of the Hibernate Offliner is independent of this choice.
  • The Offliner cannot guess missing „incoming“ links (so chose your offlining-queries judiciously). E.g., if you have a person class with a parent pointer and children set (1:n, one-way) and offline only the parent, fetching it from the local database and calling getChildren() will return a (wrong) empty set.
  • Hibernate cascading save and the Offliner may not run efficiently together
Acknowledgments
The bean browser was designed and implemented by David Bernhard, thanks for the good work!

More info
Have a look at the svn head of EL4J under framework/modules/offliner or contact the EL4J team.

Thursday, November 27, 2008

DataExtends to control lazy loading with Hibernate

Who has not suffered from LazyLoadingExceptions with JPA/ Hibernate? Often one uses the open session in view pattern to improve the situation. When sending hibernate-loaded classes over the network, not even this pattern solves the issue.
Thanks to an idea of Michael Vorburger, we have implemented a small abstraction called DataExtent. When loading an object, a DataExtent defines what extent of its "surrounding" object graph we want to load as well.
For this, you 1) define first a data extent, and 2) use it in your findById or findByCriteria methods of the DAO. You would put the often required DataExtents as constants in your DAO, other DataExtents can be defined on the fly.

The following picture illustrates a possible class graph, with different extents we may be interested in:



Sample code:

fileWithoutContentExtent =
new DataExtent(File.class)
.with("name", "lastModified", "fileSize", "mimeType");

fullFileExtent =
new DataExtent(File.class).
with("name", "content", "lastModified", "fileSize", "mimeType");

// The Extent Object of type 'Person'
myExtent = new DataExtent(Person.class);
// Construct a complex graph:
// Person has a List of Teeth, a Tooth has a 'Person' as owner,
// the owner has a list of 'Person' as friends, the friends are again
// the same 'Person'-entity as defined in the beginning.
myExtent.withSubentities(
collection("teeth",
entity(Tooth.class)
.with("owner")
),
collection("friends", myExtent.getRootEntity())
);



Then you can easily control what should be loaded in the DAO (our DAOs are typically a subclass of our generic DAO):
myPerson = myDao.findById(myPk, myExtent); or
myPersonList = myDao.findByCriteria(myCriteria, myExtent);

References:

Monday, September 01, 2008

I just came back from the SOA Security event of ipt and Credit Suisse - unfortunately quite disappointed:
  1. At the door of the event, I was refused entry because I work at a concurrent of ipt (the event runs under "SOA Interest Group"). I have no problem understanding limited access to events, but it should be stated when the event is published - or one should be notified before going there. The event was publicly announced here.
  2. The reservation system (it runs on the web site of ipt) is broken: I reserved myself twice (separated by 3 days), and I did neither get the promised answering email nor an error response (I did not hear from them at all). Later they removed the remark that they promise an answering email - so I figured I could go without confirmation.
  3. It is sad that the bank Credit Suisse, which used to have a good reputation, works with such a dicey partner.
Remark: I just checked their website again: in the mean time, they added some more concrete specification of who can go - they seem to like publishing unfinished stuff...

Tuesday, July 01, 2008

Jazoon 08 & EL4J 1.4

After a long silence due to intensive times, I am glad to announce 2 things:
  • We have released the version 1.4 of EL4J. Improvements include: more convenience methods for database access, new support to layout Swing GUIs in XML (similar to XAML), many maven improvements, jconsole can now connect by default to EL4J applications, clean-ups, ... . For a complete list of features, please consult the release notes.

Thursday, March 06, 2008

EL4J release 1.3 is out!

We are glad to announce the new el4j release!

Main features: New JSF application template based on Seam and Facelets (no need for EJB 3), simplified database access (less config duplication, more auto detection, more query possibilities), streamlined multi-environment support (make the same properties easily available in both maven (build and launch time) and Spring (run-time)), demo for single-jar deployment, new trouble-shooting guide (it helps with frequent issues that happen when you work with the technologies included in EL4J), improved doc, recursive maven builds (maven rec: as maven knows your dependencies it can now build your project and the projects it depends on automatically), clean-ups, ....

Full release notes: http://el4j.svn.sourceforge.net/viewvc/*checkout*/el4j/trunk/el4j/etc/ReleaseNotes.txt
SF.net site: http://el4j.sourceforge.net/index.html