<?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 label="ServiceStarter" id="21">
<title>
    ServiceStarter
</title>

  <tocchap>
    <tocentry>
      Service Starter
    </tocentry>
    <toclevel1>
      <tocentry>
	<ulink url="#ServiceDescriptor">ServiceDescriptor</ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Starting a nonactivatable service">
	Starting a nonactivatable service
	</ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Starting a nonactivatable server">Starting a nonactivatable server</ulink>
      </tocentry>
    </toclevel1>
    <toclevel1>
      <tocentry>
	<ulink url="#Reggie">Reggie</ulink>
      </tocentry>
    </toclevel1>
  </tocchap>

  <abstract>
    <para>
      A service is created by a server and registered with lookup
      services. The server has a fairly standard format, usually
      varying only in small details: the actual service, its entry
      attributes, number of services, etc. The ServiceStarter class
      can help with some of this, and is used by Sun for its tools
      such as reggie
    </para>
  </abstract>

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

    <para>
      In the chapter on configuration we looked at how a "meta-server" might
      be written that would get information from a configuration file
      describing a service and use that to build the service. In order
      to make a service available for use, a number of parameters must
      be set up. These include
      <orderedlist>
	<listitem> <para>
	  The service class and how to construct it
	</para> </listitem>
	<listitem> <para>
	  The transport protocol (Jeri/JRMP)
	</para> </listitem>
	<listitem> <para>
	  The proxy for the service
	</para> </listitem>
	<listitem> <para>
	  The codebase for the proxy files
	</para> </listitem>
	<listitem> <para>
	  The classpath for the local files
	</para> </listitem>
	<listitem> <para>
	  A security policy to run the server for this service
	</para> </listitem>
	<listitem> <para>
	  Entry/attribute information
	</para> </listitem>
	<listitem> <para>
	  Unicast locators of lookup services
	</para> </listitem>
	<listitem> <para>
	  Group to join on lookup services
	</para> </listitem>
	<listitem> <para>
	  Service item ID
	</para> </listitem>
      </orderedlist> 
      Some of these belong to the service, some to its proxy,
      some to the containing server, while others are advertisement
      parameters for joining lookup services.
    </para>

    <para>
      Jini has an interface <code>ServiceDescriptor</code> to give a
      standard way of handling some of these. This class is in the
      <code>com.sun.jini.start</code> package. This package is not
      specified by Jini, and may change or even disappear in later
      versions of Jini. 
      <programlisting> 
interface ServiceDescriptor {
	Object create(Configuration config); } 
      </programlisting>
    </para>

    <para>
      This has a number of implementations
      <orderedlist>
	<listitem> <para>
	  <code>NonActivatableServiceDescriptor</code>
	</para> </listitem>
	<listitem> <para>
	  <code>SharedActivatableServiceDescriptor</code>
	</para> </listitem>
	<listitem> <para>
	  <code>SharedActivationGroupDescriptor</code>
	</para> </listitem>
      </orderedlist>
    </para>

    <para>
      The first is useful for the most common situation described in
      this book, of a non-activatable service. The meat of the
      <code>NonActivatableServiceDescriptor</code> class is in its
      constructors: 
      <programlisting> 
class NonActivatableServiceDescriptor {
    NonActivatableServiceDescriptor(String codebase, 
                                    String policy, 
                                    String classpath, 
                                    String implClassName, 
                                    String[] serverConfigArgs); 
    
    NonActivatableServiceDescriptor(String codebase, 
                                    String policy, 
                                    String classpath, 
                                    String implClassName, 
                                    String[] serverConfigArgs, 
                                    LifeCycle lifeCycle); 
} 
      </programlisting> 
      The <code>codebase</code> is a
      url(s) of a directory or jar file of the proxy classes on an
      HTTP server; <code>policy</code> is the filename of the policy
      for this service within the context of the policy existing for
      the server; <code>classpath</code> is the classpath for the
      service run by the server; <code>serverConfigArgs</code> is an
      array of configuration parameters (typically just a single file name); 
      it is not yet clear what <code>lifeCycle</code> is, or how it is used.
    </para> 

    <para>
      It is notable what the constructor does, and does not, describe.
      It describes the service's class and its classpath, that is, how to run it. 
      It describes the
      environment for the proxy, but not how to create it.
      The constructor does <emphasis>not</emphasis>
      describe the entry information, the service id or the groups to
      which this service belongs. The parameters in the constructor for
      <code>NonActivatableServiceDescriptor</code> describe the
      service's <emphasis>runtime/deployment</emphasis> environment.
      They do not describe the service's
      <emphasis>advertisement</emphasis> environment.
    </para>

    <para>
      The <code>NonActivatableServiceDescriptor</code> class provides
      an implementation of the <code>create()</code> method. This is
      defined in the interface to return an <code>Object</code> but
      the class actually returns a
      <code>com.sun.jini.start.NonActivatableServiceDescriptor.Created</code>. 
      This has no methods, just two public fields 
      <programlisting>
