<?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="TroubleShooting Jini" id ="2">
<title>
TroubleShooting Jini
</title>

  <tocchap>
    <tocentry>
      Contents
    </tocentry>

    <toclevel1>
      <tocentry>
	<ulink url="#The Chapter that Shouldn't Exist"> The Chapter
	  that Shouldn't Exist </ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Java Packages"> Java Packages </ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Jini Versions"> Jini Versions </ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Jini Packages"> Jini Packages </ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#HTTP Server"> HTTP Server </ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Network Configuration"> Network Configuration
	</ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Lookup Service"> Lookup Service </ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#RMI Stubs"> RMI Stubs </ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Garbage Collection"> Garbage Collection </ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Debugging"> Debugging </ulink>
      </tocentry>
    </toclevel1>
  </tocchap>

<abstract>
<para>
This chapter looks at some of the problems that can arise in a Jini
system. Most of them are configuration problems of some kind.
This chapter is woefully incomplete :-((( Contributions welcome!!!
</para>
</abstract>


<sect1>
<title id="The Chapter that Shouldn't Exist">
The Chapter that Shouldn't Exist
</title>

<para>
Jini is advertised as "network plug and play". This carries the idea of
"zero administration" where you buy a device or install a software service, switch it on and
<emphasis>voila</emphasis> it is there and available. Well, this may
happen in the future, but right now there are a number of back-room games
that you have to succeed at. Once you have won at these, "network plug and
play" <emphasis>does</emphasis> work, but if you lose at any stage then
it can be all uphill!
</para>

<para>
What is hard is issues of getting the right files in the right places with
the right permissions. About 50% of the messages in the Jini mailing list
are all about these configuration problems. These shouldn't occur, and that
is why this is "The Chapter that Shouldn't Exist". 
</para>

<para>
This is the second chapter in this book, so right now you shouldn't have
managed to fail at anything! Each of the early sections contains instructions
on what to do to get the example programs working, and include step-by-step
instructions. 
So skip on to the next chapters, but come back
here when things go wrong. Your luck may vary: I got quite a reasonable way
on my first attempts without problems, and some are even luckier. 
Some aren't...
</para>

</sect1>

<sect1>
<title id="Java Packages">
Java Packages
</title>

<para>
Typical error:
<programlisting>
Exception in thread "main" java.lang.NoClassDefFoundError: 
         basic/InvalidLookupLocator
</programlisting>
</para>

<para>
Most of the code in this tutorial is organised into packages. To run
the examples the classes must be accessible from your class path. For
example, one of the programs in the <code>basic</code> directory is
<code>InvalidLookupLocator.java</code>. This defines the class
<code>InvalidLookupLocator</code> in the package <code>basic</code>.
The program must be run using the fully qualified path name, as in
<programlisting>
java basic.InvalidLookupLocator
</programlisting>
(Note the `.', not a `/'.)
</para>

<para>
In order to find this class, the classpath must be set correctly for
the Java runtime. If you have copied the zip file <code>classes.zip</code>
then the class files for this tutorial are in there. You only need to
reference this
<programlisting>
CLASSPATH=classes.zip:...
</programlisting>
</para>

<para>
If you have downloaded the source files, then they are all in subdirectories
such as <code>basic</code>, <code>complex</code>, etc. After compilation the
class files should also be in these subdirectories, such as
<code>basic/InvalidLookupLocator.class</code>. An alternative to using
<code>classes.zip</code> is to set the classpath to include the
directory containing those subdirectories. For example, if the full path
is say <code>/home/jan/classes/basic/InvalidLookupLocator.class</code>,
then set classpath to
<programlisting>
CLASSPATH=/home/jan/classes:...
</programlisting>
</para>

<para>
An alternative to setting the <code>CLASSPATH</code> environment variable
is to use the <code>-classpath</code> option to the Java runtime engine
<programlisting>
java -classpath /home/jan/classes basic.InvalidLookupLocator
</programlisting>
</para>
</sect1>

<sect1>
<title id="Jini and Java Versions">
Jini and Java Versions
</title>

<para>
There are five versions of Jini: 1.0, 1.1, 1.2, 2.0 and now 2.1.
The core classes are all the same. 
This version of the book will only deal with the new 2.1.
Jini 2.1 requires JDK 1.4 or later, not earlier versions of Java.
It will work with JDK 1.5 but does not require it.
</para>

<para>
The changes for 2.1 are listed in the document "jini2_1/doc/release-notes/new.html"
</para>
<!--
The main classes that have changed for 2.0 are 
<orderedlist>
<listitem>
<code>LookupDiscovery</code> has an additional constructor
</listitem>
<listitem>
<code>LeaseRenewalManager</code>
</listitem>
<listitem>
<code>ServiceIDListener</code>
</listitem>
</orderedlist>
</para>

<para>
The main new ones are 
<orderedlist>
<listitem>
<code>LookupLocatorDiscovery</code>
</listitem>
<listitem>
<code>LookupDiscoveryManager</code>
</listitem>
<listitem>
<code>ClientLookupManager</code>
</listitem>
</orderedlist>
-->

<!--
<para>
If you get syntax errors or runtime errors relating to these, then it is possible
that you are using Jini 1.0 instead of Jini 1.1. If you get "deprecated"
warnings, then it is likely that you are using the Jini 1.0 classes in a 
Jini 1.1 environment. The old classes are supported for now, but are not approved.
</para>
-->
</sect1>

<sect1>
<title id="Jini Packages">
Jini Packages
</title>

<para>
Typical error
<programlisting>
Exception in thread "main" java.lang.NoClassDefFoundError: 
             net/jini/discovery/DiscoveryListener
</programlisting>
</para>

<para>
The Jini class files are all in <code>jar</code> files.
The Jini distribution has them in a subdirectory <code>lib</code>
when it is unpacked.
There are a whole bunch of these jar files:
<programlisting>
jini-core.jar         mahalo-dl.jar         sun-util.jar
jini-examples-dl.jar  mahalo.jar            tools.jar
jini-examples.jar     reggie-dl.jar
jini-ext.jar          reggie.jar
</programlisting>
</para>

<para>
The jar file <code>jini-core.jar</code> contains the major packages of Jini
<programlisting>
net.jini.core
net.jini.core.discovery
net.jini.core.entry
net.jini.core.event
net.jini.core.lease
net.jini.core.lookup
net.jini.core.transaction
</programlisting>
If the Java compiler or runtime can't find a class in one of
these packages then you need to make sure that the
<code>jini-core.jar</code> is in your classpath. 
</para>

<para>
The jar file <code>jini-ext.jar</code> contains a set of packages
which are not in the core, but are still heavily used
<programlisting>
net.jini.admin
net.jini.discovery
net.jini.entry
net.jini.lease
net.jini.lookup
net.jini.lookup.entry
net.jini.space
</programlisting>
If the Java compiler or runtime can't find a class in one of
these packages then you need to make sure that the
<code>jini-ext.jar</code> is in your classpath. 
</para>

<para>
The jar file <code>sun-util.jar</code> contains the packages
from the <code>com.sun.jini</code> hierarchy. 
These contain a number of "convenience" classes that are
not essential but can be useful. These are less frequently
used.
</para>

<para>
A compile or run of a Jini application will typically have an
environment set something like
<programlisting>
JINI_HOME=wherever_Jini_home_is
CLASSPATH=.:$JINI_HOME/lib/jini-core.jar:$JINI_HOME/lib/jini-ext.jar
</programlisting>
</para>
</sect1>

<sect1>
<title id="HTTP Server">
HTTP Server
</title>

<para>
<programlisting>
java.rmi.ServerException: RemoteException in server thread; nested exception is:
        java.rmi.UnmarshalException: unmarshalling method/arguments; nested exception is:
        java.lang.ClassNotFoundException: could not obtain preferred value for: ...
</programlisting>
The most likely cause is that you aren't running an HTTP server on the machine
that <code>java.rmi.server.codebase</code> is pointing to. Note that using
<code>localhost</code> is a common error since it may refer to a different
machine to the intended one.
</para>
</sect1>

<sect1>
<title id="Network Configuration">
Network Configuration
</title>

<para>
A long-term aim in pervasive computing is to have <emphasis>zero configuration</emphasis>,
whereby you can plug devices into a network and things "just work". Jini goes
a long way towards making this possible at the <emphasis>service</emphasis> level,
but the current implementation relies heavily on a functioning network layer:
problems with misconfiguration of the network can cause lots of problems to Jini.
</para>

<para>
Typical error
<programlisting>
java.rmi.ConnectException: connection refused or timed out to 
               BasicObjectEndpoint[88133900-39f9-466a-880b-de8ce6653a63,
                                   TcpEndpoint[0.0.0.0:1831]]; nested exception is:
        java.net.ConnectException: Connection refused
</programlisting>
This error can occur by using the new configuration mechanism, where a service is exported
by Jeri using
<programlisting>
    exporter = new BasicJeriExporter(TcpServerEndpoint.getInstance(0),
                                     new BasicILFactory());

</programlisting>
This finds the localhost, gets its host name and IP address and listens on any
available port. I lost several days over this as the hostname on one machine was incorrectly
set, and the Java network layer (by <code>InetAddress.getLocalHost()</code>) was
unable to determine the IP address of <code>localhost</code> and returned "0.0.0.0" -
and nothing could connect to that address!
</para>

<para>
The solution was to correctly set the hostname on that machine. Then services could
be found and run on that machine. Alternatively, <code>TcpServerEndpoint.getInstance(0)</code>
could be replaced by <code>TcpServerEndpoint.getInstance("my_ip_address", 0)</code>
(for a suitable "my_ip_address" of course!) in the configuration files for the 
services in that machine.
</para>
</sect1>

<sect1>
<title id="Could not obtain preferred value for...">
Could not obtain preferred value for...
</title>

<para>
Jini can't find a class file. Something is wrong with the classpath or the codebase.
This can occur if the codebase points to a directory, and the value is not
terminated with a "/"
</para>
</sect1>

<sect1>
<title id="Lookup Service">
Lookup Service
</title>
</sect1>


<para>Typical error
<programlisting>
java.rmi.activation.ActivationException: ActivationSystem not running;
nested exception is: 
        java.rmi.NotBoundException: java.rmi.activation.ActivationSystem
java.rmi.NotBoundException: java.rmi.activation.ActivationSystem
</programlisting>
</para>
The command <code>rmid</code> starts the "activation system" running.
If this cannot start properly or dies just after starting, you will get 
this message. Usually it is caused by incorrect file permissions.

<sect1>
<title id="RMI Stubs">
RMI Stubs
</title>

<para>
Typical error
<programlisting>
java.rmi.StubNotFoundException: 
         Stub class not found: rmi.FileClassifierImpl_Stub; 
nested exception is: 
        java.lang.ClassNotFoundException: rmi.FileClassifierImpl_Stub
</programlisting>
</para>

<para>
Many of the examples export services as remote RMI objects.
These objects are subclasses of <code>UnicastRemoteObject</code>.
What gets exported is not the object itself, but a <emphasis>stub</emphasis>
that will act as proxy for the object (which continues to run back
in the server). The stub has to be created using the <code>rmic</code>
compiler as in
<programlisting>
rmic -v1.2 -d . rmi.FileClassifierImpl
</programlisting>
This will create a <code>FileClassifierImpl_Stub.class</code> in the
<code>rmi</code> subdirectory. The stub class file needs to be accessible
to the Java runtime in the same way as the original class file.
</para>

<para>
Another typical error is
<programlisting>
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
        java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
        java.lang.ClassNotFoundException: rmi.FileClassifierImpl_Stub
</programlisting>
This arises when an object is trying to get a remote reference to the 
<code>FileClassifierImpl</code>, and it is trying to load the class file for the
stub from an HTTP server. 
What makes this one particularly annoying is that it may not be referring
to the <code>FileClassifierImpl_Stub</code> at all! The class will often implement
a remote interface such as <code>RemoteFileClassifier</code>. This in turn implements
the common class <code>FileClassifier</code> as in Figure <xref linkend="stubsuper"/>. 
<figure id="stubsuper">
<graphic fileref="images/stubsuper.gif" align="center"> </graphic>
<title>Interfaces/Superclasses for an Exported Stub</title>
</figure>

<emphasis>Class files for all of these classes and interfaces 
have to be available!</emphasis>
The interface <code>FileClassifier</code> may be "well known", with a class
file on each client and server. However, an interface such as
<code>RemoteFileClassifier</code> as well as the implementation files for
<code>FileClassifierImpl</code> may only be known to a particular server.
 The HTTP server must carry not only the
class files for the stubs, but the class files for all superclasses and interfaces
that are not available to all - in this case, for <code>RemoteFileClassifier</code>
as well as <code>FileClassfier</code>.
</para>

</sect1>

<sect1>
<title id="Garbage Collection">
Garbage Collection
</title>

<para>
Typical error
<programlisting>
java.rmi.ConnectException: connection refused or timed out to BasicObjectEndpoint[afeb7958-8cff-41cb-8042-ec884a52e9a6,TcpEndpoint[192.168.2.1:3558]]; nested exception is:
        java.net.ConnectException: Connection refused
</programlisting>
If the service has been garbage collected then there will be no server listening
for connections to it, so any connection request will be refused.
This error is more likely to happen with Jini 2.0, where objects may be
garbage collected if there are no active references.
</para>

<para>
The solution is to ensure that an active reference is kept to the service.
The <code>main()</code> method should contain a reference to the server
(not just create it, but also keep a variable pointing to it).
The server should also keep a reference to the service implementation.
An alternative is to keep a static reference to the service implementation.
Similarly, if you are using a <code>JoinManager</code> to keep services
leased then there should be an active reference to it or it may be garbage
collected and cause any leases to expire.
</para>
</sect1>


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

<para>
Debugging a Jini application is difficult because there are so many bits
to it, and these bits are all running separately: the server for a service,
the client, lookup services, remote activation daemons and HTTP servers.
There are a few (not many) errors within the Jini objects themselves,
but more importantly many of these objects are implemented using multiple
threads and the flow of execution is not always clear. There are no magic
"debug" flags that can be turned on to show what is happening.
</para>

<para>
On either the client or service side, a debugger such as <code>jdb</code>
can be used to step through or trace execution of each one. Lots of
print statements help too. There are also three flags that can be turned
on to help:
<programlisting>
java -Djava.security.debug=access \
     -Dnet.jini.discovery.debug=1 \
     -Djava.rmi.server.logCalls=true ...
</programlisting>
The don't give complete information, but they do give some, and can at least
tell you if the application parts are still living!
</para>

<para>
The logging APIU can also be used for debugging, and is considered in a later
chapter.
</para>

</sect1>

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

<para>
The logging API introduced in Jini 1.4 has been adopted by Jini 2.0. This can also
be used for debugging, and is discussed in its own chapter.
</para>

</sect1>

&copyright;

</chapter>

