Summary
Recently, while working with a partner to integrate their software into our Jini infrastructure, I employeed a simple pattern which I have used many times.
Advertisement
Deploying a Java Class as a Jini Service
For some existing Java applications, there is some class that client applications use to interact with a service of some sort. That service might be a simple class that is a library of routines for Fast Fourier Transforms, or a more sophisticated application that has a UDP based client/server protocol that is hidden by a wrapper class. To deploy such classes as Jini services provides a very interesting opportunity to let you distribute updates more readily, as well as start to provide remote services through an implementation that evolves over time.
The Pattern
The pattern I used involves creating 1 new interface and 2 new classes. The interface defines a factory method for getting an instance of the Object that we want to turn into a service. There needs to be an implementation of this factory, and there needs to be a Jini service that deploys either an instance of the factory, or a remote reference to the factory if the server will manage the creation of the objects. In this case, I chose to deploy an instance of the factory since I had no server side interest in that process.
The Interface for the Factory
This interface is simple. It has a single method and is shown below. The single method, throws Exception because that is what the constructor for the implementation Object throws, and so I needed to make that exception flow through to the caller.
This factory methods exception list needs to take into account current and future requirements for exceptions. If you are going to serialize an instance of the factory implementation as your service implementation, think carefully about if/when you might choose to make that a remote method call. Include IOException in the throws clause if you have any possibility of ever making the method call execute remotely.
package product.access;
import product.parts.*;
public interface ProductFactory {
public ProductClient getInstance() throws Exception;
}
The factory interface implementation
Next, we need to define a class that will implement the factory interface defined above. In my case, I am creating a Serialized object as the service implementation, so I have defined the class to implement the interface as shown above, but to also implement the java.io.Serializable interface to allow the factory object to be Serialized.
This implementation just has to use new to create an instance of the class that I want to be the service implementation, and return that. If you have parameters that you need to pass, then change the factory method definition, and the implementation method to have those arguments so that the user of the factory, can pass any arguments needed.
package product.access;
import product.parts.*;
import java.io.Serializable;
public class ProductFactoryImpl
implements ProductFactory, Serializable {
public ProductClient getInstance() throws Exception {
return new ProductClientImpl();
}
}
Creating the Jini Service Implementation
Finally, we need to create a Jini service that will register this service with the lookup server. To do this, I made use of a very convienent class that I support on the startnow.jini.org project. PersistentJiniService provides a whole bunch of convenience methods and implementation details that let you not have to worry so much about remembering all the details.
This class definition below shows how I overrode the getExportedObject() method so that it just returns an instance of the Serializable factory class defined above. This is the object that is sent off to the Lookup Server, and will thus be what the user of the service gets when they lookup the service, and then download the implementation.
package product.access;
import java.io.*;
import product.parts.*;
import net.jini.config.*;
import org.wonderly.jini2.*;
public class ProductFactoryService extends PersistentJiniService {
public static void main( String args[] )
throws IOException, ConfigurationException {
new ProductFactoryService( args );
}
public ProductFactoryService( String args[] )
throws IOException, ConfigurationException {
super( args );
startService("product", "product.ser");
}
protected Object getExportedObject() {
return new ProductFactoryImpl();
}
}
Configuration for the Service
Finally, there are the details of the Configuration that is used to deploy the service into the Jini network. I deployed the service with JRMP and all other defaults that PersistentJiniService provides by using a config file that only contains:
import net.jini.core.entry.Entry;
import net.jini.lookup.entry.Name;
project.access.ProjectFactoryService {
entries = new Entry[] {
new Name( "project" )
};
}
While there are still a couple of other items that I dealt with for specifics of this application, this is the basic structure of this pattern. The ProductClient interface and the ProductClientImpl class are the things that change for each application. There are many variations on this pattern that include the remoting of the factory interface method as I described above.
In Summary
There's not a lot of magic here. The tedious parts are covered by the code in PersistentJiniService. If you have these kinds of tools available to you, you'll find it very quick to do these kinds of projects. It took me about 30min to devise, implement, test and deploy this solution. I've fed the ideas back to our partners, and they can hopefully use the concrete example to get a good idea of how they might fully Jini enable their application.