Summary
There are a lot of people asking what does Jini provide that J2EE doesn't. There are people who would like better information on where to start with Jini. Here's some information about how one might invest time and effort with learning and using Jini.
Advertisement
When you are learning Jini, there are a handful of fundamental concepts that I think you need to get your mind wrapped around. Other people using Jini might have some other things that they've found to be important in their experiences. This is what I think are the most fundamental for me.
Starting with some Concepts
Jini uses RMI semantics for remote service operations. Jini is designed to take advantage of mobile code, and the security model is designed to deal with this issue explicitly and as completely as the Java platform currently can allow. Jini 2.0 provides the Jini Extensible Remote Invocation (JERI) API that revitalizes RMI with a completely plugable stack for RMI semantics. One of the changes is that there is no longer convienent object substitutions done for you as objects are serialized across calls. So, you need to explicitly manage where proxies are used. This can require some important architectural consideration.
The Lookup server helps makes the network become the computer. Think carefully about how you can exploite dynamic, distributed structure to your advantage. Don't decouple and distribute blindly though (See Seven below).
java.rmi.RemoteException extends java.io.IOException. You can make your APIs usable in distributed environments where the java.rmi package is not found (such as J2ME). Have your remote interface methods throw java.io.IOException. This also makes it possible for more information about the connection associated with the RMI endpoint to be propigated to your application if you create a custom endpoint that needs to do such things.
Leasing allows your application to readily detect and react to the presence of its distributed pieces. Use leasing where you depend on remote pieces being available. Use leasing where timeliness of response/reaction is important. The lookup server already does this for interactions with it. But, there may be other places where you hand objects that reserve local resources, to others for remote use. If the network partitions or you otherwise loose contact, use leasing to manage the recovery of such resources. Distributed garbage collection can do a lot of this for exported remote references. But, sometimes you have different issues that need explicit leasing.
Transactions provide a significant, simplifying mechanism for managing highly distributed applications. The overhead of all the network traffic might be significant. But, many developers who do explicit timing analysis find that the network trip is not always the dominating factor in their system. Use idempotency to eliminate global state dependencies that can allow the user to retry operations that fail without transactions having to always be used.
Javaspaces is not a relational database. Javaspaces is not much more than a possibly distributed, multi-key hashtable. If your need the functionality of a database for non-equality based searches, then don't use Javaspaces. Instead, create an interface that specifies what you need (Even if it looks like the Javaspace API but with different semantics), and put that interface to use with a service that provides access to the searching/matching semantics you need.
The simple API for Javaspaces and the limited actions associated with the matching are on purpose and by design.
The most dominating implementation detail to Sun's Javaspaces implementation is that it does not deserialize the objects into the space. This means that it can't use language facilities for comparison directly. It only has bits that it doesn't have all the semantic understanding of.
I bought and browsed a Jini book when I first started using Jini. It helped to explain some of the finer points that were important to 'getting it'.
API Starting Points
The Jini books will cover a lot of basic things about Jini. You'll find indepth examples about the infrastructure of Jini which might be more than you need to know. Here's the API pieces that I think are important to start at.
Registration of your service should use the JoinManager. This class has a couple of different modes of construction. A service should initially let the system assign a serviceID to it. This serviceID should be saved, and then used from that point on for registration.
Service Lookup can be simplified with the ServiceDiscoveryManager. But, understand that the SDM uses callbacks to populate the caches it uses. This is one of the things that JRMP and many other JERI protocols don't support through firewalls. If you have a single direction connection infrastructure (inside firewall to outside), then you'll find it better to use the LookupDiscoveryManager and/or LookupLocatorDiscovery and then provide a DiscoveryListener to see the discovered() and discarded() events. A Timer can be used to retry discovery periodically so that you'll eventually see state changes on the lookup servers since callbacks via ServiceRegistrar.notify() listener registrations will never occur in oneway networks.
Configuration is your friend. The Jini 2.0 spec adds the Configuration interface. The ConfigurationFile implementation provides a very easy way to let the protocol specifics of JERI/RMI be deferred until deployment. Create a Configuration with ConfigurationProvider.getInstance(String[]). Pass it the String[] arguments that were passed into your main() to get started. Later, you can think about adding a layer of indirection by specifying only a simple commandline configuration that will let your application (server or client) connect to a Configuration service to get the configuration it needs.
There are frameworks available that simplify getting started with Jini. There are several different projects on and off the jini.org website that provide simpler ways to start using Jini.
The RIO project provides extensive enhancements to Jini for quality of service.
Project Rio offers an initial response to these realities by providing a dynamic adaptive network architecture built using Jini technology mechanisms. Intrinsic to this architecture are a set of dynamic capabilities and reliance on Policy-based and Quality of Service mechanisms that extend capabilities currently found in distributed systems.
The Seven project will provide a container based framework for reducing the per service effort needed to create complex applications that use a single JVM to deploy multiple services.
The startnow project provides a
subclassing based mechanism for creating services and clients. For a service, you can subclass PersistentJiniService and make one method call to start your service. Everything else is done for you by the parent class and the project infrastructure. A Client can subclass ConfigurableJiniApplication and then use the ServiceSelector to show a dialog for singleton service selection. There is also a JiniDesktop class to aide in learning about creating a Jini client application.
Be ready to spend some time reading and asking questions. Jini is targeted to solve distributed systems problems in a wide range of applications. So, there isn't a single wizard, IDE or wrapper API that will make everyone's use of Jini trivial. However, Jini based system design is not intended to be complex. Jini provides some simplifying tools that can make the creation, configuration and management of distributed systems easier than most non-Jini users imagine.