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