hlship      2004/06/02 12:45:31

  Modified:    src/documentation/content/xdocs index.xml bootstrap.xml
  Added:       src/documentation/resources/images
                        Bootstrap-ProjectLayout.png
  Removed:     src/documentation/resources/images
                        AdderExample-ProjectLayout.png
  Log:
  Improve the Bootstrap example.
  
  Revision  Changes    Path
  1.8       +11 -3     
jakarta-hivemind/src/documentation/content/xdocs/index.xml
  
  Index: index.xml
  ===================================================================
  RCS file: 
/home/cvs/jakarta-hivemind/src/documentation/content/xdocs/index.xml,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- index.xml 1 Jun 2004 20:22:50 -0000       1.7
  +++ index.xml 2 Jun 2004 19:45:31 -0000       1.8
  @@ -33,13 +33,21 @@
                                implements. HiveMind takes care of 
instantiating and configuring each
                                service just as necessary. HiveMind lets 
services collaborate with each
                                other via <link href="site:ioc">dependency 
injection</link>.</li>
  -                     <li> <strong><link 
href="site:configurations">Configuration</link></strong>
  -                             : HiveMind allows you to provide complex 
configuration data to your
  +                     <li> <strong><link 
href="site:configurations">Configuration</link></strong>: 
  +                             HiveMind allows you to provide complex 
configuration data to your
                                services in a format <em>you</em> define. 
HiveMind will integrate the
                                contributions of such data from multiple 
modules and convert it all into
                                data objects for you. HiveMind configurations 
allow for powerful,
                                data-driven solutions which combine seemlessly 
with the service
                                architecture.</li>
  +                     <li><strong>Microkernel</strong>: HiveMind is a 
framework for creating applications, not
  +                             an application, or even an application server, 
itself. The 'core' of HiveMind
  +                             is the <link href="site:bootstrap">startup 
logic</link>
  +                       that knows how to parse and understand the
  +                             <link href="site:descriptor">module deployment 
descriptors</link>, and use that
  +                             information to <link 
href="site:ioc">instantiate and initialize</link>
  +                             all those services and configurations.
  +                             </li>
                </ul>
                <p>In HiveMind, a service is an implementation of a Java 
interface. Unlike
                        other SOAs (Service Oriented Architectures, such as a 
SOAP, or EJBs),
  
  
  
  1.5       +301 -113  
jakarta-hivemind/src/documentation/content/xdocs/bootstrap.xml
  
  Index: bootstrap.xml
  ===================================================================
  RCS file: 
/home/cvs/jakarta-hivemind/src/documentation/content/xdocs/bootstrap.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- bootstrap.xml     26 May 2004 21:28:49 -0000      1.4
  +++ bootstrap.xml     2 Jun 2004 19:45:31 -0000       1.5
  @@ -16,36 +16,45 @@
      limitations under the License.
   -->
   <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.2//EN"
  -     "./dtd/document-v12.dtd" [
  -     <!ENTITY % common-links SYSTEM "links.ent">
  -     %common-links;
  -     ]>
  +  "./dtd/document-v12.dtd" [
  +  <!ENTITY % common-links SYSTEM "links.ent">
  +  %common-links;
  +  ]>
   <document>
  -     <header>
  -             <title>Bootstrapping the Registry</title>
  -     </header>
  -     <body>
  -             <p>Before you can access the configuration 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 &api.RegistryBuilder;, 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>
  -             <figure src="images/AdderExample-ProjectLayout.png" 
alt="[Project Layout]"/>
  -             <section>
  -                     <title>Services, Interfaces, Descriptors</title>
  -                     <p>The first step is to define the service 
