ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Using Jini to Build a Catastrophe-Resistant System
Pages: 1, 2

Rio goes a long way towards eliminating any single points of failure from the system, but our reliance on a JavaSpace just introduced such a problem again. Various strategies were discussed at Discovery 01, and the model we chose reflects those discussions. We built a simple, space federator JSB called Kirk whose job it is to keep two spaces in sync.



Like any good application, COS applications can be started, stopped, and removed from the environment, upgraded, and redeployed without interfering with other running applications.

This is essential for production systems and perfect for concurrency in development environments where many developers wish to run overlapping versions of the same code.

COS applications provide 100% continuity of service based on the contiguity of services running in the ensemble. A contiguous component can start and stop, and resume operation from exactly where it left off. This type of service creates a situation where each and any service can be taken off-line, upgraded, and restarted with nothing more than a performance degradation to active applications.


Diagram.

COS applications are specified as using an XML file that holds a named ServiceEnsemble and a Rio operational string.

An example service ensemble is presented here.


Listing 1. COS service ensemble.

<ServiceEnsemble name="ArchiveEnsemble">
  <ServiceMode id="KarenArchiveCreate"
               service="Karen"
               param="archive"
               context="create">
  </ServiceMode>

  <ServiceMode id="KirkReplicateCreate"
               service="Kirk"
               param="replicate"
               context="create">
  </ServiceMode>
</ServiceEnsemble>

This describes two service modes, KarenArchiveCreate and KirkReplicateCreate. This, in effect, tells the distribution service that for this named application, whenever an entry is created, issue a service flag for Karen (an Archivist service that talks to a JDBC database) to read the entry from the space and run the entry's archive() method. Also, issue a flag that instructs Kirk (a space federator that keeps two spaces in sync) to replicate that object in Kirk's replication space. Both services only involve a read of the entry from the space, and so can run asynchronously.

COS also allows you to specify dependencies between service runs. This is useful when one service depends on the result of another; in this case, the service distribution model is extended to message-dependent services in the ensemble on the completion of all its dependencies.

COS provides a clean interface, CosConnectable, that enforces the methods used by third-party code (i.e., the Crudlet taglib) to access any named service ensemble. It maps closely to the original Crudlet specification itself, with create, retrieve, update, delete, lifecycle, and exists methods. There was no need for a T (template), however; instead, we have added a notifyEvent() method that allows client apps to listen for remote events from the space.

The facilities for adding and removing lifecycle events, which are new to the COS system, were an idea that never really worked in the original Crudlet code.

Lifecycle events provide persistent, guaranteed service ensemble events that are not executed immediately on delegation to the COS. They are instead submitted along with a trigger condition object, which determines when and how often the ensemble event should be executed. These events are placed into the COS as service ensemble events when a matching trigger event arrives in the space.

Triggers, created by factory methods, can be of two varieties:

  • Once only. Once a trigger event is received, and the ensemble event is executed, the lifecycle event is removed from the pending list -- i.e., once-only execution.
  • Repeated. This type of lifecycle event will issue the ensemble event to be executed every time a matching trigger is received.

COS provides Ben, a reference implementation of a service that spits time triggers into the space. These can be consumed, and time-triggerable events can be deployed, much in the manner of a Unix cron system. Indeed, cron is a key component in a good operating system.

The state of the lifecycle service is stored in the JavaSpace, allowing multiple competing instances of the lifecycle service in scalable designs.

There is a full discussion of the COS event model on the Pronoic Web site.

Crudlet's role in all of this is simply as an XML transformation mechanism, to provide some patterns used to provide Web interfaces, and perhaps to transform incoming data. It is really just a taglib that acts as a client of the COS, in this context. Matching JDP taglibs are trivial to develop.

The COS provides reference implementations of Jini Service Beans to handle JDBC archiving (Karen), scheduling (Robin), watchmaking (Ben), distributing (Max), space federation (Kirk), cleaning/garbage-collection (Otto), and http-posting (Roger). It also provides a suite of tests and utilities.

It provides a ClientAppInterface that enforces connect(), disconnect(), and isConnected() methods, and an AbstractClientApp that provides default implementations of those methods. As such, connecting to the COS is trivially easy for a client.

A simple CosClientApp would connect like this:

public class SimpleClient extents AbstractClientApp {

	static public void main(String[] args) 
	{
		
        System.setSecurityManager(new java.rmi.RMISecurityManager());

		ClientApp app = new ClientApp();

		try {
			app.setConfigInfo(Config.getInputStreamFromURL(args[0]));
		} catch (IOException ie) {
			Messenger.fatal("IO exception while parsing arguments.);
		}

		try {
			app.connect("someusername","somepassword");
		} catch (GeneralCosException e) {
			String msg = "A general cos exception was thrown"
				+" during initialisation."
				+" Message = \""
				+e.getMessage()+"\"";
		}
	}
}

Internal to the app/JSP/XSP page you can use app.getCosConnector() to return a CosConnectable that you use to interact with the COS.

The methods are:

  • cos.create(entry,transaction,ensemblename)
  • cos.retrieve(template,transaction)
  • cos.update(entry,transaction)
  • cos.delete(entry,transaction)
  • cos.exists(entry,transaction)
  • cos.addLifecycle(entryID,trigger,ensemblename,transaction)
  • cos.removeLifecycle(entryID,trigger,ensemblename,transaction)
  • cos.notifyEvent(entry,transaction,listener,handback)

I will go into the use of these in the next article, where I discuss the building, testing, deploying, and running of a simple COS application that provides peer-to-peer task allocation and tracking.

Dave Sag is a skilled Object Modeler and Software Designer, using Java as well as other programming environments.


Return to ONJava.com.