<?xml version='1.0'?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
               "http://docbook.org/xml/4.2/docbookx.dtd"
	       [
	       <!ENTITY copyright SYSTEM "copyright.xml">
	       ]>

<chapter title="Introspection" id="24">
<title>
Introspection
</title>

<tocchap>
<title>
Contents
</title>

<toclevel1>
<tocentry>
  <ulink url="#Unknown services">Unknown services</ulink>
</tocentry>
<tocentry>
  <ulink url="#Introspection">Introspection</ulink>
</tocentry>
<tocentry>
  <ulink url="#Unknown classes">Unknown classes</ulink>
</tocentry>
</toclevel1>
</tocchap>

<abstract>
<para>
Questions often asked are: how do you find all services, and
how do you  deal with a service if you
don't know what it is? The first is answered by searching for 
<classname>Object</classname>.
 Introspection is the answer to the second, but if you
require your services to be introspected then you have to pay
extra attention to the deployment environment.
</para>
</abstract>

 <sect1>
    <title id="Basic Service Lister">
      Basic Service Lister
    </title>
    
    <para>
      The client of the chapter "Simple Example" looked for a particular
      class by specifying the class in the <classname>ServiceItem</classname>.
      How do we find all services? Well, any class inherits from 
      <classname>Object</classname>, so one way is to just look for all
      services that implement <classname>Object</classname> (this is one
      of the few cases in which we might specify a <emphasis>class</emphasis>
      instead of an <emphasis>interface</emphasis>). We can adapt the
      client quite simply by looking for all services, and then doing something
      simple like printing its class
      <programlisting>
	<?program "src/client/BasicServiceLister.java"?>
      </programlisting>
    </para>
    
  </sect1>
  
<sect1>
<title id="Unknown services">
Unknown services
</title>

<para>
A common question is "how do I deal with services that I know
nothing about?" There are two answers:
<orderedlist>
<listitem>
  Are you sure you want to? If you don't know about the service
  beforehand, then what are you going to sensibly infer about its
  behaviour just from discovering the interface? In most cases, if
  you don't already know the service interface and have some idea
  of what it is supposed to do, then getting this service isn't
  going to be of much use
</listitem>
<listitem>
  On the other hand, service browsers may no have prior knowledge
  of the services they discover but may still wish to use
  information about these services. For example, a service browser
  could present this information to a user and ask if the user
  wants to invoke the service. Or a client using AI techniques
  may be able to guess at behaviour from the interface, and invoke
  the service based on this 
</listitem>
</orderedlist>
This (short) chapter is concerned with the second case.
</para>

</sect1>

<sect1>
<title id="Introspection">
Introspection
</title>

<para>
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.
</para>

<para>
The starting point for these are various <code>Class</code> methods
which include
<programlisting>
Constructor[] getConstructors();
Class[]       getClasses();
Field[]       getFields();
Class[]       getInterfaces();
Method[]      getMethods();
int           getModifiers();
Package       getPackage();
</programlisting>
Methods in the classes <code>Field</code>, <code>Method</code>, etc,
allow you to gain extra details.
</para>

<para>
For example, to find information about interfaces of
services on a lookup service,
<programlisting>
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 &amp;lt; 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 &amp;lt; ifaces.length; m++) {
	    System.out.println("  implements " + ifaces[m].getName());
        }
    }
}
</programlisting>

</para>
</sect1>

<sect1>
<title id="Unknown classes">
Unknown classes
</title>

<para>
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 <code>null</code>. That is why there is a
check for <code>null</code> service in the last example code: a
service has been found, but cannot be rebuilt into an object due
to missing class files.
</para>

<para>
Clients get the class files from two sources:
<orderedlist>
<listitem>
  Already known, and in their class path
</listitem>
<listitem>
  Accessed from a Web server, by the <code>java.rmi.server.codebase</code>
  property of the service
</listitem>
</orderedlist>
If you are a service provider, you may wish to make your service
available to clients who have never heard of your service before.
In this case, you cannot rely on the client knowing anything except
for the core Java classes. This may be in doubt if the client is using
one of the "limited device" Java memory models - this is not a problem
yet, since these models do not yet support Jini. You can make a pretty solid
bet that the core Jini classes will have to be there too, 
but non-essential classes in the package <code>jini-ext.jar</code>
may not be present.
</para>

<para>
The example that we have been using so far is an implementation
of <code>FileClassifier</code>. A typical implementation uses these
non-core classes/interfaces:
<orderedlist>
<listitem>
  <code>FileClassifier</code>
</listitem>
<listitem>
  <code>RemoteFileClassifier</code>
</listitem>
<listitem>
  <code>MIMEType</code>
</listitem>
<listitem>
  <code>FileClassifierImpl</code>
</listitem>
</orderedlist>
The assumption in earlier chapters is that <code>FileClassifier</code>
and <code>MIMEType</code> are "well known" and the others need to be
accessible from a Web server. For robust introspection, this assumption
must be dropped: <code>FileClassifier</code>
and <code>MIMEType</code> must also be available from the service's Web
server. This a <emphasis>server</emphasis> responsibility, not
a <emphasis>client</emphasis> responsibility; the client can do nothing
if the service does not make its class files available.
</para>

<para>
To summarise: if a service wishes to be discovered by clients that
have no prior knowledge of the service, then it must make 
<emphasis>all</emphasis> 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."
</para>
</sect1>

&copyright;
</chapter>