interface:</p>
  -                     <source><![CDATA[
  +  <header>
  +    <title>Bootstrapping the Registry</title>
  +  </header>
  +  <body>
  +    <p>Before you can access the configuration points and services defined in
  +      your application's module deployment descriptors, you need a registry; 
here we'll
  +      describe how to construct the registry.</p>
  +    <p>The key class here is &api.RegistryBuilder;, which contains code for
  +      locating and parsing the module deployment descriptors and 
constructing a
  +      registry from the combined data. The descriptors are all found on the 
class path; they'll include
  +      the descriptors for HiveMind itself with descriptors packaged into 
your application's JARs. 
  +      </p>
  +      
  +      <note>
  +      As HiveMind grows in popularity, we may start to see
  +      third party frameworks come bundled with
  +      HiveMind module deployment descriptors ... but it's too soon for that, 
now.  
  +      </note>
  +      
  +    <p>Let's examine how all this comes together. The layout of the project 
is
  +      shown below.</p>
  +    <figure src="images/Bootstrap-ProjectLayout.png" alt="[Project Layout]"/>
  +    <section>
  +      <title>Service Interfaces and Implementations</title>
  +      <p>The first step is to define the service interface:</p>
  +      <source><![CDATA[
   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><![CDATA[
  +      <p>Next we need an implementation for that service:</p>
  +      <source><![CDATA[
   package hivemind.examples.impl;
   
   import hivemind.examples.Adder;
  @@ -53,117 +62,245 @@
   public class AdderImpl implements Adder
   {
   
  -    public int add(int arg0, int arg1)
  -    {
  -        return arg0 + arg1;
  -    }
  +  public int add(int arg0, int arg1)
  +  {
  +    return arg0 + arg1;
  +  }
   
   }]]> </source>
  -                     <p>Finally, we need the HiveMind module deployment 
descriptor, <code>
  -                             hivemodule.sdl</code>. This file is in <link 
href="site:sdl">Simple Data
  -                             Language</link> format (though equivalent XML 
is supported if the file
  -                             is named <code>hivemodule.xml</code>).</p>
  -                     <source><![CDATA[
  +
  +    <p>
  +    The example includes three additional interfaces and matching 
implementations:
  +    for a Subtracter, Multiplier, Divider, and lastly, a Calculator that 
combines them
  +    together:  
  +    </p>
  +    
  +    <source><![CDATA[
  +package hivemind.examples;
  +
  +
  +public interface Calculator extends Adder, Subtracter, Multiplier, Divider
  +{
  +
  +}    
  +]]></source>
  +
  +<p>
  +The Calculator implementation will require some wiring; it expects that each 
of the other four
  +services (Adder, Substracter, Multiplier and Divider) will be plugged into 
it:
  +</p>
  +
  +<source><![CDATA[
  +package hivemind.examples.impl;
  +
  +import hivemind.examples.Adder;
  +import hivemind.examples.Calculator;
  +import hivemind.examples.Divider;
  +import hivemind.examples.Multiplier;
  +import hivemind.examples.Subtracter;
  +
  +public class CalculatorImpl implements Calculator
  +{
  +  private Adder _adder;
  +  private Subtracter _subtracter;
  +  private Multiplier _multiplier;
  +  private Divider _divider;
  +
  +  public void setAdder(Adder adder)
  +  {
  +    _adder = adder;
  +  }
  +
  +  public void setDivider(Divider divider)
  +  {
  +    _divider = divider;
  +  }
  +
  +  public void setMultiplier(Multiplier multiplier)
  +  {
  +    _multiplier = multiplier;
  +  }
  +
  +  public void setSubtracter(Subtracter subtracter)
  +  {
  +    _subtracter = subtracter;
  +  }
  +
  +  public int add(int arg0, int arg1)
  +  {
  +    return _adder.add(arg0, arg1);
  +  }
  +
  +  public int subtract(int arg0, int arg1)
  +  {
  +    return _subtracter.subtract(arg0, arg1);
  +  }
  +
  +  public int multiply(int arg0, int arg1)
  +  {
  +    return _multiplier.multiply(arg0, arg1);
  +  }
  +
  +  public int divide(int arg0, int arg1)
  +  {
  +    return _divider.divide(arg0, arg1);
  +  }
  +}
  +]]></source>
  +
  +</section>
  +
  +  <section>
  +      <title>Module Deployment Descriptor</title>
  +      <p>Finally, we need the HiveMind module deployment descriptor, <code>
  +        hivemodule.sdl</code>. This file is in <link href="site:sdl">Simple 
Data
  +        Language</link> format (though equivalent XML is supported if the 
file
  +        is named <code>hivemodule.xml</code>).</p>
  +        
  +      <p>
  +      The module descriptor creates each of the services in terms of
  +      an interface, and an implementation. In addition, each service gets its
  +      own logging interceptor.  
  +      </p>
  +      <source><![CDATA[
   module (id=hivemind.examples version="1.0.0")
   {
  -  service-point (id=Adder interface=hivemind.examples.Adder) 
  +  service-point (id=Adder interface=hivemind.examples.Adder)
     {
       create-instance (class=hivemind.examples.impl.AdderImpl)
  -  } 
  +    interceptor (service-id=hivemind.LoggingInterceptor)
  +  }
  +  
  +  service-point (id=Subtracter interface=hivemind.examples.Subtracter)
  +  {
  +    create-instance (class=hivemind.examples.impl.SubtracterImpl)
  +    interceptor (service-id=hivemind.LoggingInterceptor)
  +  }
  +  
  +  service-point (id=Multiplier interface=hivemind.examples.Multiplier)
  +  {
  +    create-instance (class=hivemind.examples.impl.MultiplierImpl)
  +    interceptor (service-id=hivemind.LoggingInterceptor)
  +  }
  +  
  +  service-point (id=Divider interface=hivemind.examples.Divider)
  +  {
  +    create-instance (class=hivemind.examples.impl.DividerImpl)
  +    interceptor (service-id=hivemind.LoggingInterceptor)
  +  }
  +  
  +  service-point (id=Calculator interface=hivemind.examples.Calculator)
  +  {
  +    invoke-factory (service-id=hivemind.BuilderFactory)
  +    {
  +      construct (class=hivemind.examples.impl.CalculatorImpl)
  +      {
  +        set-service (property=adder service-id=Adder)
  +        set-service (property=subtracter service-id=Subtracter)
  +        set-service (property=multiplier service-id=Multiplier)
  +        set-service (property=divider service-id=Divider)
  +      }
  +    }
  +    
  +    interceptor (service-id=hivemind.LoggingInterceptor)
  +  }
   }]]></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>
  -                     <title>Building the Registry</title>
  -                     <p>Before your code can access any services (or 
configuration points), it
  -                             must construct the registry.</p>
  -                     <source><![CDATA[
  +      <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>
  +      
  +      <p>
  +      The interesting part is the use of the &hivemind.BuilderFactory; to 
construct
  +      the Calculator service and connect it to the other   four services.
  +      </p>
  +    </section>
  +    <section>
  +      <title>Building the Registry</title>
  +      <p>Before your code can access any services (or configuration points), 
it
  +        must construct the &api.Registry;.  The Registry is the applications 
gateway into the services
  +        and configurations managed by HiveMind.</p>
  +      <source><![CDATA[
   package hivemind.examples;
   
  -import java.util.Locale;
  -
  -import org.apache.hivemind.ClassResolver;
   import org.apache.hivemind.Registry;
  -import org.apache.hivemind.impl.DefaultClassResolver;
   import org.apache.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();
  +  public static void main(String[] args)
  +  {
  +    int arg0 = Integer.parseInt(args[0]);
  +    int arg1 = Integer.parseInt(args[1]);
   
  -        builder.processModules(resolver);
  +    Registry registry = RegistryBuilder.constructDefaultRegistry();
   
  -        Registry registry = builder.constructRegistry(Locale.getDefault());
  +    Calculator c =
  +      (Calculator) registry.getService("hivemind.examples.Calculator", 
Calculator.class);
   
  -        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:</p>
  -                     <ul>
  -                             <li>Create a &api.ClassResolver; instance. 
DefaultClassResolver uses the
  -                                     thread's context class loader.</li>
  -                             <li>Create a &api.RegistryBuilder; 
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.sdl</code> or 
<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 
&api.Registry; from it.</li>
  -                     </ul>
  -                     <p>Alternately, the static method <link
  -                             
href="&apiroot;/impl/RegistryBuilder.html#constructDefaultRegistry()">
  -                             constructDefaultRegistry()</link> can be 
invoked. It's just those same
  -                             four lines of code.</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>
  -                     <title>Building the Example</title>
  -                     <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"?>
  +    System.out.println("Inputs " + arg0 + " and " + arg1);
  +
  +    System.out.println("Add   : " + c.add(arg0, arg1));
  +    System.out.println("Subtract: " + c.subtract(arg0, arg1));
  +    System.out.println("Multiply: " + c.multiply(arg0, arg1));
  +    System.out.println("Divide  : " + c.divide(arg0, arg1));
  +  }
  +}
  +]]> </source>
  +<p>&api.RegistryBuilder; contains a static method for constructing a 
Registry, which
  +  is suitable for most situations.</p>
  +      <p>Now that we have the registry, we can use the fully qualified id of 
the Calculator
  +        service, <code>hivemind.examples.Calculator</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 Calculator service, we can finally 
invoke the 
  +        <code>add()</code>, <code>subtract()</code>, <code>multiply()</code> 
  +        and <code>divide()</code> methods.</p>
  +    </section>
  +    <section>
  +      <title>Building the Example</title>
  +      <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="test.src.dir" value="src/test"/>
     <property name="conf.dir" value="src/conf"/>
  -  <property name="meta-inf.dir" value="src/META-INF"/>
  +  <property name="descriptor.dir" value="src/descriptor"/>
     <property name="target.dir" value="target"/>
     <property name="classes.dir" value="${target.dir}/classes"/>
  +  <property name="test.classes.dir" value="${target.dir}/test-classes"/>
     <property name="example.jar" value="${target.dir}/hivemind-examples.jar"/>
     <property name="lib.dir" value="lib"/>
  +  <property name="junit.temp.dir" value="${target.dir}/junit-temp"/>
  +  <property name="junit.reports.dir" value="${target.dir}/junit-reports"/>
   
     <path id="build.class.path">
       <fileset dir="${lib.dir}">
         <include name="*.jar"/>
       </fileset>
     </path>
  -  
  +      
  +  <path id="test.build.class.path">
  +    <path refid="build.class.path"/>
  +    <path location="${classes.dir}"/>
  +  </path>
  +        
     <path id="run.class.path">
       <path refid="build.class.path"/>
  -    <pathelement location="${example.jar}"/>
  +    <pathelement location="${classes.dir}"/>
  +    <pathelement location="${descriptor.dir}"/>
       <pathelement location="${conf.dir}"/>
     </path>
  -    
  +  
  +  <path id="test.run.class.path">
  +    <path refid="run.class.path"/>
  +    <path location="${test.classes.dir}"/>
  +  </path>  
  +  
     <target name="clean" description="Delete all derived files.">
       <delete dir="${target.dir}" quiet="true"/>
     </target>
  @@ -173,30 +310,81 @@
       <javac srcdir="${java.src.dir}" destdir="${classes.dir}" 
classpathref="build.class.path"/>
     </target>
     
  -  <target name="jar" description="Construct the JAR file." depends="compile">
  +  <target name="compile-tests" description="Compile test classes." 
depends="compile">
  +    <mkdir dir="${test.classes.dir}"/>
  +    <javac srcdir="${test.src.dir}" destdir="${test.classes.dir}" 
classpathref="test.build.class.path"/>
  +  </target>
  +  
  +  <target name="run-tests" description="Run unit tests." 
depends="compile-tests">
  +  
  +    <mkdir dir="${junit.temp.dir}"/>
  +    <mkdir dir="${junit.reports.dir}"/>
  +
  +    <junit haltonfailure="off" failureproperty="junit-failure" 
tempdir="${junit.temp.dir}">    
  +      <classpath refid="test.run.class.path"/>
  +    
  +      <formatter type="xml"/>
  +      <formatter type="plain"/>
  +      <formatter type="brief" usefile="false"/>
  +    
  +      <batchtest todir="${junit.reports.dir}">
  +        <fileset dir="${test.classes.dir}">
  +          <include name="**/Test*.class"/>
  +        </fileset>
  +      </batchtest>
  +    </junit>
  +
  +    <fail if="junit-failure" message="Some tests failed."/>
  +
  +  </target>
  +  
  +  <target name="jar" description="Construct the JAR file." 
depends="compile,run-tests">
       <jar destfile="${example.jar}">
         <fileset dir="${classes.dir}"/>
  -      <metainf dir="${meta-inf.dir}"/>
  +    <fileset dir="${descriptor.dir}"/>
       </jar>
     </target>
     
  -  <target name="run" depends="jar" description="Run the Adder service.">
  -    <echo>Adding 11 and 23, should get 34.</echo>
  -  
  +  <target name="run" depends="compile" description="Run the Adder service.">
       <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 the 
<code>log4j.properties</code> 
  -                             configuration file; otherwise Log4J will write 
console errors about
  -                             missing configuration.</p>
  -             </section>
  -     </body>
  +</project>
  +]]></source>
  +      <p>The important part is to package both the classes and the HiveMind
  +        module deployment descriptor into the JAR.</p>
  +      <p>The only other oddity was to add <code>src/conf</code> to the 
runtime
  +        classpath; this is to include the <code>log4j.properties</code> 
  +        configuration file; otherwise Log4J will write console errors about
  +        missing configuration.</p>
  +    </section>
  +    
  +    <section>
  +      <title>Running the Examples</title>  
  +      
  +<source><![CDATA[
  +bash-2.05b$ ant run
  +Buildfile: build.xml
  +
  +compile:
  +    [mkdir] Created dir: C:\workspace\hivemind-example\target\classes
  +    [javac] Compiling 15 source files to 
C:\workspace\hivemind-example\target\classes
  +
  +run:
  +     [java] Inputs 11 and 23
  +     [java] Add     : 34
  +     [java] Subtract: -12
  +     [java] Multiply: 253
  +     [java] Divide  : 0
  +
  +
  +
  +BUILD SUCCESSFUL
  +Total time: 3 seconds
  +]]></source>
  +    </section>
  +  </body>
   </document>
  
  
  
  1.1                  
jakarta-hivemind/src/documentation/resources/images/Bootstrap-ProjectLayout.png
  
        <<Binary file>>
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to