public class Created { 
    public Object impl; 
    public Object proxy; 
} 
      </programlisting> 
      From this one can extract the
      implementation and its proxy.
    </para>

    <para>
      There are further wrinkles in using
      <code>NonActivatableServiceDescriptor</code>. The implementation
      object must be constructed from its class. The constructor has
      two parameters: the string array <code>serverConfigArgs</code>,
      and a <emphasis>lifecycle</emphasis> object. At present it is
      not clear what role this object is expected to play, and it is
      sufficient to use a default value <code>NoOpLifeCycle</code>.
    </para>

    <para> In addition to creating the implementation  object, the
      <code>create()</code> method must create a proxy object for the
      implementation in order to return a <code>Created</code> object.
      This is done by requiring the implementation to support one of
      the two interfaces <code>ServiceProxyAccessor</code> or
      <code>ProxyAccessor</code> and calling
      <code>getServiceProxy()</code> or <code>getProxy()</code>
      respectively on the implementation. That is, the service must
      include the method <code>getServiceProxy()</code> (or
      <code>getProxy()</code>) and within this method it will
      probably create the proxy (possibly using the configuration information).
      object and return it.
    </para>

    <para>
      Pseudo-code using this is
      <programlisting>
	codebase = ...
	policy = ...
	classpath = ...
	implClass = ...
	configArgs = ...

	create a NonActivatableServiceDescriptor

	call create() on this, returning "created" object
	impl = created.impl
	proxy = created.proxy
      </programlisting>
      while the service will have a constructor
      <programlisting>
	Service(String[] config, Lifecyle lc) {
	    proxy = ...
	}
	</programlisting>
      and method 
      <programlisting>
	getServiceProxy() {
	    return proxy
	}
      </programlisting>
    </para>
  </sect1>
  
  <sect1>
    <title id="Starting a nonactivatable service">
      Starting a nonactivatable service
    </title>
    
    <para>
      The implementation must be <code>Remote</code> and must be able to create a
      proxy. In its constructor it is handed a configuration array, so this may as
      well be used to find an exporter to get the proxy. The class
      <code>starter.FileClassifierStarterImpl</code> inherits from
      <code>rmi.FileClassifierImpl</code> and adds <code>ServiceProxyAccessor</code>
      to the basic file classifier:
      <programlisting>
	<?program src/starter/FileClassifierStarterImpl.java ?>
      </programlisting>
    </para>

    <para>
      A configuration file suitable for using Jeri with the above
      <classname>FileClassifierStarterImpl</classname> is 
      <code>resources/starter/file_classifier.config</code>:
      <programlisting>
	<?program resources/starter/file_classifier.config ?>
      </programlisting>
    </para>
    
    <para>
      The server to start this service needs to set various parameters for the
      <code>ServiceDescriptor</code>. 
      The pseudocode above set these explicitly. However, since they describe
      the runtime and deployment environment,
      they are better set in another configuration
      file such as <code>resources/starter/serviceDesc.config</code>:
      <programlisting>
	<?program resources/starter/serviceDesc.config ?>
      </programlisting>
      This configuration file contains two sets of configurations: one for 
      the <code>ServiceDescription</code> component and one for the
      <code>AdvertDescription</code> component (discussed shortly). 
    </para>

    <para>
      The <code>resources/starter/serviceDesc.config</code>
      configuration file uses two jar files, 
      <filename>starter.ServiceDescription-dl.jar</filename>for the
      service codebase and <filename>starter.ServiceDescription-start.jar</filename>
      for the server's classpath. The contents of these files are
      <orderedlist>
	<listitem>
	  <para>
	    The <filename>starter.ServiceDescription-dl.jar</filename>
	    contains all the files that need to be downloaded to a client:
	    <programlisting>
