You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by hl...@apache.org on 2003/09/05 01:59:03 UTC

cvs commit: jakarta-commons-sandbox/hivemind/xdocs/images AdderExample-ProjectLayout.png

hlship      2003/09/04 16:59:03

  Modified:    hivemind/xdocs navigation.xml
  Added:       hivemind/xdocs bootstrap.xml
               hivemind/xdocs/images AdderExample-ProjectLayout.png
  Log:
  Add documentation about "bootstrapping" the registry.
  
  Revision  Changes    Path
  1.13      +2 -0      jakarta-commons-sandbox/hivemind/xdocs/navigation.xml
  
  Index: navigation.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/xdocs/navigation.xml,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- navigation.xml	6 Aug 2003 18:50:05 -0000	1.12
  +++ navigation.xml	4 Sep 2003 23:59:03 -0000	1.13
  @@ -1,4 +1,5 @@
   <?xml version="1.0" encoding="ISO-8859-1"?>
  +<!-- $Id$ -->
   <project name="HiveMind">
   	<title>HiveMind</title>
   	<body>
  @@ -8,6 +9,7 @@
   			<item name="Localization" href="/localization.html"/>
   		  <item name="Inversion of Control" href="/ioc.html"/>
   		  <item name="Multi-Threading" href="/multithreading.html"/>
  +		  <item name="Bootstrapping" href="/bootstrap.html"/>
   			<item name="Module Descriptor" href="/descriptor.html" collapse="true">
   				<item name="XML Processing Rules" href="/rules.html"/>	
   			</item>
  
  
  
  1.1                  jakarta-commons-sandbox/hivemind/xdocs/bootstrap.xml
  
  Index: bootstrap.xml
  ===================================================================
  <?xml version="1.0"?>
  <!-- $Id: bootstrap.xml,v 1.1 2003/09/04 23:59:03 hlship Exp $ -->
  <!DOCTYPE document [
  	<!ENTITY % common-links SYSTEM "../common/links.xml">
  	%common-links;
  	]>
  <document>
  	<properties>
  		<title>Bootstrapping the Registry</title>
  		<author email="hlship@apache.org">Howard M. Lewis Ship</author>
  	</properties>
  	<body>
  
  <section name="Introduction">
  
  <p>
  Before you can access the extension points and services defined in your	many module deployment
  descriptors, you need a registry; here we'll describe how to construct the registry.
  </p>
  
  <p>
  The key class here is
  <a href="apidocs/org/apache/commons/hivemind/impl/RegistryBuilder.html">RegistryBuilder</a>, which contains
  code for locating and parsing the module deployment descriptors and constructing a registry from the combined
  data.
  </p>
  
  
  <p>
  Let's examine how all this comes together. The layout of the project is shown below.
  </p>
  
  <img src="images/AdderExample-ProjectLayout.png"/>
  
  </section>
  
  <section name="Services, Interfaces, Descriptors">
  
  <p>
  The first step is to define the service interface:
  </p>	
  
  <source>
  package hivemind.examples;
  
  public interface Adder
  {
      public int add(int arg0, int arg1);
  }	
  </source>
  	
  <p>
  Next we need an implementation for that service:	
  </p>	
  
  <source>
  package hivemind.examples.impl;
  
  import hivemind.examples.Adder;
  
  public class AdderImpl implements Adder
  {
  
      public int add(int arg0, int arg1)
      {
          return arg0 + arg1;
      }
  
  }
  </source>
  
  <p>
  Finally, we need the HiveMind module deployment descriptor.	
  </p>
  
  <source><![CDATA[
  <?xml version="1.0"?>
  
  <module id="hivemind.examples" version="1.0.0">
  
    <service id="Adder" interface="hivemind.examples.Adder">
    	<create-instance class="hivemind.examples.impl.AdderImpl"/>	
    </service>
  
  </module>]]></source>
  
  <p>
  Here we've chosen to have the module id, <code>hivemind.examples</code>	match the package name but
  that is not an absolute requirement.
  </p>
  
  </section>
  
  <section name="Building the Registry">
  
  <p>
  Before your code can access any services (or extension points), it must construct the registry.	
  </p>	
  	
  
  <source>
  package hivemind.examples;
  
  import java.util.Locale;
  
  import org.apache.commons.hivemind.ClassResolver;
  import org.apache.commons.hivemind.Registry;
  import org.apache.commons.hivemind.impl.DefaultClassResolver;
  import org.apache.commons.hivemind.impl.RegistryBuilder;
  
  public class Main
  {
  
      public static void main(String[] args)
      {
          int arg0 = Integer.parseInt(args[0]);
          int arg1 = Integer.parseInt(args[1]);
  
          ClassResolver resolver = new DefaultClassResolver();
          RegistryBuilder builder = new RegistryBuilder();
  
          builder.processModules(resolver);
  
          Registry registry = builder.constructRegistry(Locale.getDefault());
  
          Adder adder = (Adder) registry.getService("hivemind.examples.Adder", Adder.class);
  
          System.out.println("Result: " + adder.add(arg0, arg1));
      }
  }
  	
  </source>	
  
  <p>
  Building the registry requires four steps:
  <ul>
  <li>Create a <a href="apidocs/org/apache/commons/hivemind/ClassResolver.html">ClassResolver</a> instance. The
  	DefaultClassResolver is pretty much all you'll need, it use's the thread's context class loader.</li>	
  <li>
  Create a <a href="apidocs/org/apache/commons/hivemind/impl/RegistryBuilder.html">RegistryBuilder</a> instance.
  </li>
  <li>
  Invoke <code>processModules()</code> to find and parse all HiveMind module deployment descriptors visible on
  the classpath (as <code>META-INF/hivemodule.xml</code>).  Here, this will be the master HiveMind module descriptor (for
  the <code>hivemind</code> module), and the descriptor for this example module. You could invoke <code>processModule()</code>
  to parse additional deployment descriptors stored in unusual locations.
  </li>
  <li>
  Invoke <code>constructRegistry()</code>	to integrate and validate all the information in all
  of the HiveMind module deployment descriptors and produce a 
  <a href="apidocs/org/apache/commons/hivemind/Registry.html">Registry</a> from it.
  </li>
  
  </ul>	
  
  </p>
  
  <p>
  Now that we have the registry, we can use the full id of the Adder service, <code>hivemind.examples.Adder</code>,	
  to get the service implementation. We pass in the class that we'll be casting the service to ... this allows HiveMind 
  to produce a more meaningful error than a ClassCastException.
  </p>
  
  <p>
  Using the reference to the Adder service, we can finally invoke the <code>add()</code>	method.
  </p>
  
  </section>
  
  <section name="Building the Example">
  
  <p>
  Building and running the example using Ant is a snap; all the details are in the <code>build.xml</code>:
  </p>
  
  <source><![CDATA[<?xml version="1.0"?>
  
  <project name="HiveMind Adder Example" default="jar">
  
    <property name="java.src.dir" value="src/java"/>
    <property name="conf.dir" value="src/conf"/>
    <property name="meta-inf.dir" value="src/META-INF"/>
    <property name="target.dir" value="target"/>
    <property name="classes.dir" value="${target.dir}/classes"/>
    <property name="example.jar" value="${target.dir}/hivemind-examples.jar"/>
    <property name="lib.dir" value="lib"/>
  
    <path id="build.class.path">
      <fileset dir="${lib.dir}">
        <include name="*.jar"/>
      </fileset>
    </path>
    
    <path id="run.class.path">
      <path refid="build.class.path"/>
      <pathelement location="${example.jar}"/>
      <pathelement location="${conf.dir}"/>
    </path>
      
    <target name="clean" description="Delete all derived files.">
      <delete dir="${target.dir}" quiet="true"/>
    </target>
    
    <target name="compile" description="Compile all Java code.">  
      <mkdir dir="${classes.dir}"/>    
      <javac srcdir="${java.src.dir}" destdir="${classes.dir}" classpathref="build.class.path"/>
    </target>
    
    <target name="jar" description="Construct the JAR file." depends="compile">
      <jar destfile="${example.jar}">
        <fileset dir="${classes.dir}"/>
        <metainf dir="${meta-inf.dir}"/>
      </jar>
    </target>
    
    <target name="run" depends="jar" description="Run the Adder service.">
      <echo>Adding 11 and 23, should get 34.</echo>
    
      <java classname="hivemind.examples.Main" classpathref="run.class.path" fork="true">
        <arg value="11"/>
        <arg value="23"/>
      </java>
    </target>
  
  </project>]]></source>
  	 
  <p>
  The important part is to package both the classes and the HiveMind module deployment descriptor
  into the JAR.  The latter is accomplished using the &lt;metainf&gt; element.
  </p>
  
  <p>
  The only other oddity was to add <code>src/conf</code>	to the runtime classpath; this is to include
  a <code>log4j.properties</code>; otherwise Log4J will write console errors about missing configuration.
  </p>
  	
  </section>
  </body>
  </document>
  
  
  1.1                  jakarta-commons-sandbox/hivemind/xdocs/images/AdderExample-ProjectLayout.png
  
  	<<Binary file>>