站内搜索: 请输入搜索关键词
当前页面: 在线文档首页 > NetBeans API Javadoc 5.0.0

Lookup Library - NetBeans API Javadoc 5.0.0

Lookup Library - The Solution to Comunication Between Components

$Revision: 1.1 $
History: Available in CVS

This is the home page of the lookup library implementation, which is intended to solve a general problem that every component-based system has had to face: how different components register to the system and how other parts of the system can look them up.

There already are libraries trying to solve this problem, usually by querying for an interface and finding its appropriate implementaion. The most famous is Jini, the platform for development of distributed network services. Our library does something similar, but tries to stay small and easy to use. The NetBeans Lookup Library's main focus is a modular application consisting of independent modules that want to communicate with each other. It does not try to solve networking or legacy application integration. It is simple but powerful.

Why would you want to use it?

A well-written modular program separates development and deployment. There are many situations where a component needs some functionality but does not actually care about the implementation. It is up to the system adminstrator that deploys (installs) the application to decide which implementation to use.

The most simple and most often used method for allowing other implementations to be plugged in is the system property pattern:

    public Toolkit getDefaultToolkit () {
        java.awt.Toolkit t = null;
        String classname = System.getProperty ("java.awt.Toolkit");
        if (classname != null) {
            try {
                Class c = Class.forName (classname);
                t = (java.awt.Toolkit)c.newInstance ();
            } catch (Exception ex) {
                System.out.println ("Cannot initialize toolkit: " + classname);
                ex.printStackTrace ();
            }
        }
        // fallback 
        if (t == null) {
            t = new GenericAWTToolkit ();
        }
    }
The idea is simple. The deployer can start the Java VM with the flag -Djava.awt.Toolkit=org.myorg.MyToolkit where the MyToolkit is his class with default constructor and the code in the getDefaultToolkit method will instantiate the class and use it.

In principle this is general enough of a solution and works well, except that writing the code above is error prone and it also requires passing the arguments to the virtual machine. It would be much nicer if the registation could be done just by putting a JAR file with the MyToolkit class into the application classpath.

Actually this has been realized also by the JDK development team and addressed in JDK 1.3 as part of the provider extension mechanism. The MyToolkit could be registered by adding a file /META-INF/services/java.awt.Toolkit with one line org.myorg.MyToolkit into the JAR file that contains the MyToolkit implementation. The code in getDefaultToolkit will scan all JAR files in classpath and search for that file, create an instance of MyToolkit and use it. The deployer can influence which toolkit will be created by adding the right JAR files into the classpath.

Of course the code to access the META-INF/services/ files is even more error prone than the property pattern. And this is exactly the place where the lookup library can help. It provides an implementation of the search algorithm with an easy interface. Just write:

    import java.awt.Toolkit;
    import org.openide.util.Lookup;;
    Toolkit t = (Toolkit)Lookup.getDefault().lookup(Toolkit.class);
and if the JAR with MyToolkit is in the class path, the simple call above will do the rest.

So whenever one writes an application divided into several independent modules (jar files) that are being developed and deployed independently, there is a need for registering and discovering components. First of all, a set of interfaces can be defined to enable inter-module communication (like the abstract class java.awt.Toolkit). After that a set of modules providing implementation can written (MyToolkit and other concurent implementations) and after that, whenever a module trying to utilitize the functionality wants to access the Toolkit via lookup, the real implementation is returned.

It is the responsibility of lookup to find a suitable implementation of the requested service and return an object implementing the service. This is the the basic functionality and while the library provides you with a little bit more, even this simple usage might be extremaly useful: the client code knows nothing about the implementation and the implementation can be switched in deployment time by simply replacing one implementation jar with other. There is no code change required.

Local lookup usage

The example in previous paragraph demostrated the usage of lookup as a global registry (by using the Lookup.getDefault() call). One can also consider another scenario where the lookup can help.

Let's switch hats to be an API designer for a while. The goal is to introduce a new object into the system. But you either are not sure yet what all the roles of the new object will be or you (more importantly) want to be able to add (or change) roles of the object dynamically. So why not to introduce following method to the object's interface:

public class  MorphingObject {
    public Lookup getLookup() {
        return myLookup;
    }
    ...
}
By exposing the method getLookup you can attach different functionality to the MorphingObject at runtime and whoever gets a reference to your object can ask it whether the object supports a given interface like this:
MorphingObject morph = ...
AnInterface impl = (AnInterface)morph.getLookup().lookup(AnInterface.class);
if (impl == null) {
    return;/* AnInterface not supported now! */
}
impl.useIt();

Additional functionality

The NetBeans lookup library also provides:

Further information