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 <metainf> 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]