common/MIMEType.class
common/FileClassifier.class
rmi/RemoteFileClassifier.class
	    </programlisting>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    The  <filename>starter.ServiceDescription-start.jar</filename>
	    contains all the files that are needed for the server to create
	    the service:
	    <programlisting>
common/FileClassifier.class
common/MIMEType.class
rmi/FileClassifierImpl.class
rmi/RemoteFileClassifier.class
starter/FileClassifierStarterImpl.class
	    </programlisting>
	  </para>
	</listitem>
      </orderedlist>
    </para>

    <para>
      A server which picks up the values from this configuration file and creates
      the service and its proxy follows. The program essentially uses two parts:
      one to build the service using a <code>ServiceDescriptor</code> and
      its configuration entries, the other to advertise the service using
      <code>JoinManager</code> and its associated 
      <code>AdvertDescription</code> configuration entries.
      (Although <code>JoinManager</code> has a constructor which will take
      a configuration, this does not support any of the entries we specified
      above.)
      <programlisting>
	<?program src/starter/ServiceDescription.java ?>
      </programlisting>
    </para>

    <para>
      This server may be run from a command line such as
      <programlisting> 
java starter.ServiceDescription resources/starter/serviceDesc.config 
      </programlisting>
      using a classpath that includes 
      <classname>starter.ServiceDescription</classname>
    </para>

    <para>
      To summarise what is going on here
      <orderedlist>
	<listitem>
	  <para>
	    The service is started by running  a 
	    <classname>service.ServiceDescription</classname>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    The classpath for
	    <classname>service.ServiceDescription</classname> must include
	    (for example) a jar file 
	    <filename>starter.ServiceDescription.jar</filename> that contains
	    <filename>starter.ServiceDescription.class</filename>
	    as well as the standard Jini classes
	  </para>
	</listitem>
	<listitem>
	  <para>
	    <classname>service.ServiceDescription</classname> uses a configuration
	    file such as <filename>serviceDesc.config</filename> which includes
	    a description of the codebase, etc, which are suitable parameters
	    for the constructor of a <classname>ServiceDescriptor</classname>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    The <filename>serviceDesc.config</filename> configuration also contains
	    an advertisement description to register the service with lookup
	    services
	  </para>
	</listitem>
	<listitem>
	  <para>
	    When the service is started by 
	    <classname>ServiceDescriptor.create()</classname> it uses its own
	    configuration file <filename>file_classifier.config</filename>
	    which specifies the exporter
	  </para>
	</listitem>
	<listitem>
	  <para>
	    The classpath used to start the service includes the files in the
	    jar file <filename>starter.ServiceDescription-start.jar</filename>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    The codebase used by clients to download the service includes
	    the jar file <filename>starter.ServiceDescription-dl.jar</filename>
	  </para>
	</listitem>
      </orderedlist>
    </para>

    <para>
      The <command>ant</command> file to build and run this is
      <filename>antBuildFiles/starter.ServiceDescription.xml</filename>
      <programlisting>
	<?antFile antBuildFiles/starter.ServiceDescription.xml ?>
      </programlisting>
    </para>

  </sect1>
  
  <sect1>
    <title id="Starting a nonactivatable server">
      Starting a nonactivatable server
    </title>
    
    <para>
      The standard tools supplied by Sun such as <code>reggie</code> all use
      the <code>ServiceDescription</code> class. But instead of starting a
      <emphasis>service</emphasis>, they start a <emphasis>server</emphasis>.
      So in this case an application is needed to start the server, which 
      in turn will start the service.
    </para>
    
    <para>
      Sun supply a class <code>ServiceStarter</code> in the
      <code>com.sun.jini.start</code> package. This package is not
      specified by Jini, and may change or even disappear in later versions
      of Jini. It has a public <code>main()</code> method, which will
      take command line arguments. A configuration can be given as a
      command line argument and will be searched for an array of 
      <code>ServiceDescriptor</code>'s. The search is in component
      <code>com.sun.jini.start</code> and the descriptors are labelled
      as <code>serviceDescriptors</code>. The <code>create()</code>
      method will be called on each descriptor to create a server.
    </para>
    
    <para>
      To use the <code>ServiceStarter</code>, you need to write a server
      and also a configuration file containing a <code>ServiceDescriptor</code>
      for that server. The server does not need to have a <code>main()</code>
      method, since the server is started by <code>ServiceStarter</code>, not
      the server itself.
    </para>
    
    <para>
      For example, we could use the <code>FileClasifierServerConfig</code>
      from the chapter on "Configuration". The configuration file for
      this server remains unaltered as 
      <programlisting>
	<?program config/serviceid.config?>
      </programlisting>
      The server itself need not be altered - its <code>main()</code>
      method is just not called. If it were being written from scratch,
      there would be no need to include this method. Repeating this from
      the "Configuration" chapter,
      <programlisting>
	<?program src/config/FileClassifierServerConfig.java?>
      </programlisting>
    </para>
    
    <para>
      What is new is a configuration file for <code>ServiceStarter</code>.
      This could be in <code>resources/starter/start-transient-fileclassifier.config</code>:
      <programlisting>
	<?program resources/starter/start-transient-fileclassifier.config?>
      </programlisting>
    </para>
    
    <para>
      The server is set running by
      <programlisting>
	java -jar start.jar ServiceStarter resources/start-transient-fileclassifier.config
      </programlisting>
    </para>

    <para>
      A typical descriptor for the <code>reggie</code> service might be
      <programlisting>
