A question often asked is: how to deal with a service if you don't know what it is? Introspection is the answer, but if you require your services to be introspected then you have to pay extra attention to the deployment environment.
A common question is "how do I deal with services that I know nothing about?" There are two answers:
Java has a well-developed introspection library. This allows a Java program to take a class and find all of the methods (including contructors) and to find the parameters and return types of these methods. For non-interface classes, the fields can also be found. The classes that a class implements or extends can also be determined. The access methods (private, public, protected) and the thrown exceptions can be found as well. In other words, all of the important information (except JavaDoc comments) can be retrieved from the object's class.
The starting point for these are various Class
methods
which include
Constructor[] getConstructors();
Class[] getClasses();
Field[] getFields();
Class[] getInterfaces();
Method[] getMethods();
int getModifiers();
Package getPackage();
Methods in the classes Field
, Method
, etc,
allow you to gain extra details.
For example, to find information about interfaces of services on a lookup service,
ServiceRegistrar registrar = ...
ServiceTemplate templ = new ServiceTemplate(null, null, null);
ServiceMatches matches = registrar.lookup(templ, Integer.MAX_VALUE);
ServiceItem[] items = matches.items;
for (int n = 0; n < items.length; n++) {
Object service = items[n].service;
if (service != null) {
Class cls = service.getClass();
System.out.println("Class is " + cls.getName());
Class[] ifaces = cls.getInterfaces();
for (int m = 0; m < ifaces.length; m++) {
System.out.println(" implements " + ifaces[m].getName());
}
}
}
In earlier chapters we have assumed that a client will know at least
the interfaces of the services it is attempting to use. For a browser
or a "smart" client this may not be the case: the client will often
come across services that it does not know much about. When a client
discovers a service, it must be able to reconstitute it into an object
that it can deal with, and for this it needs to be able to find the
class files. If any one of the needed class files are missing, then
the service comes back as null
. That is why there is a
check for null
service in the last example code: a
service has been found, but cannot be rebuilt into an object due
to missing class files.
Clients get the class files from two sources:
java.rmi.server.codebase
property of the service
jini-ext.jar
may not be present.
The example that we have been using so far is an implementation
of FileClassifier
. A typical implementation uses these
non-core classes/interfaces:
FileClassifier
RemoteFileClassifier
MIMEType
FileClassifierImpl
FileClassifier
and MIMEType
are "well known" and the others need to be
accessible from a Web server. For robust introspection, this assumption
must be dropped: FileClassifier
and MIMEType
must also be available from the service's Web
server. This a server responsibility, not
a client responsibility; the client can do nothing
if the service does not make its class files available.
To summarise: if a service wishes to be discovered by clients that have no prior knowledge of the service, then it must make all of its interface and specification classes publically available from a Web server. Any other classes that are non-standard or potentially missing from the client should be on this public Web server too. There is a restriction: you cannot make some classes available to non-signatories to various copyright agreements, meaning that licensing restrictions may not allow you to make some classes publically available. For example, you cannot make any of the Jini files publically available "just in case the client doesn't have them."
If you found this chapter of value, the full book is available from APress or Amazon . There is a review of the book at Java Zone