Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


The POJO Container: POJO Clustering at the JVM Level : Page 4

POJO clustering at the JVM level not only provides a simple way for applications to achieve scale-out, but also sets the stage for a stack of enterprise-scale services and practices based on simple POJOs—the POJO container.


WEBINAR: On-Demand

Unleash Your DevOps Strategy by Synchronizing Application and Database Changes REGISTER >

UnitOfWork Pattern Case Study
Let's look now at a real-world use case from a Fortune 50 company as an example of how an application might be designed using the UnitOfWork pattern. A dataset lives in three separate systems of record that must all be reconciled as changes arrive. Each system of record is updated asynchronously, so the reconciliation engine must wait until a change event arrives from each of the three systems of record before the reconciliation begins.

Click to enlarge
Figure 4. Complete Diagram of Example Use Case

The UnitOfWork pattern can be applied to this use case in a number of ways. For this example, the two UnitOfWork types are Change and ChangeSet. Change represents a change event received by one of the systems of record, and ChangeSet represents the three required events from the different systems of record bundled together. The two WorkHandlers are a coordinator and a reconciler. The coordinator determines when all of the change events for a given logical change have arrived from each system of record. When all the change events have arrived, it passes the set of changes to a reconciler that receives ChangeSets and does the actual reconciliation. (See Figure 4 for a complete diagram of the use case). Here is the sample code for the two WorkHandler implementations:

public class Coordinator implements WorkHandler { // The pending map should be configured to be a // clustered Map so all WorkHandler instances see // the same pending ChangeSets. private Map<ChangeID, ChangeSet> pending; private ChangeSetFactory modSetFactory; // ... constructor, etc. public void handleWork(UnitOfWork work) { Change modification = (Change) work; ChangeID modID = modification.getModID(); // Since the pending Map is clustered, this // becomes a clustered synchronization synchronized (this.pending) { ChangeSet mods = getPendingSet(modID); mods.add(modification); if (mods.size()< 3) { this.pending.put(modID, mods); } else { Sink completeSink = mods.routeMe(); completeSink.put(mods); pending.remove(mods); } } private ChangeSet getPendingSet(ChangeID modID) { ChangeSet pendingFor = (ChangeSet) pending.get(modID); if (pendingFor == null) { pendingFor = modSetFactory.newModificationSet(); } return pendingFor; } } public class Reconciler implements WorkHandler { public void handleWork(UnitOfWork work) { ChangeSet mods = (ChangeSet) work; reconcile(mods); } private void reconcile(ChangeSet mods) { // do whatever needs to be done to reconcile // the modifications } }

The master will receive change events from the different systems of record and put them on the queue for the appropriate worker based on the ChangeID. Each worker will have a WorkHandler attached to it. Workers with Coordinator handlers attached to them will receive Change units of work, determine whether or not all the changes have arrived, and either make it pending or forward it on to the Reconciler queue. Workers with Reconciler handlers attached to them will receive complete ChangeSets and do the work of reconciling the Changes found in those ChangeSets. If you make the pending Map of Changes in the Coordinator a clustered map, Change events can be routed blindly to any Coordinator worker and, if any Coordinator worker fails, other Coordinators can pick up where it left off.

In the POJO container, any number of workers can be executed on threads in any number of container instances. Each worker's queue is implemented as a simple library queue (e.g., LinkedBlockingQueue) and clustered using the POJO clustering techniques described earlier. The cluster can be dynamically load balanced such that new container instances can join the cluster on the fly as can the number of Worker threads devoted to each type of work. As a new worker comes online, its work queue is registered in a clustered data structure such that it becomes visible to the Master and ready to receive new work.

Toward the POJO Container
POJO clustering at the JVM level provides a simple, seamless way for applications to achieve scale-out. Clustered heap, object identity, and clustered locking can all be delivered as a service of the virtual machine. A flexible UnitofWork pattern layered on top can deliver consistent and predictable application design that can be tuned for performance without massive refactoring. What emerges is a stack of services and practices based on simple POJOs that exhibit enterprise-scale performance, availability, and control: the POJO container.

Ari Zilka is founder and CEO of Terracotta, a developer of solutions for Java scalability.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date