String codebase = "http://192.168.1.13:8080/reggie-dl.jar";
String policy = "/usr/local/reggie/reggie.policy";
String classpath = "/usr/local/jini2_0/lib/reggie.jar";
String config = "/usr/local/reggie/transient-reggie.config";

ServiceDescriptor desc = 
                new NonActivatableServiceDescriptor(
                        codebase, policy, classpath,
                        "com.sun.jini.reggie.TransientRegistrarImpl",
                         new String[] {config})
      </programlisting>
    </para>

  </sect1>

  <sect1>
    <title id="Reggie"> 
      Reggie 
    </title>
    <para>
      We can now see what is going in when a standard Sun service such as
      <command>reggie</command> is started. A typical command line is
      <programlisting>
java -Djava.security.policy=reggie/start.policy -jar \
      start.jar start-transient-reggie.config
</programlisting>
      The configuration file contains information required to start the
      <command>reggie</command> server, such as
      <programlisting>
	<?program resources/start-transient-reggie.config?>
      </programlisting>
      This particular configuration starts a <classname>TransientRegistrarImpl</classname>
    </para>

    <para>
      When the <classname>TransientRegistrarImpl</classname> begins, it uses a
      configuration file too. This was specified to be
      <filename>/usr/local/reggie/transient-reggie.config</filename> and contains
      <programlisting>
	<?program resources/transient-reggie.config?>
      </programlisting>
    </para>
  </sect1>
  
  <sect1>
    <title id="Conclusion">
      Conclusion
    </title>

    <para>
      A <code>ServiceDescriptor</code> allows a service to be created
      with given parameters. It can be used directly, or by using
      the Sun-supplied  <code>ServiceStarter</code>.
      Sun use this to startup their own
      services such as <code>reggie</code>. These classes are in the
      <code>com.sun.jini.start</code> package, and as such are not
      guaranteed to be stable or even to exist in future versions of
      Jini. Alternatively, like <code>JoinManager</code>, they might
      migrate to the core Jini package in future.
    </para>

    <para>
      We have seen that using <code>ServiceStarter</code> for a server essentially
      involves no changes to the server or its service. What is the point of it, then?
      Typically, starting a service involves a combination of factors from a number
      of sources
      <orderedlist>
	<listitem> <para>
	  Some values may come from the environment, such as <code>CLASSPATH</code>
	</para> </listitem>
	<listitem> <para>
	  Some values may be defined in Java properties, such as security policy
	</para> </listitem>
	<listitem> <para>
	  Some values may be given as command line arguments
	</para> </listitem>
      </orderedlist>
      The <code>ServiceStarter</code> allows all of these to be placed in a
      configuration, so that a single mechanism can be used. 
    </para>
  </sect1>

&copyright;
</chapter>
