Author: rhauch
Date: 2009-06-07 18:33:45 -0400 (Sun, 07 Jun 2009)
New Revision: 989
Added:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/conclusion.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/repository_example.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/sequencer_example.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/use_cases.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/custom.dtd
Removed:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/custom_sequencers.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/future.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/understanding_dna.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_for_sequencing.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_repositories.xml
Modified:
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/ConsoleInput.java
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java
trunk/docs/gettingstarted/src/main/docbook/en-US/content/author_group.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/downloading_and_running.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/introduction.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/legal_notice.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/content/preface.xml
trunk/docs/gettingstarted/src/main/docbook/en-US/master.xml
trunk/docs/reference/src/main/docbook/en-US/content/development_tools.xml
Log:
DNA-389 Updated the Getting Started document to reflect the new configuration approach,
and restructured the document to better focus on the examples and high-level introduction,
leaving the more detailed discussions for the Reference Guide (and removing more of the
duplication).
Modified:
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/ConsoleInput.java
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/ConsoleInput.java 2009-06-07
15:05:15 UTC (rev 988)
+++
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/ConsoleInput.java 2009-06-07
22:33:45 UTC (rev 989)
@@ -125,14 +125,13 @@
try {
// Terminate ...
System.out.println();
- System.out.print("done.\nShutting down repositories and
services ... ");
+ System.out.print("done.\nShutting down repositories ...
");
client.shutdown();
System.out.print("done.");
System.out.println();
System.out.println();
} catch (Exception err) {
- System.out.println("Error shutting down sequencing
service and repository: "
- + err.getLocalizedMessage());
+ System.out.println("Error shutting down repository:
" + err.getLocalizedMessage());
err.printStackTrace(System.err);
}
}
Modified:
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java 2009-06-07
15:05:15 UTC (rev 988)
+++
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java 2009-06-07
22:33:45 UTC (rev 989)
@@ -202,7 +202,7 @@
if (loginContext == null) {
if (jaasContextName != null) {
loginContext = new LoginContext(jaasContextName,
this.userInterface.getCallbackHandler());
- loginContext.login();
+ loginContext.login(); // This authenticates the user
}
}
return loginContext;
Modified:
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java
===================================================================
---
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java 2009-06-07
15:05:15 UTC (rev 988)
+++
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java 2009-06-07
22:33:45 UTC (rev 989)
@@ -68,7 +68,7 @@
throw new IllegalStateException(ex);
}
- // Configure the DNA JCR engine. This could be done by loading a configuration
from a file, or by
+ // Configure the DNA configuration. This could be done by loading a configuration
from a file, or by
// using a (local or remote) configuration repository, or by setting up the
configuration programmatically.
// This example uses the programmatic approach...
String repositoryId = "content";
Modified: trunk/docs/gettingstarted/src/main/docbook/en-US/content/author_group.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/author_group.xml 2009-06-07
15:05:15 UTC (rev 988)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/author_group.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -24,7 +24,10 @@
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
-<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
<authorgroup>
<corpauthor>Randall M. Hauch</corpauthor>
<corpauthor>John Verhaeg</corpauthor>
Added: trunk/docs/gettingstarted/src/main/docbook/en-US/content/conclusion.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/conclusion.xml
(rev 0)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/conclusion.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ JBoss DNA (
http://www.jboss.org/dna)
+ ~
+ ~ See the COPYRIGHT.txt file distributed with this work for information
+ ~ regarding copyright ownership. Some portions may be licensed
+ ~ to Red Hat, Inc. under one or more contributor license agreements.
+ ~ See the AUTHORS.txt file in the distribution for a full listing of
+ ~ individual contributors.
+ ~
+ ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ ~ is licensed to you under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ JBoss DNA is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
+<chapter id="conclusion">
+ <title>Wrapping Up</title>
+ <para>
+ This document provided a very high-level overview of JBoss DNA, introducing you to what
would be required to use JBoss DNA
+ in your own application. We saw two simple examples that showed two different aspects
of JBoss DNA: the sequencing system
+ and the connector system. Each of these examples showed how to create a JBoss DNA
configuration, how to start up
+ the JBoss DNA engine, and how to then access a
<code>javax.jcr.Repository</code> instance, and after that your application
+ just uses the standard JCR API.
+ </para>
+ <para>
+ For a more in-depth description of JBoss DNA and the internal workings, see our
&ReferenceGuide;.
+ This also describes how to write your own custom sequencers or connectors.
+ If you have any questions or comments, please feel free to contact JBoss DNA's
+ <ulink url="mailto:dna-users@jboss.org">user mailing
list</ulink>
+ or use the
+ <ulink
url="http://www.jboss.com/index.html?module=bb&op=viewforum&...
forums</ulink>
+ or (preferably) the
+ <ulink
url="http://www.jboss.org/dna/lists.html">mailing
lists</ulink>. If you find a bug or have a suggestion, please
+ create a new issue in the project's
+ <ulink
url="http://jira.jboss.org/jira/browse/DNA">JIRA issue
management system</ulink>
+ . If there's something in particular you're interested in, talk with the
community - there may be others interested in the
+ same thing.
+ </para>
+ <sect1 id="future">
+ <title>Future directions</title>
+ <para>
+ What's next for JBoss DNA? Well, the sequencing system is just the beginning.
With this release, the sequencing system
+ is stable enough so that more <link
linkend="sequencers">sequencers</link> can be developed and used within
your own applications.
+ We've also established the foundation for JBoss DNA repositories, including a
number of <link linkend="repository-connectors">connectors</link>.
+ We'll continue to expand our library of sequencers and connectors, as well as
expand our support of JCR.
+ Other components on our roadmap include a web user interface, a REST-ful server, and a
view system that allows domain-specific
+ views of information in the repository. These components are farther out on our
roadmap, and at this time have not been
+ targeted to a particular release.
+ </para>
+ </sect1>
+ <sect1 id="get_involved">
+ <title>Getting involved</title>
+ <para>
+ If you're interested in getting involved with the JBoss DNA project, consider
picking up one of the sequencers or connectors on our
+ <ulink url="&Roadmap;">roadmap</ulink>.
+ Or, check out <ulink url="&JIRA;">JIRA</ulink>
+ for the list of features we've thought of. If you think of one that's not
there, please add it to JIRA!
+ </para>
+ </sect1>
+</chapter>
Property changes on:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/conclusion.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Deleted: trunk/docs/gettingstarted/src/main/docbook/en-US/content/custom_sequencers.xml
===================================================================
---
trunk/docs/gettingstarted/src/main/docbook/en-US/content/custom_sequencers.xml 2009-06-07
15:05:15 UTC (rev 988)
+++
trunk/docs/gettingstarted/src/main/docbook/en-US/content/custom_sequencers.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -1,346 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ JBoss DNA (
http://www.jboss.org/dna)
- ~
- ~ See the COPYRIGHT.txt file distributed with this work for information
- ~ regarding copyright ownership. Some portions may be licensed
- ~ to Red Hat, Inc. under one or more contributor license agreements.
- ~ See the AUTHORS.txt file in the distribution for a full listing of
- ~ individual contributors.
- ~
- ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- ~ is licensed to you under the terms of the GNU Lesser General Public License as
- ~ published by the Free Software Foundation; either version 2.1 of
- ~ the License, or (at your option) any later version.
- ~
- ~ JBoss DNA is distributed in the hope that it will be useful,
- ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- ~ for more details.
- ~
- ~ You should have received a copy of the GNU Lesser General Public License
- ~ along with this distribution; if not, write to:
- ~ Free Software Foundation, Inc.
- ~ 51 Franklin Street, Fifth Floor
- ~ Boston, MA 02110-1301 USA
- -->
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="custom_sequencers">
- <title>Creating custom sequencers</title>
- <para>The current release of JBoss DNA comes with six sequencers. However,
it's very easy to create your own
- sequencers and to then configure JBoss DNA to use them in your own application.
- </para>
- <para>
- Creating a custom sequencer involves the following steps:
- <itemizedlist>
- <listitem>
- <para>Create a Maven 2 project for your sequencer;</para>
- </listitem>
- <listitem>
- <para>Implement the
<code>org.jboss.dna.spi.sequencers.StreamSequencer</code> interface with your
own implementation, and create unit tests to verify
- the functionality and expected behavior;</para>
- </listitem>
- <listitem>
- <para>Add the sequencer configuration to the JBoss DNA
<code>SequencingService</code> in your application
- as described in the <link linkend="using_dna">previous
chapter</link>; and</para>
- </listitem>
- <listitem>
- <para>Deploy the JAR file with your implementation (as well as any
dependencies), and make them available to JBoss DNA
- in your application.</para>
- </listitem>
- </itemizedlist>
- It's that simple.
- </para>
- <sect1 id="custom_sequencer_project">
- <title>Creating the Maven 2 project</title>
- <para>The first step is to create the Maven 2 project that you can use to
compile your code and build the JARs.
- Maven 2 automates a lot of the work, and since you're already <link
linkend="downloading_and_running">set up to use Maven</link>,
- using Maven for your project will save you a lot of time and effort. Of course, you
don't have to use Maven 2, but then you'll
- have to get the required libraries and manage the compiling and building process
yourself.</para>
- <note>
- <para>JBoss DNA may provide in the future a Maven archetype for creating
sequencer projects. If you'd find this useful
- and would like to help create it, please <link
linkend="preface">join the community</link>.</para>
- </note>
- <note>
- <para>The <code>dna-sequencer-images</code> project is a small,
self-contained sequencer implementation that
- has only the minimal dependencies. Starting with this project's source and
modifying it to suit your needs may be the easiest way to get started.
- See the subversion repository: <ulink
url="http://anonsvn.jboss.org/repos/dna/trunk/extensions/dna-sequenc...
- </para>
- </note>
- <para>You can create your Maven project any way you'd like. For examples,
see the <ulink
url="http://maven.apache.org/guides/getting-started/index.html#How_d...
2 documentation</ulink>.
- Once you've done that, just add the dependencies in your project's
<code>pom.xml</code> dependencies section:</para>
- <programlisting role="XML"><![CDATA[
-<dependency>
- <groupId>org.jboss.dna</groupId>
- <artifactId>dna-common</artifactId>
- <version>0.5</version>
-</dependency>
-<dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
-</dependency>
- ]]></programlisting>
- <para>These are minimum dependencies required for compiling a sequencer. Of
course, you'll have to add
- other dependencies that your sequencer needs.</para>
- <para>As for testing, you probably will want to add more dependencies, such as
those listed here:</para>
- <programlisting role="XML"><![CDATA[
-<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.4</version>
- <scope>test</scope>
-</dependency>
-<dependency>
- <groupId>org.hamcrest</groupId>
- <artifactId>hamcrest-library</artifactId>
- <version>1.1</version>
- <scope>test</scope>
-</dependency>
-<!-- Logging with Log4J -->
-<dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>1.4.3</version>
- <scope>test</scope>
-</dependency>
-<dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>1.2.14</version>
- <scope>test</scope>
-</dependency>
- ]]></programlisting>
- <para>Testing JBoss DNA sequencers does not require a JCR repository or the
JBoss DNA services. (For more detail,
- see the <link linkend="testing_custom_sequencers">testing
section</link>.) However, if you want to do
- integration testing with a JCR repository and the JBoss DNA services, you'll need
additional dependencies for these libraries.</para>
- <programlisting role="XML"><![CDATA[
-<!-- JBoss DNA JCR Repository -->
-<dependency>
- <groupId>org.jboss.dna</groupId>
- <artifactId>dna-jcr</artifactId>
- <version>0.5</version>
- <scope>test</scope>
-</dependency>
-<!-- Java Content Repository API -->
-<dependency>
- <groupId>javax.jcr</groupId>
- <artifactId>jcr</artifactId>
- <version>1.0.1</version>
- <scope>test</scope>
-</dependency>
- ]]></programlisting>
- <para>At this point, your project should be set up correctly, and you're
ready to move on to
- <link linkend="custom_sequencer_implementation">writing the Java
implementation</link> for your sequencer.</para>
- </sect1>
- <sect1 id="custom_sequencer_implementation">
- <title>Implementing the StreamSequencer interface</title>
- <para>After creating the project and setting up the dependencies, the next step
is to create a Java class that implements
- the <code>org.jboss.dna.spi.sequencers.StreamSequencer</code> interface.
This interface is very straightforward
- and involves a single method:</para>
- <programlisting role="JAVA"><![CDATA[
-public interface StreamSequencer {
-
- /**
- * Sequence the data found in the supplied stream, placing the output
- * information into the supplied map.
- *
- * @param stream the stream with the data to be sequenced; never null
- * @param output the output from the sequencing operation; never null
- * @param context the context for the sequencing operation; never null
- */
- void sequence( InputStream stream, SequencerOutput output, SequencerContext context
);
- ]]></programlisting>
- <para>The job of a stream sequencer is to process the data in the supplied
stream, and place into the <code>SequencerOutput</code>
- any information that is to go into the JCR repository. JBoss DNA figures out when
your sequencer should be called
- (of course, using the sequencing configuration you'll add in a bit), and then
makes sure the generated information
- is saved in the correct place in the repository.
- </para>
- <para>The <code>SequencerContext</code> provides information about
- the current sequencing operation, including the location and properties of the node
being sequenced, the MIME type
- of the node being sequenced, and a location to record problems that aren't severe
enough to warrant throwing an exception.
- </para>
- <para>The <code>SequencerOutput</code> class is fairly easy to use.
There are basically two methods you need to call.
- One method sets the property values, while the other sets references to other nodes
in the repository. Use these
- methods to describe the properties of the nodes you want to create, using relative
paths for the nodes and
- valid JCR property names for properties and references. JBoss DNA will ensure that
nodes are created or updated
- whenever they're needed.</para>
- <programlisting role="JAVA"><![CDATA[
-public interface SequencerOutput {
-
- /**
- * Set the supplied property on the supplied node. The allowable
- * values are any of the following:
- * - primitives (which will be autoboxed)
- * - String instances
- * - String arrays
- * - byte arrays
- * - InputStream instances
- * - Calendar instances
- *
- * @param nodePath the path to the node containing the property;
- * may not be null
- * @param property the name of the property to be set
- * @param values the value(s) for the property; may be empty if
- * any existing property is to be removed
- */
- void setProperty( String nodePath, String property, Object... values );
-
- /**
- * Set the supplied reference on the supplied node.
- *
- * @param nodePath the path to the node containing the property;
- * may not be null
- * @param property the name of the property to be set
- * @param paths the paths to the referenced property, which may be
- * absolute paths or relative to the sequencer output node;
- * may be empty if any existing property is to be removed
- */
- void setReference( String nodePath, String property, String... paths );
-}
- ]]></programlisting>
- <para>JBoss DNA will create nodes of type
<code>nt:unstructured</code> unless you specify the value for the
- <code>jcr:primaryType</code> property. You can also specify the values
for the <code>jcr:mixinTypes</code> property
- if you want to add mixins to any node.</para>
- <para>For a complete example of a sequencer, let's look at the
<code>org.jboss.dna.sequencers.image.ImageMetadataSequencer</code>
- implementation:</para>
- <programlisting role="JAVA"><![CDATA[
-public class ImageMetadataSequencer implements StreamSequencer {
-
- public static final String METADATA_NODE = "image:metadata";
- public static final String IMAGE_PRIMARY_TYPE = "jcr:primaryType";
- public static final String IMAGE_MIXINS = "jcr:mixinTypes";
- public static final String IMAGE_MIME_TYPE = "jcr:mimeType";
- public static final String IMAGE_ENCODING = "jcr:encoding";
- public static final String IMAGE_FORMAT_NAME = "image:formatName";
- public static final String IMAGE_WIDTH = "image:width";
- public static final String IMAGE_HEIGHT = "image:height";
- public static final String IMAGE_BITS_PER_PIXEL = "image:bitsPerPixel";
- public static final String IMAGE_PROGRESSIVE = "image:progressive";
- public static final String IMAGE_NUMBER_OF_IMAGES =
"image:numberOfImages";
- public static final String IMAGE_PHYSICAL_WIDTH_DPI =
"image:physicalWidthDpi";
- public static final String IMAGE_PHYSICAL_HEIGHT_DPI =
"image:physicalHeightDpi";
- public static final String IMAGE_PHYSICAL_WIDTH_INCHES =
"image:physicalWidthInches";
- public static final String IMAGE_PHYSICAL_HEIGHT_INCHES =
"image:physicalHeightInches";
-
- /**
- * {@inheritDoc}
- */
- public void sequence( InputStream stream, SequencerOutput output,
- SequencerContext context ) {
- ImageMetadata metadata = new ImageMetadata();
- metadata.setInput(stream);
- metadata.setDetermineImageNumber(true);
- metadata.setCollectComments(true);
-
- // Process the image stream and extract the metadata ...
- if (!metadata.check()) {
- metadata = null;
- }
-
- // Generate the output graph if we found useful metadata ...
- if (metadata != null) {
- // Place the image metadata into the output map ...
- output.setProperty(METADATA_NODE, IMAGE_PRIMARY_TYPE,
"image:metadata");
- // output.psetProperty(METADATA_NODE, IMAGE_MIXINS, "");
- output.setProperty(METADATA_NODE, IMAGE_MIME_TYPE, metadata.getMimeType());
- // output.setProperty(METADATA_NODE, IMAGE_ENCODING, "");
- output.setProperty(METADATA_NODE, IMAGE_FORMAT_NAME,
metadata.getFormatName());
- output.setProperty(METADATA_NODE, IMAGE_WIDTH, metadata.getWidth());
- output.setProperty(METADATA_NODE, IMAGE_HEIGHT, metadata.getHeight());
- output.setProperty(METADATA_NODE, IMAGE_BITS_PER_PIXEL,
metadata.getBitsPerPixel());
- output.setProperty(METADATA_NODE, IMAGE_PROGRESSIVE,
metadata.isProgressive());
- output.setProperty(METADATA_NODE, IMAGE_NUMBER_OF_IMAGES,
metadata.getNumberOfImages());
- output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_WIDTH_DPI,
metadata.getPhysicalWidthDpi());
- output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_HEIGHT_DPI,
metadata.getPhysicalHeightDpi());
- output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_WIDTH_INCHES,
metadata.getPhysicalWidthInch());
- output.setProperty(METADATA_NODE, IMAGE_PHYSICAL_HEIGHT_INCHES,
metadata.getPhysicalHeightInch());
- }
- }
-}
- ]]></programlisting>
- <para>
- Notice how the image metadata is extracted and the output graph is generated. A
single node is created with the name <code>image:metadata</code>
- and with the <code>image:metadata</code> node type. No mixins are
defined for the node, but several properties are set on the node
- using the values obtained from the image metadata. After this method returns, the
constructed graph will be saved to the repository
- in all of the places defined by its configuration. (This is why only relative paths
are used in the sequencer.)
- </para>
- </sect1>
- <sect1 id="testing_custom_sequencers">
- <title>Testing custom sequencers</title>
- <para>The sequencing framework was designed to make testing sequencers much
easier. In particular, the
- <code>StreamSequencer</code> interface does not make use of the JCR API.
So instead of requiring a fully-configured
- JCR repository and JBoss DNA system, unit tests for a sequencer can focus on testing
that the content is
- processed correctly and the desired output graph is generated.</para>
- <note>
- <para>For a complete example of a sequencer unit test, see the
<code>ImageMetadataSequencerTest</code> unit test
- in the <code>org.jboss.dna.sequencer.images</code> package of the
<code>dna-sequencers-image</code> project.
- </para>
- </note>
- <para>The following code fragment shows one way of testing a sequencer, using
JUnit 4.4 assertions and
- some of the classes made available by JBoss DNA. Of course,
- this example code does not do any error handling and does not make all the
assertions a real test would.</para>
- <programlisting role="JAVA"><![CDATA[
-Sequencer sequencer = new ImageMetadataSequencer();
-MockSequencerOutput output = new MockSequencerOutput();
-MockSequencerContext context = new MockSequencerContext();
-InputStream stream = null;
-try {
- stream =
this.getClass().getClassLoader().getResource("caution.gif").openStream();
- sequencer.sequence(stream,output,context); // writes to 'output'
- assertThat(output.getPropertyValues("image:metadata",
"jcr:primaryType"),
- is(new Object[] {"image:metadata"}));
- assertThat(output.getPropertyValues("image:metadata",
"jcr:mimeType"),
- is(new Object[] {"image/gif"}));
- // ... make more assertions here
- assertThat(output.hasReferences(), is(false));
-} finally {
- stream.close();
-}
- ]]></programlisting>
- <para>It's also useful to test that a sequencer produces no output for
something it should not understand:</para>
- <programlisting role="JAVA"><![CDATA[
-Sequencer sequencer = new ImageMetadataSequencer();
-MockSequencerOutput output = new MockSequencerOutput();
-MockSequencerContext context = new MockSequencerContext();
-InputStream stream = null;
-try {
- stream =
this.getClass().getClassLoader().getResource("caution.pict").openStream();
- sequencer.sequence(stream,output,context); // writes to 'output'
- assertThat(output.hasProperties(), is(false));
- assertThat(output.hasReferences(), is(false));
-} finally {
- stream.close();
-}
- ]]></programlisting>
- <para>These are just two simple tests that show ways of testing a sequencer.
Some tests may get quite involved,
- especially if a lot of output data is produced.
- </para>
- <para>It may also be useful to create some integration tests
- that <link linkend="using_dna">configure JBoss DNA</link> to
use a custom sequencer, and to then upload
- content using the JCR API, verifying that the custom sequencer did run. However,
remember that JBoss DNA
- runs sequencers asynchronously in the background, and you must sychronize your tests
to ensure that the
- sequencers have a chance to run before checking the results. (One way of doing this
(although, granted, not always reliable) is to wait for a second
- after uploading your content, shutdown the <code>SequencingService</code>
and await its termination,
- and then check that the sequencer output has been saved to the JCR repository. For
an example of this technique,
- see the <code>SequencingClientTest</code> unit test in the example
application.)
- </para>
- </sect1>
- <sect1 id="deploying_custom_sequencers">
- <title>Deploying custom sequencers</title>
- <para>The first step of deploying a sequencer consists of adding/changing the
sequencer configuration (e.g., <code>SequencerConfig</code>)
- in the <code>SequencingService</code>. This was covered in the <link
linkend="sequencing_service">previous chapter</link>.
- </para>
- <para>
- The second step is to make the sequencer implementation available to JBoss DNA. At
this time, the JAR containing
- your new sequencer, as well as any JARs that your sequencer depends on, should be
placed on your application classpath.</para>
- <note>
- <para>A future goal of JBoss DNA is to allow sequencers, connectors, and
other extensions to be easily deployed into
- a runtime repository. This process will not only be much simpler, but it will
also provide JBoss DNA
- with the information necessary to update configurations and create the
appropriate class loaders for each extension.
- Having separate class loaders for each extension helps prevent the pollution of
the common classpath,
- facilitates an isolated runtime environment to eliminate any dependency
conflicts, and may potentially
- enable hot redeployment of newer extension versions.
- </para>
- </note>
- </sect1>
-</chapter>
Modified:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/downloading_and_running.xml
===================================================================
---
trunk/docs/gettingstarted/src/main/docbook/en-US/content/downloading_and_running.xml 2009-06-07
15:05:15 UTC (rev 988)
+++
trunk/docs/gettingstarted/src/main/docbook/en-US/content/downloading_and_running.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -24,14 +24,17 @@
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
<chapter id="downloading_and_running">
<title>Running the example applications</title>
<para>
This chapter provides instructions for downloading and running a sample application
that demonstrates how JBoss DNA works
with a JCR repository to automatically sequence changing content to extract useful
information. So read on to get the simple
- application running, and then in the <link linkend="using_dna">next
chapter</link>
- we'll dive into the source code for the example and show how to use JBoss DNA in
your own applications. </para>
+ application running.
+ </para>
<para>JBoss DNA uses Maven 2 for its build system, as is this example. Using Maven
2 has several advantages, including
the ability to manage dependencies. If a library is needed, Maven automatically finds
and downloads that library, plus
everything that library needs. This means that it's very easy to build the
examples - or even create a maven project that
@@ -244,165 +247,10 @@
</itemizedlist>
</para>
</sect1>
- <sect1 id="running_sequencer_example">
- <title>Running the sequencing example</title>
- <para>The sequencing example consists of a client application that sets up an
in-memory JCR repository and that allows a user to
- upload files into that repository. The client also sets up the DNA services with
two sequencers so that if any of the
- uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will automatically
extract the image's metadata (e.g., image
- format, physical size, pixel density, etc.) and store that in the repository.
Alternatively, if the uploaded file
- is an MP3 audio file, DNA will extract some of the ID3 metadata (e.g., the author,
title, album, year and comment)
- and store that in the repository.</para>
- <para>
- To run the client application, go to the
<code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code>
- directory and type <code>./run.sh</code>. You should see the
command-line client and its menus in your terminal:
- <figure id="xample-sequencer-cli-client">
- <title>Example client</title>
- <graphic align="center" scale="100"
fileref="example-sequencer-client.png"/>
- </figure>
- From this menu, you can upload a file into the repository, search for media in the
repository, print sequencing statistics,
- or quit the application.</para>
- <para>
- The first step is to upload one of the example images. If you type 'u' and
press return, you'll be prompted to supply the
- path to the file you want to upload. Since the application is running from within
the
-
<code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code>
directory, you can specify any of the files
- in that directory without specifying the path:
- <figure id="example-sequencer-upload">
- <title>Uploading an image using the example client</title>
- <graphic align="center" scale="100"
fileref="example-sequencer-upload.png"/>
- </figure>
- You can specify any fully-qualified or relative path. The application will notify
you if it cannot find the file you
- specified. The example client configures JBoss DNA to sequence MP3 audio files,
Java source files, or image files with one of
- the following extensions (technically, nodes that have names ending in the
following):
- <code>jpg</code>, <code>jpeg</code>,
<code>gif</code>, <code>bmp</code>, <code>pcx</code>,
<code>png</code>,
- <code>iff</code>, <code>ras</code>,
<code>pbm</code>, <code>pgm</code>, <code>ppm</code>,
and <code>psd</code>.
- Files with other extensions in the repository path will be ignored. For your
convenience, the example provides several
- files that will be sequenced (<code>caution.png</code>,
<code>caution.jpg</code>, <code>caution.gif</code>, and
- <code>sample1.mp3</code>) and one image that will not be sequenced
(<code>caution.pict</code>). Feel free to try other files.
- </para>
- <para>
- After you have specified the file you want to upload, the example application asks
you where in the repository you'd like to
- place the file. (If you want to use the suggested location, just press
<code>return</code>.) The client application
- uses the JCR API to upload the file to that location in the repository, creating
any nodes (of type <code>nt:folder</code>)
- for any directories that don't exist, and creating a node (of type
<code>nt:file</code>) for the file. And, per the JCR specification,
- the application creates a <code>jcr:content</code> node (of type
<code>nt:resource</code>) under the file node.
- The file contents are placed on this <code>jcr:content</code> node in the
<code>jcr:data</code> property. For example, if you specify
- <code>/a/b/caution.png</code>, the following structure will be created
in the repository:</para>
- <programlisting><![CDATA[
-/a (nt:folder)
- /b (nt:folder)
- /caution.png (nt:file)
- /jcr:content (nt:resource)
- @jcr:data = {contents of the file}
- @jcr:mimeType = {mime type of the file}
- @jcr:lastModified = {now}
-]]></programlisting>
- <para>Other kinds of files are treated in a similar way.</para>
- <para>When the client uploads the file using the JCR API, DNA gets notified of
the changes, consults the sequencers to see whether
- any of them are interested in the new or updated content, and if so runs those
sequencers. The image sequencer processes image
- files for metadata, and any metadata found is stored under the
<code>/images</code> branch of the repository. The MP3 sequencer
- processes MP3 audio files for metadata, and any metadata found is stored under the
<code>/mp3s</code>
- branch of the repository. And metadata about Java classes are stored under the
<code>/java</code> area of the repository.
- All of this happens asynchronously, so any DNA activity doesn't impede or slow
down the client activities.
- </para>
- <para>So, after the file is uploaded, you can search the repository for the image
metadata using the "s" menu option:
- <figure id="example-sequencer-search">
- <title>Searching for media using the example client</title>
- <graphic align="center" scale="100"
fileref="example-sequencer-search.png"/>
- </figure>
- Here are the search results after the <code>sample1.mp3</code> audio
file has been uploaded (to the <code>/a/b/sample1.mp3</code> location):
- <figure id="example-sequencer-search-with-mp3">
- <title>Searching for media using the example client</title>
- <graphic align="center" scale="100"
fileref="example-sequencer-search-with-mp3.png"/>
- </figure>
- You can also display the sequencing statistics using the "d" menu option:
- <figure id="example-sequencer-statistics">
- <title>Sequencing statistics using the example client</title>
- <graphic align="center" scale="100"
fileref="example-sequencer-statistics.png"/>
- </figure>
- These stats show how many nodes were sequenced, and how many nodes were skipped
because they didn't apply to the sequencer's
- criteria.
- </para>
- <note>
- <para>There will probably be more nodes skipped than sequenced, since there are
more <code>nt:folder</code> and <code>nt:resource</code>
- nodes than there are <code>nt:file</code> nodes with acceptable
names.</para>
- </note>
- <para>You can repeat this process with other files. Any file that isn't an
image or MP3 files (as recognized by the sequencing configurations
- that we'll describe later) will not be sequenced.</para>
+ <sect1 id="downloading_and_running_whats_next">
+ <title>What's next</title>
+ <para>In this chapter you downloaded, installed, and built the two example
applications. In the next two chapters, we'll
+ run these examples and walk through the code.
+ </para>
</sect1>
- <sect1 id="running_repository_example">
- <title>Running the repository example</title>
- <para>The repository example consists of a client application that sets up two
DNA repositories (named "Cars" and "Airplanes") and
- a federated repository ("Vehicles") that dynamically federates the
information from the other two repositories.
- The client application allows you to interactively navigate each of these repositories
just as you would navigate the
- directory structure on a file system.</para>
- <para>This collection of repositories is shown in the following figure:
- <figure id="example-repositories">
- <title>Repositories used in the example client</title>
- <graphic align="center" scale="100"
fileref="example-repositories.png"/>
- </figure>
- Most of the repositories are in-memory repositories (using the In-Memory repository
connector), but the federated "Vehicles" repository
- content is federated from the other repositories and cached into the "Cache"
repository. This is shown in the following figure:
- <figure id="example-federated-repository">
- <title>Vehicles repository content is federated from the Cars, Airplanes and
Configuration repositories</title>
- <graphic align="center" scale="100"
fileref="example-federated-repository.png"/>
- </figure>
- </para>
- <para>
- To run the client application, go to the
<code>examples/repository/target/dna-example-repositories-basic.dir/</code>
- directory and type <code>./run.sh</code>. You should see the
command-line client and its menus in your terminal:
- <figure id="example-repositories-client">
- <title>Example Client</title>
- <graphic align="center" scale="100"
fileref="example-repositories-client.png"/>
- </figure>
- From this menu, you can see the list of repositories, select one, and navigate
through that repository in a manner similar
- to a *nix command-line shell (although the client itself uses the JCR API to
interact with the repositories).
- Here are some of the commands you can use:</para>
- <table frame='all'>
- <title>Repository client commands to navigate a repository</title>
- <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
- <colspec colname='c1' colwidth="1*"/>
- <colspec colname='c2' colwidth="1*"/>
- <thead>
- <row><entry>Command</entry><entry>Description</entry></row>
- </thead>
- <tbody>
- <row><entry>pwd</entry><entry>Print the path of the current
node (e.g., the "working directory")</entry></row>
- <row><entry>ls
[<emphasis>path</emphasis>]</entry><entry>List the children and
properties of the node at the supplied path,
- where "<emphasis>path</emphasis>" can be any relative
path or absolute path. If "<emphasis>path</emphasis>" is not
supplied,
- the current working node's path is used.</entry></row>
- <row><entry>cd
<emphasis>path</emphasis></entry><entry>Change to the specified
node, where "<emphasis>path</emphasis>"
- can be any relative path or absolute path. For example, "<code>cd
alpha</code>" changes the current node to be a child named
- "<code>alpha</code>"; "<code>cd
..</code>" changes the current node to the parent node; "<code>cd
/a/b</code>" changes
- the current node to be the "<code>/a/b</code>"
node.</entry></row>
- <row><entry>exit</entry><entry>Exit this repository and
return the list of repositories.</entry></row>
- </tbody>
- </tgroup>
- </table>
- <para>If you were to select the "Cars" repository and use some of the
commands, you should see something similar to:
- <figure id="example-repositories-navigating">
- <title>Navigating the Cars repository</title>
- <graphic align="center" scale="100"
fileref="example-repositories-navigating.png"/>
- </figure>
- </para>
- <para>You can also choose to navigate the "Vehicles" repository, which
projects the "Cars" repository content under the
- <code>/Vehicles/Cars</code> node, the "Airplanes" content under
the <code>/Vehicles/Airplanes</code> branch,
- and the "Configuration" content under
<code>/dna:system</code>.
- </para>
- <para>Try using the client to walk the different repositories. And while this
is a contrived application, it does demonstrate
- the use of JBoss DNA to federate repositories and provide access through
JCR.</para>
- </sect1>
- <sect1 id="downloading_and_running_review">
- <title>Summarizing what we just did</title>
- <para>In this chapter you downloaded, installed, and built the two example
applicationss. With the sequencer client, you could upload files into a
- JCR repository, while JBoss DNA automatically sequenced the image, MP3, or Java
source files you uploaded, extracted the metadata from the
- files, and stored that metadata inside the repository. The repository client
allowed you to walk through multiple repositories,
- including one whose content was federated from multiple other
repositories.</para>
- <para>These example applications were very simplistic. In fact, running through
the examples probably only took you a few minutes.
- So while these applications won't win any awards, they hopefully showed you the
basics of what JBoss DNA can do.</para>
- <para>In the next two chapters, we'll venture into the code to get an
understanding of how JBoss DNA actually works.
- The <link linkend="using_dna_for_sequencing">next chapter</link>
reviews the sequencer application and talks about
- how you can use DNA sequencers in your own applications. Then in the <link
linkend="using_dna_repositories">following chapter</link>
- we'll venture into the repositories example code to show how you can use DNA
repositories, including federated repositories,
- in your own applications.</para>
- </sect1>
</chapter>
Deleted: trunk/docs/gettingstarted/src/main/docbook/en-US/content/future.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/future.xml 2009-06-07
15:05:15 UTC (rev 988)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/future.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ JBoss DNA (
http://www.jboss.org/dna)
- ~
- ~ See the COPYRIGHT.txt file distributed with this work for information
- ~ regarding copyright ownership. Some portions may be licensed
- ~ to Red Hat, Inc. under one or more contributor license agreements.
- ~ See the AUTHORS.txt file in the distribution for a full listing of
- ~ individual contributors.
- ~
- ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- ~ is licensed to you under the terms of the GNU Lesser General Public License as
- ~ published by the Free Software Foundation; either version 2.1 of
- ~ the License, or (at your option) any later version.
- ~
- ~ JBoss DNA is distributed in the hope that it will be useful,
- ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- ~ for more details.
- ~
- ~ You should have received a copy of the GNU Lesser General Public License
- ~ along with this distribution; if not, write to:
- ~ Free Software Foundation, Inc.
- ~ 51 Franklin Street, Fifth Floor
- ~ Boston, MA 02110-1301 USA
- -->
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="future">
- <title>Looking to the future</title>
- <para>
- What's next for JBoss DNA? Well, the sequencing system is just the beginning.
With this release, the sequencing system
- is stable enough so that more <link
linkend="sequencers">sequencers</link> can be developed and used within
your own applications.
- We've also established the foundation for JBoss DNA repositories, including a
number of <link linkend="repository-connectors">connectors</link>.
- We'll continue to expand our library of sequencers and connectors, as well as
expand our support of JCR.
- Other components on our roadmap include a web user interface, a REST-ful server, and a
view system that allows domain-specific
- views of information in the repository. These components are farther out on our
roadmap, and at this time have not been
- targeted to a particular release.
- </para>
- <para>
- If you're interested in getting involved with the JBoss DNA project, consider
picking up one of the sequencers on our
- <ulink
url="http://jira.jboss.org/jira/browse/DNA?report=com.atlassian.jira...;.
- Or, check out <ulink
url="http://jira.jboss.org/jira/secure/IssueNavigator.jspa?reset=tru...
- for the list of sequencers we've thought of. If you think of one that's not
there, please add it to JIRA!
- </para>
-</chapter>
Modified: trunk/docs/gettingstarted/src/main/docbook/en-US/content/introduction.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/introduction.xml 2009-06-07
15:05:15 UTC (rev 988)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/introduction.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -24,7 +24,10 @@
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
<chapter id="introduction">
<title>Introduction</title>
<para>There are a lot of ways for applications to store information persistently
so that it can be accessed at a
@@ -85,26 +88,48 @@
and is being revised under <ulink
url="http://www.jcp.org/en/jsr/detail?id=283">JSR-283</ul...;.
</para>
<para>
- The <emphasis>JBoss DNA project</emphasis>
- is building unified metadata repository system that is compliant with JCR. Nearly
all of these capabilities are to be hidden
- below the JCR API and involve automated processing of the information in the
repository. Thus, JBoss DNA can add value to
- existing repository implementations. For example, JCR repositories offer the ability
to upload files into the repository and
- have the file content indexed for search purposes. JBoss DNA also defines a library
for "sequencing" content - to extract
- meaningful information from that content and store it in the repository, where it can
then be searched, accessed, and
- analyzed using the JCR API.
- </para>
- <para> JBoss DNA has other features as well. You can create federated
repositories that dynamically merge the information
- from multiple databases, services, applications, and other JCR repositories. JBoss
DNA also will allow you to
- create customized views based upon the type of data and the role of the user that is
accessing the data. And yet another goal is
- to create a REST-ful API to allow the JCR content to be accessed easily by other
applications written in other languages.
- </para>
- <para>
- The <link linkend="understanding_dna">next chapter</link> in
this book goes into more detail about JBoss DNA and its architecture,
- the different components, what's available now, and what's coming in future
releases.
- <link linkend="downloading_and_running">Chapter 3</link> then
provides instructions for downloading and running the sequencer
- examples for the current release. <link linkend="using_dna">Chapter
4</link> walks through how to use JBoss DNA sequencers
- in your applications, while <link linkend="custom_sequencers">Chapter
5</link> shows how to use JBoss DNA repositories.
- <link linkend="custom_sequencers">Chapter 6</link> goes over how
to create custom sequencers, and finally,
- <link linkend="future">Chapter 7</link> wraps things up with a
discussion about the future of JBoss DNA.
- </para>
+ The JCR API provides a number of information services that are needed by many
applications,
+ including: read and write access to information; the ability to structure information
in a hierarchical and flexible manner that can adapt
+ and evolve over time; ability to work with unstructured content; ability to
(transparently) handle large strings;
+ notifications of changes in the information; search and query; versioning of
information; access control; integrity constraints;
+ participation within distributed transactions; explicit locking of content; and of
course persistence.
+ </para>
+ <sect1 id="what_is_jboss_dna">
+ <title>JBoss DNA</title>
+ <para>
+ What makes JCR interesting, however, is that a JCR implementation provides all these
features and capabilities regardless
+ of where or how that information is persisted or stored. <emphasis>This is in
fact the main purpose of JBoss DNA:
+ provide a JCR implementation that provides access to content stored in many different
kinds of systems.</emphasis>
+ A JBoss DNA repository isn't yet another silo of information, but rather it's
a JCR view of the information you already have
+ in your environment: files systems, databases, other repositories, services,
applications, etc. JBoss DNA can
+ help you understand the systems and information you already have.
+ </para>
+ <para>
+ Of course when you start providing a unified view of all this information, you start
recognizing the need to store more
+ information, including metadata about and relationships between the existing content.
JBoss DNA lets you do this, too.
+ And JBoss DNA even tries to help you discover more about the information you already
have, especially the
+ information wrapped up in the kinds of files often found in enterprise systems:
service definitions, policy files,
+ images, media, documents, presentations, application components, reusable libraries,
configuration files,
+ application installations, databases schemas, management scripts, and so on. As files
are loaded into the repository,
+ JBoss DNA can <emphasis>sequence</emphasis> these files to extract from
their content meaningful information that
+ can be stored in the repository, where it can then be searched, accessed, and analyzed
using the JCR API.
+ </para>
+ </sect1>
+ <sect1 id="introduction_whats_next">
+ <title>What's next</title>
+ <para>
+ As we'll see in the <link linkend="use_cases">next
chapter</link>, the ability of JBoss DNA to
+ federate, integrate, and sequence information make JBoss DNA a powerful asset and
tool.
+ Then <link linkend="using_dna">Chapter 3</link> will show that
once a JBoss DNA repository is set up, application see
+ JBoss DNA just as another JCR <code>javax.jcr.Repository</code> instance
and uses the standard JCR API to obtain a <code>javax.jcr.Session</code>
+ and work with the content.
+ </para>
+ <para>
+ <link linkend="downloading_and_running">Chapter 4</link> walks
you through downloading
+ and building the JBoss DNA examples, while <link
linkend="sequencer_example">Chapter 5</link>
+ and <link linkend="repository_example">Chapter 6</link> will run
these very simple examples and walking through code.
+ <link linkend="conclusion">Chapter 7</link> wraps things up with
a discussion about the future of JBoss DNA
+ and what you can do next to start using JBoss DNA in your own applications.
+ </para>
+ </sect1>
</chapter>
Modified: trunk/docs/gettingstarted/src/main/docbook/en-US/content/legal_notice.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/legal_notice.xml 2009-06-07
15:05:15 UTC (rev 988)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/legal_notice.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -24,7 +24,10 @@
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
-<!DOCTYPE legalnotice PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!DOCTYPE legalnotice PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
<legalnotice id="Legal_Notice">
<title>Legal Notice</title>
Modified: trunk/docs/gettingstarted/src/main/docbook/en-US/content/preface.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/preface.xml 2009-06-07
15:05:15 UTC (rev 988)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/preface.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -24,7 +24,10 @@
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
-<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
<preface id="preface" revision="1">
<title>What this book covers</title>
<para>The goal of this book is to help you learn about JBoss DNA and how you can
use it in your own applications to get the
Added: trunk/docs/gettingstarted/src/main/docbook/en-US/content/repository_example.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/repository_example.xml
(rev 0)
+++
trunk/docs/gettingstarted/src/main/docbook/en-US/content/repository_example.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -0,0 +1,483 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ JBoss DNA (
http://www.jboss.org/dna)
+ ~
+ ~ See the COPYRIGHT.txt file distributed with this work for information
+ ~ regarding copyright ownership. Some portions may be licensed
+ ~ to Red Hat, Inc. under one or more contributor license agreements.
+ ~ See the AUTHORS.txt file in the distribution for a full listing of
+ ~ individual contributors.
+ ~
+ ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ ~ is licensed to you under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ JBoss DNA is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
+<chapter id="repository_example">
+ <title>The Repository Example</title>
+ <para>
+ <link linkend="downloading_and_running">Chapter 4</link> walked
through the process of downloading and building the examples,
+ while the <link linkend="sequencer_example">previous
chapter</link> showed how to run the sequencer example and walked
+ through the code. In this chapter, we'll run the repository example and walk
through that example code to see what
+ it's doing.
+ </para>
+ <sect1 id="running_repository_example">
+ <title>Running the repository example</title>
+ <para>The repository example consists of a client application that sets up two
DNA repositories (named "Cars" and "Airplanes") and
+ a federated repository ("Vehicles") that dynamically federates the
information from the other two repositories.
+ The client application allows you to interactively navigate each of these repositories
just as you would navigate the
+ directory structure on a file system.</para>
+ <para>This collection of repositories is shown in the following figure:
+ <figure id="example-repositories">
+ <title>Repositories used in the example client</title>
+ <graphic align="center" scale="100"
fileref="example-repositories.png"/>
+ </figure>
+ Most of the repositories are in-memory repositories (using the In-Memory repository
connector), but the federated "Vehicles" repository
+ content is federated from the other repositories and cached into the "Cache"
repository. This is shown in the following figure:
+ <figure id="example-federated-repository">
+ <title>Vehicles repository content is federated from the Cars, Airplanes and
Configuration repositories</title>
+ <graphic align="center" scale="100"
fileref="example-federated-repository.png"/>
+ </figure>
+ </para>
+ <para>
+ To run the client application, go to the
<code>examples/repository/target/dna-example-repositories-basic.dir/</code>
+ directory and type <code>./run.sh</code>. You should see the
command-line client and its menus in your terminal:
+ <figure id="example-repositories-client">
+ <title>Example Client</title>
+ <graphic align="center" scale="100"
fileref="example-repositories-client.png"/>
+ </figure>
+ From this menu, you can see the list of repositories, select one, and navigate
through that repository in a manner similar
+ to a *nix command-line shell (although the client itself uses the JCR API to
interact with the repositories).
+ Here are some of the commands you can use:</para>
+ <table frame='all'>
+ <title>Repository client commands to navigate a repository</title>
+ <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <thead>
+ <row><entry>Command</entry><entry>Description</entry></row>
+ </thead>
+ <tbody>
+ <row><entry>pwd</entry><entry>Print the path of the current
node (e.g., the "working directory")</entry></row>
+ <row><entry>ls
[<emphasis>path</emphasis>]</entry><entry>List the children and
properties of the node at the supplied path,
+ where "<emphasis>path</emphasis>" can be any relative
path or absolute path. If "<emphasis>path</emphasis>" is not
supplied,
+ the current working node's path is used.</entry></row>
+ <row><entry>cd
<emphasis>path</emphasis></entry><entry>Change to the specified
node, where "<emphasis>path</emphasis>"
+ can be any relative path or absolute path. For example, "<code>cd
alpha</code>" changes the current node to be a child named
+ "<code>alpha</code>"; "<code>cd
..</code>" changes the current node to the parent node; "<code>cd
/a/b</code>" changes
+ the current node to be the "<code>/a/b</code>"
node.</entry></row>
+ <row><entry>exit</entry><entry>Exit this repository and
return the list of repositories.</entry></row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>If you were to select the "Cars" repository and use some of the
commands, you should see something similar to:
+ <figure id="example-repositories-navigating">
+ <title>Navigating the Cars repository</title>
+ <graphic align="center" scale="100"
fileref="example-repositories-navigating.png"/>
+ </figure>
+ </para>
+ <para>You can also choose to navigate the "Vehicles" repository, which
projects the "Cars" repository content under the
+ <code>/Vehicles/Cars</code> node, the "Airplanes" content under
the <code>/Vehicles/Airplanes</code> branch,
+ and the "Configuration" content under
<code>/dna:system</code>.
+ </para>
+ <para>Try using the client to walk the different repositories. And while this
is a contrived application, it does demonstrate
+ the use of JBoss DNA to federate repositories and provide access through
JCR.</para>
+ </sect1>
+ <sect1 id="connectors">
+ <title>JBoss DNA connectors</title>
+ <para>As mentioned in the <link
linkend="introduction">Introduction</link>, one of the capabilities of
JBoss DNA is to provide access through
+ <ulink
url="http://www.jcp.org/en/jsr/detail?id=170">JCR</ulink>
to different kinds of repositories and storage systems.
+ Your applications work with the JCR API, but through JBoss DNA you're able to
accesses the content from where the information
+ exists - not just a single purpose-built repository. This is fundamentally what makes
JBoss DNA different.</para>
+ <para>How does JBoss DNA do this? At the heart of JBoss DNA and it's JCR
implementation is a simple connector
+ system that is designed around creating and accessing graphs. The JBoss DNA JCR
implementation actually just sits on
+ top of a single repository source, which it uses to access of the repositories
content.
+ <figure id="dnajcr-and-connector">
+ <title>JBoss DNA's JCR implementation delegates to a repository
source</title>
+ <graphic align="center" scale="100"
fileref="dnajcr-and-connector.png"/>
+ </figure>
+ That single repository source could be an in-memory repository, a JBoss Cache
instance, or a federated repository.
+ <figure id="dna-connectors-0.2">
+ <title>JBoss DNA can put JCR on top of multiple kinds of systems</title>
+ <graphic align="center" scale="100"
fileref="dna-connectors-0.2.png"/>
+ </figure>
+ And the JBoss DNA project has plans to create other connectors, too. For instance,
we're going to build a connector
+ to other JCR repositories. And another to a file system, so that the files and
directories on an area of the file system
+ can be accessed through JCR. Of course, if we don't have a connector to suit
your needs, you can write your own.
+ <figure id="dna-connectors-future">
+ <title>Future JBoss DNA connectors</title>
+ <graphic align="center" scale="100"
fileref="dna-connectors-future.png"/>
+ </figure>
+ </para>
+ <note>
+ <para>You might be thinking that these connectors are interesting, but what do
they really provide? Is it really useful
+ to use JCR to access a relational database rather than JDBC? Or, why access the
files on a file system when there
+ are already mechanisms to do that?</para>
+ <para>Maybe putting JCR on top of a single system (like a JDBC database)
isn't that interesting. What
+ <emphasis>is</emphasis> interesting, though, is accessing the
information in multiple systems <emphasis>as if all that information were
+ in a single JCR repository</emphasis>. That's what the federated
repository source is all about. The JBoss DNA connector
+ system just makes it possible to interact with all these systems in the same
way.</para>
+ <para>Think of it this way: with JBoss DNA, you can use JCR to get to the
schemas of multiple relational databases <emphasis>and</emphasis> the schemas
+ defined by DDL files in your SVN repository <emphasis>and</emphasis> the
schemas defined by logical models stored on your file system.
+ </para>
+ </note>
+ <para>Before we go further, let's define some terminology regarding
connectors.</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A <emphasis role="strong">connector</emphasis> is the runnable
code packaged in one or more JAR files that
+ contains implementations of several interfaces (described below). A Java developer
<emphasis>writes</emphasis>
+ a connector to a type of source, such as a particular database management system,
LDAP directory, source code
+ management system, etc. It is then packaged into one or more JAR files (including
dependent JARs) and deployed
+ for use in applications that use JBoss DNA repositories.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The description of a particular source system (e.g., the "Customer"
database, or the company LDAP system)
+ is called a <emphasis role="strong">repository
source</emphasis>. JBoss DNA defines a &RepositorySource; interface
+ that defines methods describing the behavior and supported features and a method for
establishing connections.
+ A connector will have a class that implements this interface and that has JavaBean
properties for
+ all of the connector-specific properties required to fully describe an instance of
the system. Use of JavaBean
+ properties is not required, but it is highly recommended, as it enables reflective
configuration and administration.
+ Applications that use JBoss DNA create an instance of the connector's
&RepositorySource; implementation and set
+ the properties for the external source that the application wants to access with
that connector.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A repository source instance is then used to establish <emphasis
role="strong">connections</emphasis> to
+ that source. A connector provides an implementation of the
&RepositoryConnection; interface, which
+ defines methods for interacting with the external system. In particular, the
<code>execute(...)</code> method
+ takes an &ExecutionContext; instance and a &Request; object. The
&ExectuionContext; object defines the
+ environment in which the processing is occurring, including information about the
JAAS &Subject; and &LoginContext;.
+ The &Request; object describes the requested operations on the content, with
different concrete subclasses
+ representing each type of activity. Examples of commands include (but not limited
to) getting a node, moving a node, creating a node,
+ changing a node, and deleting a node. And, if the repository source is able to
participate in JTA/JTS distributed transactions, then the
+ &RepositoryConnection; must implement the
<code>getXaResource()</code> method by returning
+ a valid <code>javax.transaction.xa.XAResource</code> object that can be
used by the transaction monitor.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>As an example, consider that we want JBoss DNA to give us access through
JCR to the schema information contained in a
+ relational databases. We first have to develop a connector that allows us to interact
with relational databases using JDBC.
+ That connector would contain a <code>JdbcRepositorySource</code> Java
class that implements &RepositorySource;,
+ and that has all of the various JavaBean properties for setting the name of the driver
class, URL, username, password,
+ and other properties. (Or we might have a JavaBean property that defines the JNDI
name where we can find a JDBC
+ <code>DataSource</code> instance pointing to our JDBC database.)
+ </para>
+ <para>So with this very high-level summary, let's dive a little deeper and
look at the repository example.</para>
+ </sect1>
+ <sect1 id="example_repository_application_review">
+ <title>Reviewing the example repository application</title>
+ <para>Recall that the example repository application consists of a client
application that sets up a repository service and the
+ repositories defined in a configuration repository, allowing the user to pick a
repository and interactively navigate
+ the selected repository. Several repositories are set up, including several in-memory
repositories and one federated repository
+ that dynamically federates the content from the other repositories.</para>
+ <para>
+ The example is comprised of 2 classes and 1 interface, located in the
<code>src/main/java</code> directory:</para>
+ <programlisting><![CDATA[
+ org/jboss/example/dna/repositories/ConsoleInput.java
+ /RepositoryClient.java
+ /UserInterface.java
+ ]]></programlisting>
+ <para><code>RepositoryClient</code> is the class that contains the
main application. It uses an instance of the
+ <code>UserInterface</code> interface to methods that will be called at
runtime to obtain information about the
+ files that are imported into the in-memory repositories and the JAAS
<code>CallbackHandler</code> implementation
+ that will be used by JAAS to prompt the user for authentication information.
Finally, the <code>ConsoleInput</code>
+ is an implementation of this that creates a text user interface, allowing the user to
operate the client from the command-line.
+ We can easily create a graphical implementation of
<code>UserInterface</code> at a later date, or we can also create a mock
+ implementation for testing purposes that simulates a user entering data. This allows
us to check the behavior of the client
+ automatically using conventional JUnit test cases, as demonstrated by the code in the
<code>src/test/java</code> directory:</para>
+ <programlisting><![CDATA[
+ org/jboss/example/dna/sequencers/RepositoryClientTest.java
+ /RepositoryClientUsingJcrTest.java
+ ]]></programlisting>
+ <para>If we look at the <code>RepositoryClient</code> code, there are
a handful of methods that encapsulate the various activities.</para>
+ <note>
+ <para>Some of the code samples included in this book have had some of the error
handling and comments removed so that
+ the code is more readable and concise.</para>
+ </note>
+ <para>The <code>main(String[] argv)</code> method is of course the
method that is executed when the application is run. This code
+ creates the JBoss DNA configuration by loading it from a file.
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+// Set up the JAAS provider (IDTrust) and a policy file (which defines the
"dna-jcr" login config name)
+IDTrustConfiguration idtrustConfig = new IDTrustConfiguration();
+try {
+ idtrustConfig.config("security/jaas.conf.xml");
+} catch (Exception ex) {
+ throw new IllegalStateException(ex);
+}
+
+// Now configure the repository client component ...
+RepositoryClient client = new RepositoryClient();
+for (String arg : args) {
+ arg = arg.trim();
+ if (arg.equals("--api=jcr")) client.setApi(Api.JCR);
+ if (arg.equals("--api=dna")) client.setApi(Api.DNA);
+ if (arg.equals("--jaas"))
client.setJaasContextName(JAAS_LOGIN_CONTEXT_NAME);
+ if (arg.startsWith("--jaas=") && arg.length() > 7)
client.setJaasContextName(arg.substring(7).trim());
+}
+// And have it use a ConsoleInput user interface ...
+client.setUserInterface(new ConsoleInput(client, args));
+ ]]></programlisting>
+ <para>
+ The first block sets up the JAAS provider to be the IDTrust library and a policy file
that defines the "dna-jcr" JAAS configuration.
+ </para>
+ <para>
+ The second block of code instantiates the <code>RepositoryClient</code> and
passes in some options determined from the command-line.
+ It then sets the user interface (which then executes its behavior, which we'll see
below).
+ </para>
+ <para>
+ The <code>startRepositories()</code> method builds the
<code>JcrEngine</code> component from the configuration, starts the engine,
+ and obtains the JCR <code>javax.jcr.Repository</code> instance that the
client will use. Note that the client has not yet
+ obtained a <code>javax.jcr.Session</code> instance, since this will be done
each time the client needs to access content from
+ the repository. (This is actually a common practice according to the JCR
specification, since Sessions are intended to be
+ very lightweight.)
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+public void startRepositories() throws IOException, SAXException {
+ if (engine != null) return; // already started
+
+ // Load the configuration from a file, as provided by the user interface ...
+ JcrConfiguration configuration = new JcrConfiguration();
+ configuration.loadFrom(userInterface.getRepositoryConfiguration());
+
+ // Load the node types for each JCR repository, via a CND file. These could have been
defined
+ // in the configuration file, but this approach is easy and allows us to define the
node types
+ // using the CND format in one or multiple files.
+ String locationOfCndFiles = userInterface.getLocationOfCndFiles();
+ configuration.repository("aircraft
repository").addNodeTypes(locationOfCndFiles + "/aircraft.cnd");
+ configuration.repository("car repository").addNodeTypes(locationOfCndFiles
+ "/cars.cnd");
+ configuration.repository("virtual").addNodeTypes(locationOfCndFiles +
"/virtual.cnd");
+
+ // Now create the JCR engine ...
+ engine = configuration.build();
+ engine.start();
+
+ // For this example, we're using a couple of in-memory repositories (including
one for the configuration repository).
+ // Normally, these would exist already and would simply be accessed. But in this
example, we're going to
+ // populate these repositories here by importing from files. First do the
configuration repository ...
+ String location = this.userInterface.getLocationOfRepositoryFiles();
+
+ // Now import the content for the two in-memory repositories ...
+ Graph cars = engine.getGraph("Cars");
+ cars.importXmlFrom(location + "/cars.xml").into("/");
+ Graph aircraft = engine.getGraph("Aircraft");
+ aircraft.importXmlFrom(location + "/aircraft.xml").into("/");
+}
+ ]]></programlisting>
+ <para>
+ This method does a number of different things. First, it checks to make sure the
repositories are not already running; if so
+ the method just returns. Then, it creates a JBoss DNA
<code>JcrConfiguration</code> instance and loads the configuration
+ from a file provided by the user interface. The method then loads the node types for
each of the repositories; this could
+ have been done in the configuration, but it would have made the configuration file
larger and more difficult to understand.
+ It then creates the <code>JcrEngine</code> from the configuration and
starts it. Finally, it obtains the location of the
+ content files from the user interface, and imports them into the "Cars" and
"Aircraft" repositories. Again, this is
+ done to keep the example simple.
+ </para>
+ <para>
+ The <code>shutdown()</code> method of the example then logs out and
requests the <code>JcrEngine</code> instance shuts down and, since that may
take
+ a few moments (if there are any ongoing operations or enqueued activities) awaits for
it to complete the shutdown.
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+public void shutdown() throws InterruptedException, LoginException {
+ logout();
+ if (engine == null) return;
+ try {
+ // Tell the engine to shut down, and then wait up to 5 seconds for it to
complete...
+ engine.shutdown();
+ engine.awaitTermination(5, TimeUnit.SECONDS);
+ } finally {
+ engine = null;
+ }
+}
+ ]]></programlisting>
+ <para>
+ A few of the other methods in the <code>RepositoryClient</code> class deal
with the JAAS <code>LoginContext</code>.
+ When needed, the client will authenticate the user (by asking the user interface for a
callback handler that will be called
+ when the authentication information is needed). The resulting authenticated
<code>LoginContext</code> is wrapped
+ by a custom <code>javax.jcr.Credentials</code> implementation. As long as
the <code>Credentials</code> implementation
+ has a <code>getLoginContext()</code> method that returns a
<code>LoginContext</code> object, JBoss DNA's repository
+ implementation will use that context to create the
<code>javax.jcr.Session</code>. (Of course, the
<code>javax.jcr.SimpleCredentials</code>
+ can also be used to create a Session, and JBoss DNA will then attempt to use JAAS to
authenticate the user given by the credentials.)
+ </para>
+ <para>
+ The <code>getNodeInfo(...)</code> method of the example is what is called
when the properties and children of a particular node
+ are requested by the user interface. (In the console user interface, this happens
when the user navigates the graph structure.)
+ There are really two different behaviors to this method, depending upon whether the
JCR API is to be used or whether
+ the JBoss DNA Graph API is to be used. The portion that uses JCR is shown below:
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+JcrRepository jcrRepository = engine.getRepository(sourceName);
+Session session = null;
+if (loginContext != null) {
+ // Could also use SimpleCredentials(username,password) too
+ Credentials credentials = new JaasCredentials(loginContext);
+ session = jcrRepository.login(credentials);
+} else {
+ session = jcrRepository.login();
+}
+try {
+ // Make the path relative to the root by removing the leading slash(es) ...
+ pathToNode = pathToNode.replaceAll("^/+", "");
+ // Get the node by path ...
+ Node root = session.getRootNode();
+ Node node = root;
+ if (pathToNode.length() != 0) {
+ if (!pathToNode.endsWith("]")) pathToNode = pathToNode +
"[1]";
+ node = pathToNode.equals("") ? root : root.getNode(pathToNode);
+ }
+
+ // Now populate the properties and children ...
+ if (properties != null) {
+ for (PropertyIterator iter = node.getProperties(); iter.hasNext();) {
+ javax.jcr.Property property = iter.nextProperty();
+ Object[] values = null;
+ // Must call either 'getValue()' or 'getValues()' depending
upon # of values
+ if (property.getDefinition().isMultiple()) {
+ Value[] jcrValues = property.getValues();
+ values = new String[jcrValues.length];
+ for (int i = 0; i < jcrValues.length; i++) {
+ values[i] = jcrValues[i].getString();
+ }
+ } else {
+ values = new Object[] {property.getValue().getString()};
+ }
+ properties.put(property.getName(), values);
+ }
+ }
+ if (children != null) {
+ // Figure out which children need same-name sibling indexes ...
+ Set<String> sameNameSiblings = new HashSet<String>();
+ for (NodeIterator iter = node.getNodes(); iter.hasNext();) {
+ javax.jcr.Node child = iter.nextNode();
+ if (child.getIndex() > 1) sameNameSiblings.add(child.getName());
+ }
+ for (NodeIterator iter = node.getNodes(); iter.hasNext();) {
+ javax.jcr.Node child = iter.nextNode();
+ String name = child.getName();
+ if (sameNameSiblings.contains(name)) name = name + "[" +
child.getIndex() + "]";
+ children.add(name);
+ }
+ }
+} catch (javax.jcr.ItemNotFoundException e) {
+ return false;
+} catch (javax.jcr.PathNotFoundException e) {
+ return false;
+} finally {
+ if (session != null) session.logout();
+}
+ ]]></programlisting>
+ <para>
+ This code is literally just using the standard JCR API. First, it obtains a
<code>javax.jcr.Session</code> instance
+ (using the available <code>LoginContext</code>), finds the desired
<code>javax.jcr.Node</code>, copies the
+ properties and names of the children into collections supplied by the caller via
method parameters, and
+ finally logs out of the session.
+ </para>
+ <para>
+ The JBoss DNA Graph API is actually an internal API used within the different
components of JBoss DNA
+ (including the connector and sequencer frameworks), and provides low-level access to
the exact same content.
+ Though we do not recommend using this API in your client applications, if you need to
write a connector
+ or sequencer, you may need to know how to use the Graph API.
+ Here is the portion of the <code>getNodeInfo(...)</code> method that does
the exact same operation as the JCR code
+ shown above:
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+// Use the DNA Graph API to read the properties and children of the node ...
+ExecutionContext context = loginContext != null ? this.context.create(loginContext) :
this.context;
+Graph graph = engine.getGraph(context, sourceName);
+graph.useWorkspace("default");
+org.jboss.dna.graph.Node node = graph.getNodeAt(pathToNode);
+
+if (properties != null) {
+ // Now copy the properties into the map provided as a method parameter ...
+ for (Property property : node.getProperties()) {
+ String name = property.getName().getString(context.getNamespaceRegistry());
+ properties.put(name, property.getValuesAsArray());
+ }
+}
+if (children != null) {
+ // And copy the names of the children into the list provided as a method parameter
...
+ for (Location child : node.getChildren()) {
+ String name =
child.getPath().getLastSegment().getString(context.getNamespaceRegistry());
+ children.add(name);
+ }
+}
+ ]]></programlisting>
+ <para>
+ Note that this code is significantly shorter than the equivalent code based upon the
JCR API.
+ This is in part because the Graph API doesn't have the notion of a stateful
session. But some of it also is simply
+ because the Graph API design requires less code to do the same kinds of operations.
+ </para>
+ <para>None of the other methods in the <code>RepositoryClient</code>
really do anything with JBoss DNA or JCR
+ <emphasis>per se</emphasis>. Instead, they really facilitate interaction
with the user interface.
+ </para>
+ <para>If we look at the <code>ConsoleInput</code> constructor, it
starts the repository and a thread
+ for the user interface. At this point, the constructor returns, but the main
application continues under the user interface thread.
+ When the user requests to quit, the user interface thread also shuts down the JCR
repository.</para>
+ <programlisting role="JAVA"><![CDATA[
+public ConsoleInput( SequencerClient client ) {
+ try {
+ client.startRepositories();
+
+ System.out.println(getMenu());
+ Thread eventThread = new Thread(new Runnable() {
+ private boolean quit = false;
+ public void run() {
+ try {
+ while (!quit) {
+ // Display the prompt and process the requested operation ...
+ }
+ } finally {
+ try {
+ // Terminate ...
+ client.shutdown();
+ } catch (Exception err) {
+ System.out.println("Error shutting down repository: "
+ + err.getLocalizedMessage());
+ err.printStackTrace(System.err);
+ }
+ }
+ }
+ });
+ eventThread.start();
+ } catch (Exception err) {
+ System.out.println("Error: " + err.getLocalizedMessage());
+ err.printStackTrace(System.err);
+ }
+}
+ ]]></programlisting>
+ <para>At this point, we've reviewed all of the interesting code in the
example application related to JBoss DNA. However, feel free
+ to play with the application, trying different things.
+ </para>
+ </sect1>
+ <sect1 id="repository_example_whats_next">
+ <title>What's next</title>
+ <para>
+ This chapter walked through running the repository example and looked at the example
code. This example allowed you to walk
+ through multiple repositories, including one whose content was federated from multiple
other repositories.
+ This was a very simplistic example that only took a few minutes to run.
+ </para>
+ <para>
+ In the <link linkend="conclusion">next chapter</link> we'll
wrap up by summarizing what we've learned about JBoss DNA
+ and provide information about where you can find out more about JBoss DNA.
+ </para>
+ </sect1>
+</chapter>
Property changes on:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/repository_example.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: trunk/docs/gettingstarted/src/main/docbook/en-US/content/sequencer_example.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/sequencer_example.xml
(rev 0)
+++
trunk/docs/gettingstarted/src/main/docbook/en-US/content/sequencer_example.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -0,0 +1,315 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ JBoss DNA (
http://www.jboss.org/dna)
+ ~
+ ~ See the COPYRIGHT.txt file distributed with this work for information
+ ~ regarding copyright ownership. Some portions may be licensed
+ ~ to Red Hat, Inc. under one or more contributor license agreements.
+ ~ See the AUTHORS.txt file in the distribution for a full listing of
+ ~ individual contributors.
+ ~
+ ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ ~ is licensed to you under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ JBoss DNA is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
+<chapter id="sequencer_example">
+ <title>The Sequencer Example</title>
+ <para>
+ The previous chapter walked through the process of downloading and building the
examples.
+ This chapter will focus on the sequencer example, showing how to run the example and
then walking through the code
+ to describe what it's doing.
+ </para>
+ <sect1 id="running_sequencer_example">
+ <title>Running the sequencing example</title>
+ <para>The sequencing example consists of a client application that sets up an
in-memory JCR repository and that allows a user to
+ upload files into that repository. The client also sets up the DNA services with
two sequencers so that if any of the
+ uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will automatically
extract the image's metadata (e.g., image
+ format, physical size, pixel density, etc.) and store that in the repository.
Alternatively, if the uploaded file
+ is an MP3 audio file, DNA will extract some of the ID3 metadata (e.g., the author,
title, album, year and comment)
+ and store that in the repository.</para>
+ <para>
+ To run the client application, go to the
<code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code>
+ directory and type <code>./run.sh</code>. You should see the
command-line client and its menus in your terminal:
+ <figure id="xample-sequencer-cli-client">
+ <title>Example client</title>
+ <graphic align="center" scale="100"
fileref="example-sequencer-client.png"/>
+ </figure>
+ From this menu, you can upload a file into the repository, search for media in the
repository, print sequencing statistics,
+ or quit the application.</para>
+ <para>
+ The first step is to upload one of the example images. If you type 'u' and
press return, you'll be prompted to supply the
+ path to the file you want to upload. Since the application is running from within
the
+
<code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code>
directory, you can specify any of the files
+ in that directory without specifying the path:
+ <figure id="example-sequencer-upload">
+ <title>Uploading an image using the example client</title>
+ <graphic align="center" scale="100"
fileref="example-sequencer-upload.png"/>
+ </figure>
+ You can specify any fully-qualified or relative path. The application will notify
you if it cannot find the file you
+ specified. The example client configures JBoss DNA to sequence MP3 audio files,
Java source files, or image files with one of
+ the following extensions (technically, nodes that have names ending in the
following):
+ <code>jpg</code>, <code>jpeg</code>,
<code>gif</code>, <code>bmp</code>, <code>pcx</code>,
<code>png</code>,
+ <code>iff</code>, <code>ras</code>,
<code>pbm</code>, <code>pgm</code>, <code>ppm</code>,
and <code>psd</code>.
+ Files with other extensions in the repository path will be ignored. For your
convenience, the example provides several
+ files that will be sequenced (<code>caution.png</code>,
<code>caution.jpg</code>, <code>caution.gif</code>, and
+ <code>sample1.mp3</code>) and one image that will not be sequenced
(<code>caution.pict</code>). Feel free to try other files.
+ </para>
+ <para>
+ After you have specified the file you want to upload, the example application asks
you where in the repository you'd like to
+ place the file. (If you want to use the suggested location, just press
<code>return</code>.) The client application
+ uses the JCR API to upload the file to that location in the repository, creating
any nodes (of type <code>nt:folder</code>)
+ for any directories that don't exist, and creating a node (of type
<code>nt:file</code>) for the file. And, per the JCR specification,
+ the application creates a <code>jcr:content</code> node (of type
<code>nt:resource</code>) under the file node.
+ The file contents are placed on this <code>jcr:content</code> node in the
<code>jcr:data</code> property. For example, if you specify
+ <code>/a/b/caution.png</code>, the following structure will be created
in the repository:</para>
+ <programlisting><![CDATA[
+/a (nt:folder)
+ /b (nt:folder)
+ /caution.png (nt:file)
+ /jcr:content (nt:resource)
+ @jcr:data = {contents of the file}
+ @jcr:mimeType = {mime type of the file}
+ @jcr:lastModified = {now}
+]]></programlisting>
+ <para>Other kinds of files are treated in a similar way.</para>
+ <para>When the client uploads the file using the JCR API, DNA gets notified of
the changes, consults the sequencers to see whether
+ any of them are interested in the new or updated content, and if so runs those
sequencers. The image sequencer processes image
+ files for metadata, and any metadata found is stored under the
<code>/images</code> branch of the repository. The MP3 sequencer
+ processes MP3 audio files for metadata, and any metadata found is stored under the
<code>/mp3s</code>
+ branch of the repository. And metadata about Java classes are stored under the
<code>/java</code> area of the repository.
+ All of this happens asynchronously, so any DNA activity doesn't impede or slow
down the client activities.
+ </para>
+ <para>So, after the file is uploaded, you can search the repository for the image
metadata using the "s" menu option:
+ <figure id="example-sequencer-search">
+ <title>Searching for media using the example client</title>
+ <graphic align="center" scale="100"
fileref="example-sequencer-search.png"/>
+ </figure>
+ Here are the search results after the <code>sample1.mp3</code> audio
file has been uploaded (to the <code>/a/b/sample1.mp3</code> location):
+ <figure id="example-sequencer-search-with-mp3">
+ <title>Searching for media using the example client</title>
+ <graphic align="center" scale="100"
fileref="example-sequencer-search-with-mp3.png"/>
+ </figure>
+ You can also display the sequencing statistics using the "d" menu option:
+ <figure id="example-sequencer-statistics">
+ <title>Sequencing statistics using the example client</title>
+ <graphic align="center" scale="100"
fileref="example-sequencer-statistics.png"/>
+ </figure>
+ These stats show how many nodes were sequenced, and how many nodes were skipped
because they didn't apply to the sequencer's
+ criteria.
+ </para>
+ <note>
+ <para>There will probably be more nodes skipped than sequenced, since there are
more <code>nt:folder</code> and <code>nt:resource</code>
+ nodes than there are <code>nt:file</code> nodes with acceptable
names.</para>
+ </note>
+ <para>You can repeat this process with other files. Any file that isn't an
image or MP3 files (as recognized by the sequencing configurations
+ that we'll describe later) will not be sequenced.</para>
+ </sect1>
+ <sect1 id="example_application_review">
+ <title>Reviewing the example application</title>
+ <para>Recall that the example application consists of a client application that
sets up an in-memory JCR repository and
+ that allows a user to upload files into that repository. The client also sets up
the DNA services with an image sequencer so
+ that if any of the uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will
automatically extract the image's
+ metadata (e.g., image format, physical size, pixel density, etc.) and store that in
the repository. Or, if the client uploads
+ MP3 audio files, the title, author, album, year, and comment are extracted from the
audio file and stored in the repository.</para>
+ <para>
+ The example is comprised of 5 classes and 1 interface, located in the
<code>src/main/java</code> directory:</para>
+ <programlisting><![CDATA[
+ org/jboss/example/dna/sequencers/ConsoleInput.java
+ /ContentInfo.java
+ /JavaInfo.java
+ /MediaInfo.java
+ /SequencingClient.java
+ /UserInterface.java
+ ]]></programlisting>
+ <para><code>SequencingClient</code> is the class that contains the
main application. <code>ContentInfo</code> is a simple class
+ that encapsulate metadata generated by the sequencers and accessed by this example
application, and there are two subclasses:
+ <code>MediaInfo</code> encapsulates metadata about media (image and MP3)
files, while <code>JavaInfo</code> is a subclass
+ encapsulating information about a Java class. The client accesses the content from
the repository and represent the
+ information using instances of <code>ContentInfo</code> (and its
subclasses) and then passing them to the <code>UserInterface</code>.
+ <code>UserInterface</code> is an interface with methods that will be
called at runtime to
+ request data from the user. <code>ConsoleInput</code> is an
implementation of this that creates a text user interface,
+ allowing the user to operate the client from the command-line. We can easily create a
graphical implementation of
+ <code>UserInterface</code> at a later date. We can also create a mock
implementation for testing purposes that simulates
+ a user entering data. This allows us to check the behavior of the client automatically
using conventional JUnit test cases,
+ as demonstrated by the code in the <code>src/test/java</code>
directory:</para>
+ <programlisting><![CDATA[
+ org/jboss/example/dna/sequencers/SequencingClientTest.java
+ /MockUserInterface.java
+ ]]></programlisting>
+ <para>If we look at the <code>SequencingClient</code> code, there are
a handful of methods that encapsulate the various activities.</para>
+ <note>
+ <para>Some of the code samples included in this book have had some of the error
handling and comments removed so that
+ the code is more readable and concise.</para>
+ </note>
+ <para>The <code>main(String[] argv)</code> method is of course the
method that is executed when the application is run. This code
+ creates the JBoss DNA configuration using the programmatic style.
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+// Set up the JAAS provider (IDTrust) and a policy file (which defines the
"dna-jcr" login config name)
+IDTrustConfiguration idtrustConfig = new IDTrustConfiguration();
+try {
+ idtrustConfig.config("security/jaas.conf.xml");
+} catch (Exception ex) {
+ throw new IllegalStateException(ex);
+}
+
+// Create the configuration.
+String repositoryId = "content";
+String workspaceName = "default";
+JcrConfiguration config = new JcrConfiguration();
+// Set up the in-memory source where we'll upload the content and where the sequenced
output will be stored ...
+config.repositorySource("store")
+ .usingClass(InMemoryRepositorySource.class)
+ .setDescription("The repository for our content")
+ .setProperty("defaultWorkspaceName", workspaceName);
+// Set up the JCR repository to use the source ...
+config.repository(repositoryId)
+ .addNodeTypes("sequencing.cnd")
+ .setSource("store")
+ .setOption(JcrRepository.Option.JAAS_LOGIN_CONFIG_NAME, "dna-jcr");
+// Set up the image sequencer ...
+config.sequencer("Image Sequencer")
+ .usingClass("org.jboss.dna.sequencer.image.ImageMetadataSequencer")
+ .loadedFromClasspath()
+ .setDescription("Sequences image files to extract the characteristics of the
image")
+
.sequencingFrom("//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd)[*])/jcr:content[@jcr:data]")
+ .andOutputtingTo("/images/$1");
+// Set up the MP3 sequencer ...
+config.sequencer("MP3 Sequencer")
+ .usingClass("org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer")
+ .loadedFromClasspath()
+ .setDescription("Sequences mp3 files to extract the id3 tags of the audio
file")
+ .sequencingFrom("//(*.mp3[*])/jcr:content[@jcr:data]")
+ .andOutputtingTo("/mp3s/$1");
+// Set up the Java source file sequencer ...
+config.sequencer("Java Sequencer")
+ .usingClass("org.jboss.dna.sequencer.java.JavaMetadataSequencer")
+ .loadedFromClasspath()
+ .setDescription("Sequences Java files to extract the AST structure of the Java
source code")
+ .sequencingFrom("//(*.java[*])/jcr:content[@jcr:data]")
+ .andOutputtingTo("/java/$1");
+
+// Now start the client and tell it which repository and workspace to use ...
+SequencingClient client = new SequencingClient(config, repositoryId, workspaceName);
+client.setUserInterface(new ConsoleInput(client));
+ ]]></programlisting>
+ <para>
+ The first block sets up the JAAS provider to be the IDTrust library and a policy file
that defines the "dna-jcr" JAAS configuration.
+ </para>
+ <para>
+ The second block of code configures the <code>JcrConfiguration</code> and
sets up the "store" source, the "content" repository,
+ and three sequencers. Again, this is done via the programmatic style. An alternative
would be to load the entire configuration
+ from a configuration file or from an existing configuration repository. (The
repository example shown in the
+ <link linkend="repository_example">next chapter</link> shows how
to load the configuration from a file.)
+ </para>
+ <para>
+ The third block simply instantiates the <code>SequencingClient</code>
class, passing the configuration and the name of the repository
+ and workspace, and finally sets the user interface (which then executes its behavior,
which we'll see below).
+ </para>
+ <para>
+ The <code>startRepository()</code> method builds the
<code>JcrEngine</code> component from the configuration, starts the engine,
+ and obtains the JCR <code>javax.jcr.Repository</code> instance that the
client will use. Note that the client has not yet
+ obtained a <code>javax.jcr.Session</code> instance, since this will be
done each time the client needs to access content from
+ the repository. (This is actually a common practice according to the JCR
specification, since Sessions are intended to be
+ very lightweight.)
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+public void startRepository() throws Exception {
+ if (this.repository == null) {
+ try {
+ // Start the DNA engine ...
+ this.engine = this.configuration.build();
+ this.engine.start();
+
+ // Now get the JCR repository instance ...
+ this.repository = this.engine.getRepository(repositoryName);
+ } catch (Exception e) {
+ this.repository = null;
+ throw e;
+ }
+ }
+}
+ ]]></programlisting>
+ <para>The <code>shutdownRepository()</code> method requests the
<code>JcrEngine</code> instance shuts down and, since that may take
+ a few moments (if there are any ongoing operations or enqueued activities) awaits
for it to complete the shutdown.
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+public void shutdownRepository() throws Exception {
+ if (this.repository != null) {
+ try {
+ this.engine.shutdown();
+ this.engine.awaitTermination(4, TimeUnit.SECONDS);
+ } finally {
+ this.repository = null;
+ }
+ }
+}
+ ]]></programlisting>
+ <para>None of the other methods really do anything with JBoss DNA
<emphasis>per se</emphasis>. Instead, they merely work with the repository
+ using the JCR API.</para>
+ <para>If we look at the <code>ConsoleInput</code> constructor, it
starts the repository and a thread
+ for the user interface. At this point, the constructor returns, but the main
application continues under the user interface thread.
+ When the user requests to quit, the user interface thread also shuts down the JCR
repository.</para>
+ <programlisting role="JAVA"><![CDATA[
+public ConsoleInput( SequencerClient client ) {
+ try {
+ client.startRepository();
+
+ System.out.println(getMenu());
+ Thread eventThread = new Thread(new Runnable() {
+ private boolean quit = false;
+ public void run() {
+ try {
+ while (!quit) {
+ // Display the prompt and process the requested operation ...
+ }
+ } finally {
+ try {
+ // Terminate ...
+ client.shutdownRepository();
+ } catch (Exception err) {
+ System.out.println("Error shutting down sequencing service and
repository: "
+ + err.getLocalizedMessage());
+ err.printStackTrace(System.err);
+ }
+ }
+ }
+ });
+ eventThread.start();
+ } catch (Exception err) {
+ System.out.println("Error: " + err.getLocalizedMessage());
+ err.printStackTrace(System.err);
+ }
+}
+ ]]></programlisting>
+ <para>At this point, we've reviewed all of the interesting code in the
example application related to JBoss DNA. However, feel free
+ to play with the application, trying different things.</para>
+ </sect1>
+ <sect1 id="using_dna_whats_next">
+ <title>What's next</title>
+ <para>
+ This chapter walked through running the sequencer example and looked at the example
code. With the sequencer client, you could upload files into a
+ JCR repository, while JBoss DNA automatically sequenced the image, MP3, or Java
source files you uploaded, extracted the metadata from the
+ files, and stored that metadata inside the repository.
+ </para>
+ <para>
+ In the <link linkend="repository_example">next chapter </link>
we'll do the same for the repository example.
+ </para>
+ </sect1>
+</chapter>
Property changes on:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/sequencer_example.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Deleted: trunk/docs/gettingstarted/src/main/docbook/en-US/content/understanding_dna.xml
===================================================================
---
trunk/docs/gettingstarted/src/main/docbook/en-US/content/understanding_dna.xml 2009-06-07
15:05:15 UTC (rev 988)
+++
trunk/docs/gettingstarted/src/main/docbook/en-US/content/understanding_dna.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -1,576 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ JBoss DNA (
http://www.jboss.org/dna)
- ~
- ~ See the COPYRIGHT.txt file distributed with this work for information
- ~ regarding copyright ownership. Some portions may be licensed
- ~ to Red Hat, Inc. under one or more contributor license agreements.
- ~ See the AUTHORS.txt file in the distribution for a full listing of
- ~ individual contributors.
- ~
- ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- ~ is licensed to you under the terms of the GNU Lesser General Public License as
- ~ published by the Free Software Foundation; either version 2.1 of
- ~ the License, or (at your option) any later version.
- ~
- ~ JBoss DNA is distributed in the hope that it will be useful,
- ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- ~ for more details.
- ~
- ~ You should have received a copy of the GNU Lesser General Public License
- ~ along with this distribution; if not, write to:
- ~ Free Software Foundation, Inc.
- ~ 51 Franklin Street, Fifth Floor
- ~ Boston, MA 02110-1301 USA
- -->
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="understanding_dna">
- <title>Understanding JBoss DNA</title>
- <sect1 id="jboss_dna_overview">
- <title>Overview</title>
- <para>JBoss DNA is a repository and set of tools that make it easy to capture,
version, analyze, and understand the
- fundamental building blocks of information. As models, service and process
definitions, schemas, source code, and other
- artifacts are added to the repository, JBoss DNA "sequences" the makeup
of these components and extracts their structure
- and interdependencies. The JBoss DNA web application will allow end users to
access, visualize, and edit this information in
- the terminology and structure they are familiar with. Such domain-specific
solutions can be easily created with little or
- no programming.</para>
- <para> JBoss DNA supports the Java Content Repository (JCR) standard and is
able to provide a single integrated view of
- multiple repositories, external databases, services, and applications, ensuring
that JBoss DNA has access to the latest
- and most reliable master data. For instance, DNA could provide in a single view
valuable insight into the business
- processes and process-level services impacted by a change to in an intermediary web
server operation defined via WSDL.
- Similarly, a user could quickly view and navigate the dependencies between the data
source models and transformation
- information stored within a content repository, the code base stored within a
version control system, and the database
- schemas used by an application.</para>
- </sect1>
- <sect1 id="architecture">
- <title>Architecture</title>
- <para>The planned architecture for JBoss DNA consists of several major
components that will be built on top of standard APIs,
- including JCR, JDBC, JNDI and HTTP. The goal is to allow these components to be
assembled as needed and add value on top
- of other DNA components or third-party systems that support these standard APIs.
Not all of these components exist
- yet - at the moment we're focusing on completing our JCR-compliant
implementation using our connector framework.</para>
- <mediaobject>
- <imageobject role="fo">
- <imagedata align="center" fileref="dna-architecture.png"
/>
- </imageobject>
- <imageobject role="html">
- <imagedata align="center" fileref="dna-architecture.png"
/>
- </imageobject>
- </mediaobject>
- <para>
- Let's go over each of these components, starting from the bottom of the
diagram:
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="strong">DNA Connectors</emphasis>
- are used to communicate with these external sources of information, whether
there's one source (like a database) in
- which all of the content is stored, or information is being federated from
multiple sources. The connector's
- job is to interact with the external source and map the source's information
into the lower-level graph language used by
- JBoss DNA. Connectors also may optionally participate in distributed transactions
by exposing an XAResource.
- In summary, then, the connector API isolates all of the other components from how
the graph are persisted.
- We've built a number of connectors already, but we're always interested in
adding more. Or, you could write your own,
- since we've designed the connector API to be as straightforward as possible.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA Federation</emphasis>
- is actually a special repository connector that accesses information from
multiple other sources via connectors,
- making all this information look like it is part of a single, unified repository.
Because it is a connector,
- it can be used wherever connectors can be used. And because it uses connectors,
the federation connector
- makes it possible to integrate a wide variety of external systems, like other JCR
- repositories, databases, applications, and services.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA JCR</emphasis>
- is an implementation of the JCR API that accesses the content from a single
connector. Our implementation has come a long
- way, and is nearly Level 1 and Level 2 compliant. Finishing the remaining
features, including search
- and query, are major objectives of our next release.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA Sequencers</emphasis>
- are pluggable components that automatically process content (typically files)
that are uploaded into the repository,
- looking for useful structure and information in that content. When a file is
uploaded to the repository, JBoss DNA automatically
- figures out which sequencer(s) should be run, and then runs them. Each sequencer,
then, extracts the meaningful information
- from the file's content and places that structure in the repository. Once this
information is in
- the repository, it can be viewed, edited, analyzed, searched, and related to
other content. DNA defines a Java
- interface that sequencers must implement. DNA sequencers operate upon any
JCR-compliant repository.
- We have a number of sequencers, but plan on adding more over time. Like
connectors, the Sequencer API makes it very
- simple to write sequencers for your own file types.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA Analyses</emphasis>
- are similar to sequencers, except they process the graph structure rather
than uploaded files. You can think of them
- as report generators, where they process some area of the repository and generate
output. The output doesn't take the
- form of a document or file, but rather more graph content that is then stored in
the repository, where it can be accessed
- and searched just like any other content. We're still figuring out how to best
make analyzers easy to write and use,
- and have been focused on other aspects of the architecture. But we're planning
on using analyzers for dependency,
- similarity, and statistical analyses.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA Maven</emphasis>
- is a classloader library compatible with Maven 2 project dependencies. This
allows the creation of Java ClassLoader
- instances using Maven 2 style paths, and all dependencies are transitively
managed and included. This exists but is
- still immature.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- The remaining parts of the architecture haven't yet been started, but they service
important purposes for a complete metadata
- repository system.
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="strong">DNA Eclipse Plugins</emphasis>
- enable Eclipse users to access the contents of a JBoss DNA repository. This
is a planned component that may be started soon.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA JDBC Driver</emphasis>
- provides a driver implementation, allowing JDBC-aware applications to connect
to and use a JBoss DNA repository.
- This is a planned component on our roadmap.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA Remote JCR</emphasis>
- is a client-side component for accessing remote JCR repositories.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA Web Application</emphasis>
- is used by end users and domain experts to visualize, search, edit, change
and tag the repository content. The web
- application uses views to define how different types of information are to be
presented and edited in
- domain-specific ways. The goal is that this web application is easily
customized and branded for inclusion into
- other solutions and application systems. The DNA Web Application operates
upon any JCR-compliant repository,
- although it does rely upon the DNA analysis and templating services.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA Publishing
Server</emphasis>
- allows content to be downloaded, uploaded, and edited using the Atom
Publishing Protocol. With the DNA Publishing
- Server, the content of the repository can easily be created, read, edited,
and deleted using the standard HTTP
- operations of POST, GET, PUT, and DELETE (respectively). More and more tools
are being created that support working
- with Atom Publishing servers. The DNA Publishing Server operates upon any
JCR-compliant repository.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA WebDAV Server</emphasis>
- allows clients such as Microsoft Windows and Apple OS X to connect to, read,
and edit the content in the repository
- using the WebDAV standard. WebDAV is an extension of HTTP, so web browsers
are able to access the content
- served by a WebDAV compliant server. The DNA WebDAV Server operates upon any
JCR-compliant repository.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">DNA Views</emphasis>
- are definitions of how types of information are to be presented in a user
interface to allow for creation, reading,
- editing, and deletion of information. DNA view definitions consist of data
stored in a JCR repository, and as such
- views can be easily added, changed or removed entirely by using the DNA Web
Application, requiring no programming.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Continue reading the rest of this chapter for more detail about the
- <link linkend="sequencers">sequencing framework</link>
available in this release, or the <link linkend="federation">federation
engine</link>
- and <link linkend="federation_connectors">connectors</link>.
Or, skip to the <link
linkend="downloading_and_running">examples</link>
- to see how to start using JBoss DNA &versionNumber; today.
- </para>
- </sect1>
- <sect1 id="sequencers">
- <title>Sequencing content</title>
- <para> The current JBoss DNA release contains a sequencing framework that is
designed to sequence data (typically files)
- stored in a JCR repository to automatically extract meaningful and useful
information. This additional information is then
- saved back into the repository, where it can be accessed and used.</para>
- <para> In other words, you can just upload various kinds of files into a JCR
repository, and DNA automatically processes
- those files to extract meaningful structured information. For example, load DDL
files into the repository, and let
- sequencers extract the structure and metadata for the database schema. Load
Hibernate configuration files into the
- repository, and let sequencers extract the schema and mapping information. Load
Java source into the repository, and let
- sequencers extract the class structure, JavaDoc, and annotations. Load a PNG, JPEG,
or other image into the repository,
- and let sequencers extract the metadata from the image and save it in the
repository. The same with XSDs, WSDL, WS
- policies, UML, MetaMatrix models, etc.</para>
- <para>
- JBoss DNA sequencers sit on top of existing JCR repositories (including federated
repositories) - they basically extract
- more useful information from what's already stored in the repository. And they
use the existing JCR event and versioning system. Each
- sequencer typically processes a single kind of file format or a single kind of
content. </para>
- <para>The following sequencers are included in JBoss DNA:
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="strong">Image sequencer</emphasis>
- - A sequencer that processes the binary content of an image file, extracts
the metadata for the image, and then
- writes that image metadata to the repository. It gets the file format, image
resolution, number of bits per pixel
- (and optionally number of images), comments and physical resolution from
JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM,
- PGM, PPM, and PSD files. (This sequencer may be improved in the future to
also extract EXIF metadata from JPEG
- files; see <ulink
url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>.)
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">MP3 sequencer</emphasis>
- - A sequencer that processes the contents of an MP3 audio file, extracts the
metadata for the file, and then
- writes that image metadata to the repository. It gets the title, author,
album, year, and comment.
- (This sequencer may be improved in the future to also extract other ID3
metadata from other audio file formats; see
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-66">DNA-66</ulink>.)
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">ZIP Archive
Sequencer</emphasis>
- - Process ZIP archive files to extract (explode) the contents into the
repository.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Java Source File
Sequencer</emphasis>
- - Process Java source files to extract the class structure (including
annotations) into the repository.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">XML File Sequencer</emphasis>
- - Process XML files to extract the structure into the repository.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Microsoft Office File
Sequencer</emphasis>
- - Process Microsoft Office documents, spreadsheets, and presentation files to
extract their basic structure.
- For example, the sequencer extracts the outline of a document, or the title and
outline of a presentation.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">JCR Compact Node Definition (CND)
File Sequencer</emphasis>
- - Process the CND files defined by JCR, extracting the various node types
with their property definitions and child
- node definitions.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- As the community develops additional sequencers, they will also be included in
JBoss DNA. Some of those that have been
- identified as being useful include:
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="strong">Data Definition Language (DDL)
Sequencer</emphasis>
- - Process various dialects of DDL, including that from Oracle, SQL Server,
MySQL, PostgreSQL, and others. May need
- to be split up into a different sequencer for each dialect. This sequencer is
being developed as part of a
- Google Summer of Code 2009 project. (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ul...
- )
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">XML Schema Document (XSD)
Sequencer</emphasis>
- - Process XSD files and extract the various elements, attributes, complex
types, simple types, groups, and other
- information. (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-32">DNA-32</ul...
- )
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Web Service Definition Language
(WSDL) Sequencer</emphasis>
- - Process WSDL files and extract the services, bindings, ports, operations,
parameters, and other information. (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-33">DNA-33</ul...
- )
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Hibernate File
Sequencer</emphasis>
- - Process Hibernate configuration (cfg.xml) and mapping (hbm.xml) files to
extract the configuration and mapping
- information. (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-61">DNA-61</ul...
- )
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">XML Metadata Interchange (XMI)
Sequencer</emphasis>
- - Process XMI documents that contain UML models or models using another
metamodel, extracting the model structure
- into the repository. (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-31">DNA-31</ul...
- )
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Java Archive (JAR)
Sequencer</emphasis>
- - Process JAR files to extract (explode) the contents into the classes and
file resources. (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-64">DNA-64</ul...
- )
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Java Class File
Sequencer</emphasis>
- - Process Java class files (bytecode) to extract the class structure
(including annotations) into the repository.
- (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-62">DNA-62</ul...
- )
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">PDF Sequencer</emphasis>
- - Process PDF files to extract the document metadata, including table of
contents. (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-50">DNA-50</ul...
- )
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Maven 2 POM
Sequencer</emphasis>
- - Process Maven 2 Project Object Model (POM) files to extract the project
information, dependencies, plugins, and
- other content. (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-24">DNA-24</ul...
- )
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">MP3 and MP4
Sequencer</emphasis>
- - Process MP3 and MP4 audio files to extract the name of the song, artist,
album, track number, and other metadata.
- (See
- <ulink
url="http://jira.jboss.org/jira/browse/DNA-30">DNA-30</ul...
- )
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- The
- <link linkend="using_dna">examples</link>
- in this book go into more detail about how sequencers are managed and used, and
- <link linkend="custom_sequencers">Chapter 5</link>
- goes into detail about how to write custom sequencers.
- </para>
- </sect1>
- <sect1 id="federation">
- <title>JCR and federated repositories</title>
- <para>There is a lot of information stored in many of different places:
databases, repositories, SCM systems,
- registries, file systems, services, etc. The purpose of the federation engine is to
allow applications to use the JCR API
- to access that information as if it were all stored in a single JCR repository, but
to really leave the information where
- it is.</para>
- <para>Why not just copy or move the information into a JCR repository? Moving
it is probably pretty difficult, since most
- likely existing applications rely upon that information being where it is. All of
those applications
- would break or have to change. And copying the information means that we'd have
to continually synchronize the changes.
- This not only is a lot of work, but it often creates issues with knowing which
information is accurate.
- </para>
- <para>The JBoss DNA allows lets us leave the information where it is, yet
provide access to that information to new applications through
- the JCR API. As the existing applications update the information in the original
systems, applications using JBoss DNA also see
- these updates. JCR clients even get the benefit of using JCR observation to be
notified of the changes. And if a JBoss DNA repository is
- configured to allow updates, client applications can change the information in the
repository and JBoss DNA will propagate
- those changes down to the original source.</para>
- <sect2 id="repository-connectors">
- <title>Connecting to information sources</title>
- <para>
- JBoss DNA uses connectors to interact with different information sources to get
at the content
- in those systems. We already have some connectors, including:</para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="strong">In-Memory Connector</emphasis>
- - Uses a Map instance as a repository. This is a simple connector that works
really well for small and transient graphs.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">JBoss Cache
Connector</emphasis>
- - Uses a JBoss Cache instance as a repository. JBoss Cache is a powerful
cache capable of persisting the information
- and being clustered for concurrent use by multiple processes.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Federation
Connector</emphasis>
- - Creates a single repository by accessing and federating the information in
multiple other repository sources.
- This is a powerful connector that is discussed in more detail in the <link
linkend="federated_repositories">next section</link>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">File System
Connector</emphasis>
- - Expose the files and directories on a file system through JCR.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">JPA-based Storage
Connector</emphasis>
- - Store and access information in a relational database through JPA. Also
useful for persisting information in the federated
- repository not stored elsewhere.
- </para>
- </listitem>
- </itemizedlist>
- <para>We're working on a few other connectors:</para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="strong">JDBC Metadata
Connector</emphasis>
- - Connect to relational databases via JDBC and expose their schema as content
in a repository.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">SVN Connector</emphasis>
- - Interact with Subversion software configuration management (SCM)
repositories to expose the managed resources
- through JCR. Consider using the
- <ulink
url="http://svnkit.com/">SVNkit</ulink>
- (dual license) library for an API into Subversion.
- </para>
- </listitem>
- </itemizedlist>
- <para>And even more connectors that are planned:</para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="strong">JCR Repository
Connector</emphasis>
- - Connect to and interact with other JCR repositories.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Maven 2 Repository
Connector</emphasis>
- - Access and expose the contents of a Maven 2 repository (either on the local
file system or via HTTP) through
- JCR.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">UDDI Connector</emphasis>
- - Interact with UDDI registries to integrate their content into a
repository.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">CVS Connector</emphasis>
- - Interact with CVS software configuration management (SCM) repositories to
expose the managed resources through
- JCR.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Distributed Database
Connector</emphasis>
- - Store and access information in a
- <ulink
url="http://www.hypertable.org/">Hypertable</ulink>
- or
- <ulink
url="http://hadoop.apache.org/hbase/">HBase</ulink>
- distributed databases. Also useful for persisting information in the
federated repository not stored elsewhere.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- If the connectors allow the information they contribute to be updated, they must
provide an
- <code>XAResource</code>
- implementation that can be used with a Java Transaction Service. Connectors that
provide read-only access need not
- provide an implementation.
- </para>
- <para>
- Also, connectors talk to
- <emphasis>sources</emphasis>
- of information, and it's quite likely that the same connector is used to talk
to different sources. Each source contains
- the configuration details (e.g., connection information, location, properties,
options, etc.) for working with that
- particular source, as well as a reference to the connector that should be used to
establish connections to the source.
- And of course, sources can be added or removed without having to stop and restart
the federated repository.
- </para>
- </sect2>
- <sect2 id="federated_repositories">
- <title>Federated repositories</title>
- <para> The federation connector works by effectively building up a single
graph by querying each source and merging or
- unifying the responses. This information is cached, which improves performance,
reduces the number of (potentially
- expensive) remote calls, reduces the load on the sources, and helps mitigate
problems with source availability. As
- clients interact with the repository, this cache is consulted first. When the
requested portion of the graph (or
- "subgraph") is contained completely in the cache, it is retuned
immediately. However, if any part of the requested
- subgraph is not in the cache, each source is consulted for their contributions to
that subgraph, and any results are
- cached.</para>
- <para> This basic flow makes it possible for the federated repository to
build up a local cache of the integrated graph
- (or at least the portions that are used by clients). In fact, the federated
repository caches information in a manner
- that is similar to that of the Domain Name System (DNS). As sources are consulted
for their contributions, the source
- also specifies whether it is the authoritative source for this information (some
sources that are themselves federated
- may not be the information's authority), whether the information may be
modified, the time-to-live (TTL) value (the time
- after which the cached information should be refreshed), and the expiration time
(the time after which the cached
- information is no longer valid). In effect, the source has complete control over
how the information it contributes is
- cached and used.</para>
- <para>
- The federated repository also needs to incorporate
- <emphasis>negative caching</emphasis>
- , which is storage of the knowledge that something does not exist. Sources can be
configured to contribute information
- only below certain paths (e.g.,
- <code>/A/B/C</code>
- ), and the federation engine can take advantage of this by never consulting that
source for contributions to information
- on other paths. However, below that path, any negative responses must also be
cached (with appropriate TTL and expiry
- parameters) to prevent the exclusion of that source (in case the source has
information to contribute at a later time)
- or the frequent checking with the source.
- </para>
- </sect2>
- <sect2 id="federation_queries">
- <title>Searching and querying</title>
- <para> The JBoss DNA federated repository will support queries against the
integrated and unified graph. In some
- situations the query can be determined to apply to a single source, but in most
situations the query must be planned
- (and possibly rewritten) such that it can be pushed down to all the appropriate
sources. Also, the cached results must
- be consulted prior to returning the query results, as the results from one source
might have contributions from another
- source.</para>
- <para>Searching the whole federated repository is also important. This allows
users to simply supply a handful of
- search terms, and to get results that are ranked based upon how close each result
is to the search terms. (Searching is
- very different from querying, which involves specifying the exact semantics of
what is to be searched and how the
- information is to be compared.) JBoss DNA will incorporate a search engine (e.g.,
likely to be Lucene) and will populate
- the engine's indexes using the federated content and the cached information.
Notifications of changing information will
- be reflected in the indexes, but some sources may want to explicitly allow or
disallow periodic crawling of their
- content.</para>
- </sect2>
- <sect2 id="federation_updates">
- <title>Updating content</title>
- <para>
- The JBoss DNA federated repositories also make it possible for client
applications to make changes to the unified graph
- within the context of distributed transactions. According to the JCR API, client
applications use the Java Transaction
- API (JTA) to control the boundaries of their transactions. Meanwhile, the
federated repository uses a
- <ulink
url="http://www.jboss.org/jbosstm/">distributed
transaction service</ulink>
- to coordinate the XA resources provided by the connectors.
- </para>
- <para> It is quite possible that clients add properties to nodes in the
unified graph, and that this information cannot be
- handled by the same underlying source that contributed to the node. In this case,
the federated repository can be
- configured with a fallback source that will be used used to store this
"extra" information.</para>
- <para>
- It is a goal that non-XA sources (i.e., sources that use connectors without XA
resources) can participate in distributed
- transactions through the use of
- <emphasis>compensating transactions</emphasis>
- . Because the JBoss DNA federation engine implements the JCR observation system,
it is capable of recording all of the
- changes made to the distributed graph (and those changes sent to each updatable
source). Therefore, if a non-XA source
- is involved in a distributed transaction that must be rolled back, any changes
made to non-XA sources can be undone. (Of
- course, this does not make the underlying source transactional: non-transactional
sources still may expose the interim
- changes to other clients.)
- </para>
- </sect2>
- <sect2 id="federation_events">
- <title>Observing changes</title>
- <para> The JCR API supports observing a repository to receive notifications
of additions, changes and deletions of nodes
- and properties. The JBoss DNA federated repository will support this API through
two primary means.</para>
- <para> When the changes are made through the federated repository, the JBoss
DNA federation engine is well aware of the
- set of changes that have been (or are being) made to the unified graph. These
events are directly propagated to
- listeners.</para>
- <para> Sources have the ability to publish events, making it possible for the
JBoss DNA federation engine and clients that
- have registered listeners to be notified of changes in the information managed by
that source. These events are first
- processed by the federation engine and possibly altered based upon contributions
from other sources. (The federation
- engine also uses these events to update or purge information in the cache, which
may add to the event set.) The
- resulting (and possibly altered) event set is then sent to all client
listeners.</para>
- </sect2>
- </sect1>
-</chapter>
Added: trunk/docs/gettingstarted/src/main/docbook/en-US/content/use_cases.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/use_cases.xml
(rev 0)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/use_cases.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ JBoss DNA (
http://www.jboss.org/dna)
+ ~
+ ~ See the COPYRIGHT.txt file distributed with this work for information
+ ~ regarding copyright ownership. Some portions may be licensed
+ ~ to Red Hat, Inc. under one or more contributor license agreements.
+ ~ See the AUTHORS.txt file in the distribution for a full listing of
+ ~ individual contributors.
+ ~
+ ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ ~ is licensed to you under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ JBoss DNA is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
+<chapter id="use_cases">
+ <title>JBoss DNA Use Cases</title>
+ <para>There are lots of ways to use JBoss DNA in your own applications, but this
chapter attempts to show some representative
+ scenarios that take advantage of JBoss DNA's support for the JCR API as well as the
federation, integration, and sequencing
+ capabilities.
+ </para>
+ <sect1 id="service_repository">
+ <title>Service repository</title>
+ <para>
+ In a SOA environment, one important component is a service registry that provides
versioned storage of all the artifacts
+ that describe the services, their capabilities/restrictions, and the policies that
surround them. Service repositories
+ contain information that define the services and their message models, ownership,
availability, security requirements/abilities, auditing,
+ funding, monitoring, provisioning, provenance, usage, discovery mechanism,
configuration, documentation, relationships
+ to other services, classification taxonomies, ontologies, and many other important
aspects.
+ </para>
+ <para>
+ A JCR repository provides an excellent starting point for a service repository. The
ability to store a wide range of
+ content, ranging from structured information to documents, means that a JCR repository
can offer the flexibility
+ to manage and organize the information while maintaining the ability to adapt the
structure and schema as needs evolve
+ over time.
+ </para>
+ <para>
+ A service repository will contain lots of information represented in different forms,
and it's important that the repository
+ make it easy for users to quickly find what they need. Organization of the
information (probably in multiple hierarchies and with tags)
+ is important, but more important is the ability for users to use simple searching (or
more advanced queries) to return ranked
+ results that match the criteria. For search to be effective, it is important that the
repository understand the different
+ kinds of artifacts that are uploaded and the information they contain.
+ </para>
+ <para>
+ JCR repositories are naturally searchable and queryable, but also can be used to
integrate a taxonomy (or folksonomic tags)
+ with the content, allowing the same content to be presented in different hierarchical
classifications.
+ But JBoss DNA capabilities also offer a great advantage, since any file that is
uploaded can be automatically sequenced and processed
+ to extract information that's meaningful and useful but often locked up within the
file. For example, when a WSDL file is uploaded,
+ the appropriate sequencer(s) process the file and extract and stores in the repository
the structured information describing the types,
+ message structures, operations, port types, bindings, and services found within the
WSDL file.
+ When an XML Schema Document is uploaded, JBoss DNA can do the same for the
schema's complex and simple types, element and attribute
+ declarations, model groups, namespaces, imports, includes, annotations, etc. And
JBoss DNA can do the same for the various policy files,
+ resource declarations, documentation, presentations, ontologies, etc.
+ </para>
+ <para>
+ It is also desirable that the service registry can provide accurate and up-to-date
information about where the services are deployed
+ and their current health. The best way to do this would be to access this information
directly from the other components of the SOA,
+ such as the Enterprise Service Bus and the management/monitoring system. JBoss DNA
connectors might allow the service registry
+ to access an ESB to discover which services are deployed, which are running, and
automatically annotate the services in the registry
+ with this dynamic information. In fact, the service registry could cache this
information to provide a safe and low-impact mechanism
+ for obtaining this information to other applications without having each application
hit the ESB.
+ </para>
+ <para>
+ Integration with a management system can be done in a similar manner. A JBoss DNA
connector could access the management system
+ to discover the servers and enable auto-discovery of the services, and "tag"
the services deployments with the lifecycle phase
+ (dev, test, production, etc.).
+ </para>
+ <para>
+ By using JBoss DNA, a service repository could manage the wide range of artifacts
required in a SOA or web-oriented architecture,
+ yet be able to present a unified view of all service information.
+ </para>
+ </sect1>
+ <sect1 id="data_source_management">
+ <title>Manage data sources and services</title>
+ <para>
+ Many enterprise environments include numerous databases and data services, yet there
is often no single place where all
+ these different assets are described or related. A data source/service repository
could provide information about the
+ many databases running within the enterprise as well as their documentation, schema
history, availability, usage policies,
+ current users of the data (including applications, ETL processes, reporting),
geographic deployments and synchronization,
+ and the provenance of the data.
+ </para>
+ <para>
+ Some of this information may actually be defined or controlled within the data sources
themselves or within other systems.
+ For example, the DDL scripts used to migrate the database schemas are (hopefully)
stored in a version control system,
+ and the databases themselves have the ability to describe their current schemas.
Using JBoss DNA, the repository could
+ use a connector to the version control system to expose the scripts, as well as
connectors to the databases to expose
+ (and cache) the current schema of the databases. The data repository would then be
able to allow users to search over
+ this information without even touching the underlying systems.
+ </para>
+ <para>
+ However, the power of a data repository is really the ability to capture the
relationships that otherwise were only captured
+ in people's heads or trapped in documents spread throughout the network. A data
repository can capture the policies that
+ dictate how each data source should be used (which are for development purposes, or
QA/testing purposes, or which are production,
+ and how are they all related), and it can integrate with management systems to provide
information about
+ availability and deployment. As web services are created to provide service-based
access to the data in databases,
+ the repository can be used to maintain the relationships between these
<emphasis>data services</emphasis> and the underlying sources.
+ Similarly, the repository can track how the databases are used by applications, ETL
processes, and reports.
+ </para>
+ </sect1>
+ <sect1 id="configuration_repository">
+ <title>Configuration repository</title>
+ <para>
+ Many applications and libraries have configuration files that allow the users (or
developers) to dictate the setup and behavior.
+ Often this involves multiple files in a specific structure on the file system. But
invalid or inopportune changes to these files
+ sometimes corrupt the environment, but creating a more robust configuration management
system is often way beyond the desired
+ effort.
+ </para>
+ <para>
+ An embedded JBoss DNA repository can provide a more formal and flexible configuration
system with little effort. JCR's
+ event system allows the system to be notified when the configuration changes, and
versioning can help guarantee the ability
+ to revert back to a previous (valid) configuration. JBoss DNA connectors can be used
to integrate the files on the file system
+ into the configuration system, keeping it natural for those wanting to view and change
the configuration via the files.
+ JBoss DNA sequencers can even process the configuration files to extract a more
structured view of the system.
+ And because JBoss DNA can used with a minimal footprint, it provides the ability to
manage and version the configuration
+ with little overhead.
+ </para>
+ <para>
+ JBoss DNA can even be used to centralize the configuration definition for a clustered
or distributed system. In this mode,
+ the configuration is managed in a central repository that is remotely accessible by
the application. When a process is started,
+ it examines the repository and reads the content containing its configuration. The
application can monitor the configuration for
+ changes so that it can modify itself and its components.
+ For larger deployments, a central "enterprise configuration" repository can
house the configuration of different kinds of systems,
+ and can even be managed and manipulated through JCR.
+ </para>
+ <para>
+ As we'll see in the <link linkend="using_dna">next
chapter</link>, this is actually the way in which JBoss DNA manages
+ its own configuration. In the embedded case, the configuration repository is simply a
local (in-memory) repository that
+ is populated by the configuration file (or programmatic API). In a clustered mode,
the repository is centralized. But either
+ way, to JBoss DNA the configuration is always defined in a repository.
+ </para>
+ </sect1>
+ <sect1 id="use_case_whats_next">
+ <title>What's next</title>
+ <para>
+ The scenarios described in this chapter are representative of some of the ways in
which JBoss DNA can be used, and hopefully
+ give you ideas about how you can leverage JBoss DNA in your application or library.
+ </para>
+ <para>
+ In the <link linkend="using_dna">next chapter</link>, we'll
show how you can set up JBoss DNA and use it via the standard JCR API.
+ </para>
+ </sect1>
+</chapter>
Property changes on:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/use_cases.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna.xml
(rev 0)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -0,0 +1,371 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ JBoss DNA (
http://www.jboss.org/dna)
+ ~
+ ~ See the COPYRIGHT.txt file distributed with this work for information
+ ~ regarding copyright ownership. Some portions may be licensed
+ ~ to Red Hat, Inc. under one or more contributor license agreements.
+ ~ See the AUTHORS.txt file in the distribution for a full listing of
+ ~ individual contributors.
+ ~
+ ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ ~ is licensed to you under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ JBoss DNA is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd " [
+<!ENTITY % CustomDTD SYSTEM "../custom.dtd">
+%CustomDTD;
+]>
+<chapter id="using_dna">
+ <title>Using JBoss DNA</title>
+ <para>Using JBoss DNA within your application is actually quite straightforward.
As you'll see in this chapter,
+ the first step is setting up JBoss DNA and starting the
<code>JcrEngine</code>. After that, you obtain the
+ <code>javax.jcr.Repository</code> instance for a named repository and just
use the standard JCR API throughout your
+ application.
+ </para>
+ <sect1 id="jcr_engine">
+ <title>JBoss DNA's JcrEngine</title>
+ <para>
+ JBoss DNA encapsulates everything necessary to run one or more JCR repositories into a
single &JcrEngine; instance.
+ This includes all underlying repository sources, the pools of connections to the
sources, the sequencers,
+ the MIME type detector(s), and the &Repository; implementations.
+ </para>
+ <para>
+ Obtaining a &JcrEngine; instance is very easy - assuming that you have a valid
&JcrConfiguration; instance. We'll see
+ how to get one of those in a little bit, but if you have one then all you have to do
is build and start the engine:
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+JcrConfiguration config = ...
+JcrEngine engine = config.build();
+engine.start();
+ ]]></programlisting>
+ <para>
+ Obtaining a JCR &Repository; instance is a matter of simply asking the engine for
it by the name defined in the configuration:
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+javax.jcr.Repository repository = engine.getRepository("Name of repository");
+ ]]></programlisting>
+ <para>
+ At this point, your application can proceed by working with the JCR API.
+ </para>
+ <para>
+ And, once you're finished with the &JcrEngine;, you should shut it down:
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+engine.shutdown();
+engine.awaitTermination(3,TimeUnit.SECONDS); // optional
+ ]]></programlisting>
+ <para>
+ When the <code>shutdown()</code> method is called, the &Repository;
instances managed by the engine are marked as being shut down,
+ and they will not be able to create new &Session;s. However, any existing
&Session;s or ongoing operations (e.g., event notifications)
+ present at the time of the <code>shutdown()</code> call will be allowed to
finish.
+ In essence, <code>shutdown()</code> is a
<emphasis>graceful</emphasis> request, and since it may take some time to
complete,
+ you can wait until the shutdown has completed by simply calling
<code>awaitTermination(...)</code> as shown above.
+ This method will block until the engine has indeed shutdown or until the supplied time
duration has passed (whichever comes first).
+ And, yes, you can call the <code>awaitTermination(...)</code> method
repeatedly if needed.
+ </para>
+ </sect1>
+ <sect1 id="jcr_configuration">
+ <title>JcrConfiguration</title>
+ <para>
+ The previous section assumed the existence of a &JcrConfiguration;. It's not
really that creating an instance is all that difficult.
+ In fact, there's only one no-argument constructor, so actually creating the
instance is a piece of cake. What can be a little more challenging,
+ though, is setting up the &JcrConfiguration; instance, which must define the
following components:
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="strong"><code>Repository
sources</code></emphasis> are the POJO objects that each describe a
particular
+ location where content is stored. Each repository source object is an instance of a
JBoss DNA connector, and is configured
+ with the properties that particular source. JBoss DNA's &RepositorySource;
classes are analogous to JDBC's &DataSource; classes -
+ they are implemented by specific connectors (aka, "drivers") for specific
kinds of repository sources (aka, "databases").
+ Similarly, a &RepositorySource; instance is analogous to a &DataSource;
instance, with bean properties for each configurable
+ parameter. Therefore, each repository source definition must supply the name of the
&RepositorySource; class, any
+ bean properties, and, optionally, the classpath that should be used to load the
class. </para>
+ </listitem>
+ <listitem>
+ <para><emphasis
role="strong"><code>Repositories</code></emphasis> define
the JCR repositories that are available. Each
+ repository has a unique name that is used to obtain the &Repository; instance
from the &JcrEngine;'s <code>getRepository(String)</code>
+ method, but each repository definition also can include the predefined namespaces
(other than those automatically defined by
+ JBoss DNA), various options, and the node types that are to be available in the
repository without explicit registration
+ through the JCR API.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis
role="strong"><code>Sequencers</code></emphasis> define the
particular sequencers that are available for use.
+ Each sequencer definition provides the path expressions governing which nodes in the
repository should be sequenced when those nodes change,
+ and where the resulting output generated by the sequencer should be placed. The
definition also must state the name of
+ the sequencer class, any bean properties and, optionally, the classpath that should
be used to load the class.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis role="strong"><code>MIME type
detectors</code></emphasis> define the particular MIME type detector(s) that
should
+ be made available. A MIME type detector does exactly what the name implies: it
attempts to determine the MIME type given a
+ "filename" and contents. JBoss DNA automatically uses a detector that
uses the file extension to identify the MIME type,
+ but also provides an implementation that uses an external library to identify the
MIME type based upon the contents.
+ The definition must state the name of the detector class, any bean properties and,
optionally, the classpath that should
+ be used to load the class.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ There really are three options:
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="strong"><code>Load from a
file</code></emphasis> is conceptually the easiest and requires the least
amount
+ of Java code, but it now requires a configuration file.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis role="strong"><code>Load from a
configuration repository</code></emphasis> is not much more complicated than
loading
+ from a file, but it does allow multiple &JcrEngine; instances (usually in
different processes perhaps on different machines)
+ to easily access their (shared) configuration. And technically, loading the
configuration from a file really just creates an
+ &InMemoryRepositorySource;, imports the configuration file into that source, and
then proceeds with this approach.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis role="strong"><code>Programmatic
configuration</code></emphasis> is always possible, even if the configuration
is loaded
+ from a file or repository. Using the &JcrConfiguration;'s API, you can
define (or update or remove) all of the definitions that make
+ up a configuration.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Each of these approaches has their obvious advantages, so the choice of which one to
use is entirely up to you.
+ </para>
+ <sect2 id="loading_from_file">
+ <title>Loading from a configuration file</title>
+ <para>
+ Loading the JBoss DNA configuration from a file is actually very simple:
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+JcrConfiguration config = new JcrConfiguration();
+configuration.loadFrom(file);
+ ]]></programlisting>
+ <para>
+ where the <code>file</code> parameter can actually be a &File;
instance, a &URL; to the file, an &InputStream;
+ containing the contents of the file, or even a &String; containing the contents
of the file.
+ </para>
+ <note>
+ <para>The <code>loadFrom(...)</code> method can be called any
number of times, but each time it is called it completely wipes
+ out any current notion of the configuration and replaces it with the configuration
found in the file.
+ </para>
+ </note>
+ <para>
+ There is an optional second parameter that defines the &Path; within the
configuration file identifying the parent node of the various
+ configuration nodes. If not specified, it assumes "/". This makes it
possible for the configuration content to be
+ located at a different location in the hierarchical structure. (This is not often
required, but when it is required
+ this second parameter is very useful.)
+ </para>
+ <para>
+ Here is the configuration file that is used in the repository example, though it has
been simplified a bit and most comments
+ have been removed for clarity):
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration
xmlns="http://www.jboss.org/dna/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0">
+ <!--
+ Define the JCR repositories
+ -->
+ <dna:repositories>
+ <!--
+ Define a JCR repository that accesses the 'Cars' source directly.
+ This of course is optional, since we could access the same content through
'vehicles'.
+ -->
+ <dna:repository jcr:name="car repository"
dna:source="Cars">
+ <options jcr:primaryType="dna:options"/>
+ <jaasLoginConfigName jcr:primaryType="dna:option"
dna:value="dna-jcr"/>
+ </options>
+ </dna:repository>
+ </dna:repositories>
+ <!--
+ Define the sources for the content. These sources are directly accessible using the
DNA-specific Graph API.
+ -->
+ <dna:sources jcr:primaryType="nt:unstructured">
+ <dna:source jcr:name="Cars"
dna:classname="org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource"
dna:retryLimit="3" dna:defaultWorkspaceName="workspace1"/>
+ <dna:source jcr:name="Aircraft"
dna:classname="org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource">
+ <!-- Define the name of the workspace used by default. Optional, but
convenient. -->
+ <defaultWorkspaceName>workspace2</defaultWorkspaceName>
+ </dna:source>
+ </dna:sources>
+ <!--
+ Define the sequencers. This is an optional section. For this example, we're not
using any sequencers.
+ -->
+ <dna:sequencers>
+ <!--dna:sequencer jcr:name="Image Sequencer"
dna:classname="org.jboss.dna.sequencer.image.ImageMetadataSequencer">
+ <dna:description>Image metadata sequencer</dna:description>
+ <dna:pathExpression>/foo/source =>
/foo/target</dna:pathExpression>
+ <dna:pathExpression>/bar/source =>
/bar/target</dna:pathExpression>
+ </dna:sequencer-->
+ </dna:sequencers>
+ <dna:mimeTypeDetectors>
+ <dna:mimeTypeDetector jcr:name="Detector"
dna:description="Standard extension-based MIME type detector"/>
+ </dna:mimeTypeDetectors>
+</configuration>
+ ]]></programlisting>
+ </sect2>
+ <sect2 id="loading_from_repository">
+ <title>Loading from a configuration repository</title>
+ <para>
+ Loading the JBoss DNA configuration from an existing repository is also pretty
straightforward. Simply create and configure the
+ &RepositorySource; instance to point to the desired repository, and then call the
<code>loadFrom(&RepositorySource; source)</code>
+ method:
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+RepositorySource configSource = ...
+JcrConfiguration config = new JcrConfiguration();
+configuration.loadFrom(configSource);
+ ]]></programlisting>
+ <para>
+ This really is a more advanced way to define your configuration, so we won't go
into how you configure a &RepositorySource;.
+ For more information, consult the &ReferenceGuide;.
+ </para>
+ <note>
+ <para>The <code>loadFrom(...)</code> method can be called any
number of times, but each time it is called it completely wipes
+ out any current notion of the configuration and replaces it with the configuration
found in the file.
+ </para>
+ </note>
+ <para>
+ There is an optional second parameter that defines the name of the workspace in the
supplied source where the configuration content
+ can be found. It is not needed if the workspace is the source's default
workspace.
+ There is an optional third parameter that defines the &Path; within the
configuration repository identifying the parent node of the various
+ configuration nodes. If not specified, it assumes "/". This makes it
possible for the configuration content to be
+ located at a different location in the hierarchical structure. (This is not often
required, but when it is required
+ this second parameter is very useful.)
+ </para>
+ </sect2>
+ <sect2 id="programmatic_configuration">
+ <title>Programmatic configuration</title>
+ <para>
+ Defining the configuration programmatically is not terribly complicated, and it for
obvious reasons results in more verbose Java code.
+ But this approach is very useful and often the easiest approach when the
configuration must change or is a reflection of other
+ dynamic information.
+ </para>
+ <para>
+ The &JcrConfiguration; class was designed to have an easy-to-use API that makes
it easy to configure each of the different kinds of
+ components, especially when using an IDE with code completion. Here are several
examples:
+ </para>
+ <sect3 id="programmatically_configuring_sources">
+ <title>Repository sources</title>
+ <para>Each repository source definition must include the name of the
&RepositorySource; class as well as each bean property
+ that should be set on the object:
+ </para>
+ <programlisting role="JAVA"><![CDATA[
+JcrConfiguration config = ...
+config.repositorySource("source A")
+ .usingClass(InMemoryRepositorySource.class)
+ .setDescription("The repository for our content")
+ .setProperty("defaultWorkspaceName", workspaceName);
+ ]]></programlisting>
+ <para>
+ This example defines an in-memory source with the name "source A", a
description, and a single "defaultWorkspaceName" bean property.
+ Different &RepositorySource; implementations will the bean properties that are
required and optional.
+ Of course, the class can be specified as Class reference or a string (followed by
whether the class should be loaded from
+ the classpath or from a specific classpath).
+ </para>
+ <note>
+ <para>Each time <code>repositorySource(String)</code> is called,
it will either load the existing definition with the supplied
+ name or will create a new definition if one does not already exist. To remove a
definition, simply call <code>remove()</code>
+ on the result of <code>repositorySource(String)</code>.
+ The set of existing definitions can be accessed with the
<code>repositorySources()</code> method.
+ </para>
+ </note>
+ </sect3>
+ <sect3 id="programmatically_configuring_repositories">
+ <title>Repositories</title>
+ <para>Each repository must be defined to use a named repository source, but all
other aspects (e.g., namespaces, node types, options)
+ are optional.</para>
+ <programlisting role="JAVA"><![CDATA[
+JcrConfiguration config = ...
+config.repository("repository A")
+ .addNodeTypes("myCustomNodeTypes.cnd")
+ .setSource("source 1")
+ .registerNamespace("acme","http://www.example.com/acme")
+ .setOption(JcrRepository.Option.JAAS_LOGIN_CONFIG_NAME, "dna-jcr");
+ ]]></programlisting>
+ <para>
+ This example defines a repository that uses the "source 1" repository
source (which could be a federated source, an in-memory source,
+ a database store, or any other source). Additionally, this example adds the node
types in the "myCustomNodeTypes.cnd" file as those
+ that will be made available when the repository is accessed. It also defines the
"http://www.example.com/acme" namespace,
+ and finally sets the "JAAS_LOGIN_CONFIG_NAME" option to define the name of
the JAAS login configuration that should be used by
+ the JBoss DNA repository.
+ </para>
+ <note>
+ <para>Each time <code>repository(String)</code> is called, it will
either load the existing definition with the supplied
+ name or will create a new definition if one does not already exist. To remove a
definition, simply call <code>remove()</code>
+ on the result of <code>repository(String)</code>.
+ The set of existing definitions can be accessed with the
<code>repositories()</code> method.
+ </para>
+ </note>
+ </sect3>
+ <sect3 id="programmatically_configuring_sequencers">
+ <title>Sequencers</title>
+ <para>Each defined sequencer must specify the name of the &StreamSequencer;
implementation class as well as the path expressions
+ defining which nodes should be sequenced and the output paths defining where the
sequencer output should be placed (often as a function
+ of the input path expression).</para>
+ <programlisting role="JAVA"><![CDATA[
+JcrConfiguration config = ...
+config.sequencer("Image Sequencer")
+ .usingClass("org.jboss.dna.sequencer.image.ImageMetadataSequencer")
+ .loadedFromClasspath()
+ .setDescription("Sequences image files to extract the characteristics of the
image")
+
.sequencingFrom("//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd)[*])/jcr:content[@jcr:data]")
+ .andOutputtingTo("/images/$1");
+ ]]></programlisting>
+ <para>
+ This shows an example of a sequencer definition named "Image Sequencer"
that uses the &ImageMetadataSequencer; class
+ (loaded from the classpath), that is to sequence the "jcr:data" property
on any new or changed nodes that are named
+ "jcr:content" below a parent node with a name ending in ".jpg",
".jpeg", ".gif", ".bmp", ".pcx", ".iff",
".ras",
+ ".pbm", ".pgm", ".ppm" or ".psd". The
output of the sequencing operation should be placed at the "/images/$1" node,
+ where the "$1" value is captured as the name of the parent node. (The
capture groups work the same was as regular expressions;
+ see the &ReferenceGuide; for more details.)
+ Of course, the class can be specified as Class reference or a string (followed by
whether the class should be loaded from
+ the classpath or from a specific classpath).
+ </para>
+ <note>
+ <para>Each time <code>sequencer(String)</code> is called, it will
either load the existing definition with the supplied
+ name or will create a new definition if one does not already exist. To remove a
definition, simply call <code>remove()</code>
+ on the result of <code>sequencer(String)</code>.
+ The set of existing definitions can be accessed with the
<code>sequencers()</code> method.
+ </para>
+ </note>
+ </sect3>
+ <sect3 id="programmatically_configuring_mime_type_detectors">
+ <title>MIME type detectors</title>
+ <para>Each defined MIME type detector must specify the name of the
&MimeTypeDetector; implementation class as well as any
+ other bean properties required by the implementation.</para>
+ <programlisting role="JAVA"><![CDATA[
+JcrConfiguration config = ...
+config.mimeTypeDetector("Extension Detector")
+ .usingClass(org.jboss.dna.graph.mimetype.ExtensionBasedMimeTypeDetector.class);
+ ]]></programlisting>
+ <para>
+ Of course, the class can be specified as Class reference or a string (followed by
whether the class should be loaded from
+ the classpath or from a specific classpath).
+ </para>
+ <note>
+ <para>Each time <code>mimeTypeDetector(String)</code> is called,
it will either load the existing definition with the supplied
+ name or will create a new definition if one does not already exist. To remove a
definition, simply call <code>remove()</code>
+ on the result of <code>mimeTypeDetector(String)</code>.
+ The set of existing definitions can be accessed with the
<code>mimeTypeDetectors()</code> method.
+ </para>
+ </note>
+ </sect3>
+ </sect2>
+ </sect1>
+ <sect1 id="using_dna_whats_next">
+ <title>What's next</title>
+ <para>
+ This chapter outline how you configure JBoss DNA, how you then access a
<code>javax.jcr.Repository</code> instance,
+ and use the standard JCR API to interact with the repository. The
+ <link linkend="downloading_and_running">next chapter </link>
walks you through downloading
+ and running the JBoss DNA examples.
+ </para>
+ </sect1>
+</chapter>
Property changes on:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Deleted:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_for_sequencing.xml
===================================================================
---
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_for_sequencing.xml 2009-06-07
15:05:15 UTC (rev 988)
+++
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_for_sequencing.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -1,558 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ JBoss DNA (
http://www.jboss.org/dna)
- ~
- ~ See the COPYRIGHT.txt file distributed with this work for information
- ~ regarding copyright ownership. Some portions may be licensed
- ~ to Red Hat, Inc. under one or more contributor license agreements.
- ~ See the AUTHORS.txt file in the distribution for a full listing of
- ~ individual contributors.
- ~
- ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- ~ is licensed to you under the terms of the GNU Lesser General Public License as
- ~ published by the Free Software Foundation; either version 2.1 of
- ~ the License, or (at your option) any later version.
- ~
- ~ JBoss DNA is distributed in the hope that it will be useful,
- ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- ~ for more details.
- ~
- ~ You should have received a copy of the GNU Lesser General Public License
- ~ along with this distribution; if not, write to:
- ~ Free Software Foundation, Inc.
- ~ 51 Franklin Street, Fifth Floor
- ~ Boston, MA 02110-1301 USA
- -->
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="using_dna_for_sequencing">
- <title>Using JBoss DNA for Sequencing</title>
- <para>As we've mentioned before, JBoss DNA is able to work with existing JCR
repositories. Your client applications
- make changes to the information in those repositories, and JBoss DNA automatically
uses its sequencers to extract
- additional information from the uploaded files.</para>
- <note>
- <para>Configuring JBoss DNA services is a bit more manual than is ideal. As
you'll see, JBoss DNA uses dependency
- injection to allow a great deal of flexibility in how it can be configured and
customized. But this flexibility
- makes it more difficult for you to use. We understand this, and will soon provide
a much easier way to set up
- and manage JBoss DNA. Current plans are to use the <ulink
url="http://www.jboss.org/jbossmc">JBoss Microcontainer</ulink>
- along with a configuration repository.</para>
- </note>
- <sect1 id="sequencing_service">
- <title>Configuring the Sequencing Service</title>
- <para>The JBoss DNA <emphasis>sequencing service</emphasis> is the
component that manages the <emphasis>sequencers</emphasis>,
- reacting to changes in JCR repositories and then running the appropriate sequencers.
- This involves processing the changes on a node, determining which (if any)
sequencers should be run on that node,
- and for each sequencer constructing the execution environment, calling the
sequencer, and saving the information
- generated by the sequencer.</para>
- <para>To set up the sequencing service, an instance is created, and dependent
components are injected into
- the object. This includes among other things:
- <itemizedlist>
- <listitem>
- <para>An <emphasis>execution context</emphasis> that defines the
context in which the service runs, including
- a factory for JCR sessions given names of the repository and workspace. This
factory must be configured,
- and is how JBoss DNA knows about your JCR repositories and how to connect to
them. More on this a bit later.</para>
- </listitem>
- <listitem>
- <para>An <code>java.util.concurrent.ExecutorService</code> used to
execute the sequencing activites. If none
- is supplied, a new single-threaded executor is created by calling
<code>Executors.newSingleThreadExecutor()</code>.
- (This can easily be changed by subclassing and overriding the
<code>SequencerService.createDefaultExecutorService()</code>
method.)</para>
- </listitem>
- <listitem>
- <para>Filters for sequencers and events. By default, all sequencers are
considered for "node added", "property added"
- and "property changed" events.</para>
- </listitem>
- </itemizedlist>
- </para>
- <para>As mentioned above, the <code>JcrExecutionContext</code>
provides access to a <code>SessionFactory</code> that is used
- by JBoss DNA to establish sessions to your JCR repositories. Two implementations
are available:
- <itemizedlist>
- <listitem>
- <para>The <code>JndiSessionFactory</code> looks up JCR
<code>Repository</code> instances in JNDI using
- names that are supplied when creating sessions. This implementation also
has methods to set the
- JCR <code>Credentials</code> for a given workspace
name.</para>
- </listitem>
- <listitem>
- <para>The <code>SimpleSessionFactory</code> has methods to
register the JCR <code>Repository</code> instances
- with names, as well as methods to set the JCR
<code>Credentials</code> for a given workspace name.</para>
- </listitem>
- </itemizedlist>
- You can use the <code>SimpleExecutionContext</code> implementation of
<code>ExecutionContext</code> and supply
- a <code>SessionFactory</code> instance, or you can provide your own
implementation.</para>
- <para>Here's an example of how to instantiate and configure the
SequencingService:</para>
- <programlisting role="JAVA"><![CDATA[
-SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
-sessionFactory.registerRepository("Repository", this.repository);
-Credentials credentials = new SimpleCredentials("jsmith",
"secret".toCharArray());
-sessionFactory.registerCredentials("Repository/Workspace1", credentials);
-JcrExecutionContext context = new
JcrExecutionContext(sessionFactory,"Repository/Workspace1");
-
-// Create the sequencing service, passing in the execution context ...
-SequencingService sequencingService = new SequencingService();
-sequencingService.setExecutionContext(context);
- ]]></programlisting>
- <para>After the sequencing service is created and configured, it must be started.
The SequencingService
- has an <emphasis>administration object</emphasis> (that is an instance
of <code>ServiceAdministrator</code>)
- with <code>start()</code>, <code>pause()</code>, and
<code>shutdown()</code> methods. The latter method will
- close the queue for sequencing, but will allow sequencing operations already
running to complete normally.
- To wait until all sequencing operations have completed, simply call the
<code>awaitTermination</code> method
- and pass it the maximum amount of time you want to wait.</para>
- <programlisting
role="JAVA"><![CDATA[sequencingService.getAdministrator().start();
-]]></programlisting>
- <para>The sequencing service must also be configured with the sequencers that it
will use. This is done using the
- <code>addSequencer(SequencerConfig)</code> method and passing a
<code>SequencerConfig</code> instance that
- you create. Here's the code that defines 3 sequencer configurations: 1 that
places image metadata into
- "<code><![CDATA[/images/<filename>]]></code>",
another that places MP3 metadata into
"<code><![CDATA[/mp3s/<filename>]]></code>",
- and a third that places a structure that represents the classes, methods, and
attributes found within Java source into
-
"<code><![CDATA[/java/<filename>]]></code>".</para>
- <programlisting role="JAVA"><![CDATA[
-String name = "Image Sequencer";
-String desc = "Sequences image files to extract the characteristics of the
image";
-String classname = "org.jboss.dna.sequencer.image.ImageMetadataSequencer";
-String[] classpath = null; // Use the current classpath
-String[] pathExpressions =
{"//(*.(jpg|jpeg|gif|bmp|pcx|png)[*])/jcr:content[@jcr:data] =>
/images/$1"};
-SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname,
- classpath, pathExpressions);
-sequencingService.addSequencer(imageSequencerConfig);
-
-name = "MP3 Sequencer";
-desc = "Sequences MP3 files to extract the ID3 tags from the audio file";
-classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
-pathExpressions = {"//(*.mp3[*])/jcr:content[@jcr:data] => /mp3s/$1"};
-SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname,
- classpath, pathExpressions);
-sequencingService.addSequencer(mp3SequencerConfig);
-
-name = "Java Sequencer";
-desc = "Sequences java files to extract the characteristics of the Java
source";
-classname = "org.jboss.dna.sequencer.java.JavaMetadataSequencer";
-pathExpressions = {"//(*.java[*])/jcr:content[@jcr:data] => /java/$1"};
-SequencerConfig javaSequencerConfig = new SequencerConfig(name, desc, classname,
- classpath, pathExpressions);
-this.sequencingService.addSequencer(javaSequencerConfig);
- ]]></programlisting>
- <para>Each configuration defines several things, including the name,
description, and sequencer implementation class.
- The configuration also defines the classpath information, which can be passed to the
<code>ExecutionContext</code> to get
- a Java classloader with which the sequencer class can be loaded. (If no classpath
information is provided, as is done
- in the code above, the application class loader is used.) The configuration also
specifies the path expressions that
- identify the nodes that should be sequenced with the sequencer and where to store
the output generated by the sequencer.
- Path expressions are pretty straightforward but are quite powerful, so before we go
any further with the example,
- let's dive into path expressions in more detail.</para>
- <sect2 id="path_expressions">
- <title>Path Expressions</title>
- <para>Path expressions consist of two parts: a selection criteria (or an input
path) and an output path:</para>
- <programlisting><![CDATA[ inputPath => outputPath
]]></programlisting>
- <para>The <emphasis>inputPath</emphasis> part defines an expression
for the path of a node that is to be sequenced.
- Input paths consist of '<code>/</code>' separated segments,
where each segment represents a pattern for a single node's
- name (including the same-name-sibling indexes) and
'<code>@</code>' signifies a property name.</para>
- <para>Let's first look at some simple examples:</para>
- <table frame='all'>
- <title>Simple Input Path Examples</title>
- <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
- <colspec colname='c1' colwidth="1*"/>
- <colspec colname='c2' colwidth="1*"/>
- <thead>
- <row>
- <entry>Input Path</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row><entry>/a/b</entry><entry>Match node
"<code>b</code>" that is a child of the top level node
"<code>a</code>". Neither node
- may have any same-name-sibilings.</entry></row>
- <row><entry>/a/*</entry><entry>Match any child node of the
top level node "<code>a</code>".</entry></row>
- <row><entry>/a/*.txt</entry><entry>Match any child node of
the top level node "<code>a</code>" that also has a name ending in
"<code>.txt</code>".</entry></row>
- <row><entry>/a/*.txt</entry><entry>Match any child node of
the top level node "<code>a</code>" that also has a name ending in
"<code>.txt</code>".</entry></row>
- <row><entry>/a/b@c</entry><entry>Match the property
"<code>c</code>" of node
"<code>/a/b</code>".</entry></row>
- <row><entry>/a/b[2]</entry><entry>The second child named
"<code>b</code>" below the top level node
"<code>a</code>".</entry></row>
- <row><entry>/a/b[2,3,4]</entry><entry>The second, third or
fourth child named "<code>b</code>" below the top level node
"<code>a</code>".</entry></row>
- <row><entry>/a/b[*]</entry><entry>Any (and every) child
named "<code>b</code>" below the top level node
"<code>a</code>".</entry></row>
- <row><entry>//a/b</entry><entry>Any node named
"<code>b</code>" that exists below a node named
"<code>a</code>", regardless
- of where node "<code>a</code>" occurs. Again, neither
node may have any same-name-sibilings.</entry></row>
- </tbody>
- </tgroup>
- </table>
- <para>With these simple examples, you can probably discern the most important
rules. First, the '<code>*</code>' is a wildcard character
- that matches any character or sequence of characters in a node's name (or index
if appearing in between square brackets), and
- can be used in conjunction with other characters (e.g.,
"<code>*.txt</code>").</para>
- <para>Second, square brackets (i.e., '<code>[</code>' and
'<code>]</code>') are used to match a node's same-name-sibiling
index.
- You can put a single non-negative number or a comma-separated list of non-negative
numbers. Use '0' to match a node that has no
- same-name-sibilings, or any positive number to match the specific
same-name-sibling.</para>
- <para>Third, combining two delimiters (e.g.,
"<code>//</code>") matches any sequence of nodes, regardless of what
their names are
- or how many nodes. Often used with other patterns to identify nodes at any level
matching other patterns.
- Three or more sequential slash characters are treated as two.</para>
- <para>Many input paths can be created using just these simple rules. However,
input paths can be more complicated. Here are some
- more examples:</para>
- <table frame='all'>
- <title>More Complex Input Path Examples</title>
- <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
- <colspec colname='c1' colwidth="1*"/>
- <colspec colname='c2' colwidth="1*"/>
- <thead>
- <row>
- <entry>Input Path</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row><entry>/a/(b|c|d)</entry><entry>Match children of the
top level node "<code>a</code>" that are named
"<code>a</code>",
- "<code>b</code>" or
"<code>c</code>". None of the nodes may have same-name-sibling
indexes.</entry></row>
- <row><entry>/a/b[c/d]</entry><entry>Match node
"<code>b</code>" child of the top level node
"<code>a</code>", when node
- "<code>b</code>" has a child named
"<code>c</code>", and "<code>c</code>" has a
child named "<code>d</code>".
- Node "<code>b</code>" is the selected node, while nodes
"<code>b</code>" and "<code>b</code>" are used
as criteria but are not
- selected.</entry></row>
- <row><entry>/a(/(b|c|d|)/e)[f/g/@something]</entry><entry>Match
node "<code>/a/b/e</code>",
"<code>/a/c/e</code>", "<code>/a/d/e</code>",
- or "<code>/a/e</code>" when they also have a child
"<code>f</code>" that itself has a child
"<code>g</code>" with property
- "<code>something</code>". None of the nodes may have
same-name-sibling indexes.</entry></row>
- </tbody>
- </tgroup>
- </table>
- <para>These examples show a few more advanced rules. Parentheses (i.e.,
'<code>(</code>' and '<code>)</code>') can be
used
- to define a set of options for names, as shown in the first and third rules.
Whatever part of the selected node's path
- appears between the parentheses is captured for use within the output path. Thus,
the first input path in the previous table
- would match node "<code>/a/b</code>", and "b" would
be captured and could be used within the output path using
"<code>$1</code>",
- where the number used in the output path identifies the parentheses.</para>
- <para>Square brackets can also be used to specify criteria on a node's
properties or children. Whatever appears in between the square
- brackets does not appear in the selected node.</para>
- <para>Let's go back to the previous code fragment and look at the first
path expression:</para>
- <programlisting><![CDATA[
//(*.(jpg|jpeg|gif|bmp|pcx|png)[*])/jcr:content[@jcr:data] => /images/$1
]]></programlisting>
- <para>This matches a node named
"<code>jcr:content</code>" with property
"<code>jcr:data</code>" but no siblings with the same name,
- and that is a child of a node whose name ends with
"<code>.jpg</code>", "<code>.jpeg</code>",
"<code>.gif</code>", "<code>.bmp</code>",
"<code>.pcx</code>",
- or "<code>.png</code>" that may have any same-name-sibling
index. These nodes can appear at any level in the repository.
- Note how the input path capture the filename (the segment containing the file
extension), including any same-name-sibling index.
- This filename is then used in the output path, which is where the sequenced content
is placed.</para>
- </sect2>
- <sect2 id="path_expressions_in_example">
- <title>Path Expressions Used in the Example</title>
- <para>Now that we've covered path expressions, let's go back to the
three sequencer configuration in the example.
- Here they are again, with a description of what each path means:</para>
- <table frame='all'>
- <title>Path Expressions for the 3 Sequencers</title>
- <tgroup cols='3' align='left' colsep='1'
rowsep='1'>
- <colspec colname='c1' colwidth="1*"/>
- <colspec colname='c2' colwidth="1*"/>
- <colspec colname='c2' colwidth="1*"/>
- <thead>
- <row>
- <entry>Input Path</entry>
- <entry>Output Path</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><![CDATA[//(*.(jpg|jpeg|gif|bmp|pcx|png)[*])/jcr:content[@jcr:data]]]></entry>
- <entry><![CDATA[/images/$1]]></entry>
- <entry>Any node with a name ending in
"<code>.jpg</code>", "<code>.jpeg</code>",
"<code>.gif</code>", "<code>.bmp</code>",
- "<code>.pcx</code>", or
"<code>.png</code>", whether or not it has a same-name-sibling
index, but that has a child named
- "<code>jcr:content</code>" with
"<code>jcr:data</code>" property. The node name representing the
filename (including any
- same-name-sibling index) is captured, and used to place the output in
"<code><![CDATA[/images/<filename>]]></code>".</entry>
- </row>
- <row>
- <entry><![CDATA[//(*.mp3[*])/jcr:content[@jcr:data]]]></entry>
- <entry><![CDATA[/mp3s/$1]]></entry>
- <entry>Any node with a name ending in
"<code>.mp3</code>", whether or not it has a same-name-sibling
index, but that has a child named
- "<code>jcr:content</code>" with
"<code>jcr:data</code>" property. The node name representing the
filename (including any
- same-name-sibling index) is captured, and used to place the output in
"<code><![CDATA[/mp3s/<filename>]]></code>".</entry>
- </row>
- <row>
- <entry><![CDATA[//(*.java[*])/jcr:content[@jcr:data]]]></entry>
- <entry><![CDATA[/java/$1]]></entry>
- <entry>Any node with a name ending in
"<code>.java</code>", whether or not it has a same-name-sibling
index, but that has a child named
- "<code>jcr:content</code>" with
"<code>jcr:data</code>" property. The node name representing the
filename (including any
- same-name-sibling index) is captured, and used to place the output in
"<code><![CDATA[/java/<filename>]]></code>".</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>After these sequencer configurations are defined and added to the
<code>SequencingService</code>,
- the service is now ready to start reacting to changes in the repository and
automatically looking for nodes to sequence.
- But we first need to wire the service into the repository to receive those change
events.
- This is accomplished using the <code>ObservationService</code>
- described in the <link linkend="observation_service">next
section</link>.</para>
- </sect2>
- </sect1>
- <sect1 id="observation_service">
- <title>Configuring the Observation Service</title>
- <para>The JBoss DNA <code>ObservationService</code> is responsible
for listening to one or more JCR repositories
- and multiplexing the events to its listeners. Unlike JCR events, this framework
embeds in the events the
- name of the repository and workspace that can be passed to a
<code>SessionFactory</code> to obtain a session
- to the repository in which the change occurred. This simple design makes it very
easy for JBoss DNA to
- concurrently work with multiple JCR repositories.</para>
- <para>Configuring an observation service is pretty easy, especially if you reuse
the same <code>SessionFactory</code>
- supplied to the sequencing service. Here's an example:</para>
- <programlisting role="JAVA"><![CDATA[
- this.observationService = new ObservationService(sessionFactory);
- this.observationService.getAdministrator().start();
- ]]></programlisting>
- <note>
- <para>Both <code>ObservationService</code> and
<code>SequencingService</code> implement
- <code>AdministeredService</code>, which has a
<code>ServiceAdministrator</code> used to start, pause, and shutdown the
- service. In other words, the lifecycle of the services are managed in the same
way.</para>
- </note>
- <para>After the observation service is started, listeners can be added. The
<code>SequencingService</code> implements the required
- interface, and so it may be registered directly:</para>
- <programlisting role="JAVA"><![CDATA[
- observationService.addListener(sequencingService);
- ]]></programlisting>
- <para>Finally, the observation service must be wired to monitor one of your JCR
repositories. This is done with
- one of the <code>monitor(...)</code> methods:</para>
- <programlisting role="JAVA"><![CDATA[
- int eventTypes = Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED;
- observationService.monitor("Main Repository/Workspace1", eventTypes);
- ]]></programlisting>
- <para>At this point, the observation service is listening to a JCR repository and
forwarding the appropriate events
- to the sequencing service, which will asynchronously process the changes and
sequence the information added to or changed in the repository.
- </para>
- </sect1>
- <sect1 id="shutting_down">
- <title>Shutting down JBoss DNA services</title>
- <para>The JBoss DNA services are utilizing resources and threads that must be
released before your application is ready to shut down.
- The safe way to do this is to simply obtain the
<code>ServiceAdministrator</code> for each service (via the
<code>getServiceAdministrator()</code> method)
- and call <code>shutdown()</code>. As previously mentioned, the shutdown
method will simply prevent new work from being processed
- and will not wait for existing work to be completed. If you want to wait until the
service completes all its work, you must wait
- until the service terminates. Here's an example that shows how this is
done:</para>
- <programlisting role="JAVA"><![CDATA[
-// Shut down the service and wait until it's all shut down ...
-sequencingService.getAdministrator().shutdown();
-sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-
-// Shut down the observation service ...
-observationService.getAdministrator().shutdown();
-observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
- ]]></programlisting>
- <para>At this point, we've covered how to configure and use the JBoss DNA
services in your application.
- The next chapter goes back to the <link
linkend="downloading_and_running">sample application</link> to show how
all
- these pieces fit together.</para>
- </sect1>
- <sect1 id="example_application_review">
- <title>Reviewing the example application</title>
- <para>Recall that the example application consists of a client application that
sets up an in-memory JCR repository and
- that allows a user to upload files into that repository. The client also sets up
the DNA services with an image sequencer so
- that if any of the uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will
automatically extract the image's
- metadata (e.g., image format, physical size, pixel density, etc.) and store that in
the repository. Or, if the client uploads
- MP3 audio files, the title, author, album, year, and comment are extracted from the
audio file and stored in the repository.</para>
- <para>
- The example is comprised of 5 classes and 1 interface, located in the
<code>src/main/java</code> directory:</para>
- <programlisting><![CDATA[
- org/jboss/example/dna/sequencers/ConsoleInput.java
- /ContentInfo.java
- /JavaInfo.java
- /MediaInfo.java
- /SequencingClient.java
- /UserInterface.java
- ]]></programlisting>
- <para><code>SequencingClient</code> is the class that contains the
main application. <code>ContentInfo</code> is a simple class
- that encapsulate metadata generated by the sequencers and accessed by this example
application, and there are two subclasses:
- <code>MediaInfo</code> encapsulates metadata about media (image and MP3)
files, while <code>JavaInfo</code> is a subclass
- encapsulating information about a Java class. The client accesses the content from
the repository and represent the
- information using instances of <code>ContentInfo</code> (and its
subclasses) and then passing them to the <code>UserInterface</code>.
- <code>UserInterface</code> is an interface with methods that will be
called at runtime to
- request data from the user. <code>ConsoleInput</code> is an
implementation of this that creates a text user interface,
- allowing the user to operate the client from the command-line. We can easily create a
graphical implementation of
- <code>UserInterface</code> at a later date. We can also create a mock
implementation for testing purposes that simulates
- a user entering data. This allows us to check the behavior of the client automatically
using conventional JUnit test cases,
- as demonstrated by the code in the <code>src/test/java</code>
directory:</para>
- <programlisting><![CDATA[
- org/jboss/example/dna/sequencers/SequencingClientTest.java
- /MockUserInterface.java
- ]]></programlisting>
- <para>If we look at the <code>SequencingClient</code> code, there are
a handful of methods that encapsulate the various activities.</para>
- <note>
- <para>Some of the code samples included in this book have had some of the error
handling and comments removed so that
- the samples are more readable and concise.</para>
- </note>
- <para>The <code>startRepository()</code> method starts up an
in-memory Jackrabbit JCR repository. The bulk of this method is simply
- gathering and passing the information required by Jackrabbit. Because Jackrabbit's
<code>TransientRepository</code>
- implementation shuts down after the last session is closed, the application
maintains a session to ensure that the
- repository remains open throughout the application's lifetime. And finally, the
node type needed by the image sequencer is
- registered with Jackrabbit.</para>
- <programlisting role="JAVA"><![CDATA[
-public void startRepository() throws Exception {
- if (this.repository == null) {
- try {
-
- // Load the Jackrabbit configuration ...
- File configFile = new File(this.jackrabbitConfigPath);
- String pathToConfig = configFile.getAbsolutePath();
-
- // Find the directory where the Jackrabbit repository data will be stored
...
- File workingDirectory = new File(this.workingDirectory);
- String workingDirectoryPath = workingDirectory.getAbsolutePath();
-
- // Get the Jackrabbit custom node definition (CND) file ...
- URL cndFile =
Thread.currentThread().getContextClassLoader().getResource("jackrabbitNodeTypes.cnd");
-
- // Create the Jackrabbit repository instance and establish a session to keep
the repository alive ...
- this.repository = new TransientRepository(pathToConfig,
workingDirectoryPath);
- if (this.username != null) {
- Credentials credentials = new SimpleCredentials(this.username,
this.password);
- this.keepAliveSession = this.repository.login(credentials,
this.workspaceName);
- } else {
- this.keepAliveSession = this.repository.login();
- }
-
- try {
- // Register the node types (only valid the first time) ...
- Workspace workspace = this.keepAliveSession.getWorkspace();
- JackrabbitNodeTypeManager mgr =
(JackrabbitNodeTypeManager)workspace.getNodeTypeManager();
- mgr.registerNodeTypes(cndFile.openStream(),
JackrabbitNodeTypeManager.TEXT_X_JCR_CND);
- } catch (RepositoryException e) {
- if (!e.getMessage().contains("already exists")) throw e;
- }
-
- } catch (Exception e) {
- this.repository = null;
- this.keepAliveSession = null;
- throw e;
- }
- }
-}
- ]]></programlisting>
- <para>As you can see, this method really has nothing to do with JBoss DNA, other
than setting up a JCR repository that JBoss
- DNA will use.</para>
- <para>The <code>shutdownRepository()</code> method shuts down the
Jackrabbit transient repository by closing the "keep-alive session".
- Again, this method really does nothing specifically with JBoss DNA, but is needed to
manage the JCR repository that JBoss DNA uses.</para>
- <programlisting role="JAVA"><![CDATA[
-public void shutdownRepository() throws Exception {
- if (this.repository != null) {
- try {
- this.keepAliveSession.logout();
- } finally {
- this.repository = null;
- this.keepAliveSession = null;
- }
- }
-}
- ]]></programlisting>
- <para>The <code>startDnaServices()</code> method first starts the JCR
repository (if it was not already started), and proceeds
- to create and configure the <code>SequencingService</code> as described
<link linkend="sequencing_service">earlier</link>.
- This involes setting up the <code>SessionFactory</code> and
<code>ExecutionContext</code>, creating the
- <code>SequencingService</code> instance, and configuring the image
sequencer. The method then continues by setting up the
- <code>ObservationService</code> as described <link
linkend="observation_service">earlier</link> and starting the
service.</para>
- <programlisting role="JAVA"><![CDATA[
-public void startDnaServices() throws Exception {
- if (this.repository == null) this.startRepository();
- if (this.sequencingService == null) {
-
- SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
- sessionFactory.registerRepository(this.repositoryName, this.repository);
- if (this.username != null) {
- Credentials credentials = new SimpleCredentials(this.username,
this.password);
- sessionFactory.registerCredentials(this.repositoryName + "/" +
this.workspaceName, credentials);
- }
- this.executionContext = new JcrExecutionContext(sessionFactory,
repositoryWorkspaceName);
-
- // Create the sequencing service, passing in the execution context ...
- this.sequencingService = new SequencingService();
- this.sequencingService.setExecutionContext(executionContext);
-
- // Configure the sequencers.
- String name = "Image Sequencer";
- String desc = "Sequences image files to extract the characteristics of the
image";
- String classname =
"org.jboss.dna.sequencer.images.ImageMetadataSequencer";
- String[] classpath = null; // Use the current classpath
- String[] pathExpressions =
{"//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data]
=> /images/$1"};
- SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname,
classpath, pathExpressions);
- this.sequencingService.addSequencer(imageSequencerConfig);
-
- // Set up the MP3 sequencer ...
- name = "Mp3 Sequencer";
- desc = "Sequences mp3 files to extract the id3 tags of the audio
file";
- classname = "org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer";
- pathExpressions = {"//(*.mp3)[*]/jcr:content[@jcr:data] =>
/mp3s/$1"};
- SequencerConfig mp3SequencerConfig = new SequencerConfig(name, desc, classname,
classpath, pathExpressions);
- this.sequencingService.addSequencer(mp3SequencerConfig);
-
- name = "Java Sequencer";
- desc = "Sequences java files to extract the characteristics of the Java
source";
- classname = "org.jboss.dna.sequencer.java.JavaMetadataSequencer";
- pathExpressions = {"//(*.java[*])/jcr:content[@jcr:data] => /java/$1"};
- SequencerConfig javaSequencerConfig = new SequencerConfig(name, desc,
classname,classpath, pathExpressions);
- this.sequencingService.addSequencer(javaSequencerConfig);
-
- // Use the DNA observation service to listen to the JCR repository (or multiple
ones), and
- // then register the sequencing service as a listener to this observation
service...
- this.observationService = new
ObservationService(this.executionContext.getSessionFactory());
- this.observationService.getAdministrator().start();
- this.observationService.addListener(this.sequencingService);
- this.observationService.monitor(this.repositoryName + "/" +
this.workspaceName, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED);
- }
- // Start up the sequencing service ...
- this.sequencingService.getAdministrator().start();
-}
- ]]></programlisting>
- <para>The <code>shutdownDnaServices()</code> method is pretty
straightforward: it just calls shutdown on each of the services
- and waits until they terminate.</para>
- <programlisting role="JAVA"><![CDATA[
-public void shutdownDnaServices() throws Exception {
- if (this.sequencingService == null) return;
-
- // Shut down the service and wait until it's all shut down ...
- this.sequencingService.getAdministrator().shutdown();
- this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-
- // Shut down the observation service ...
- this.observationService.getAdministrator().shutdown();
- this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-}
- ]]></programlisting>
- <para>None of the other methods really do anything with JBoss DNA
<emphasis>per se</emphasis>. Instead, they merely work with the repository
- using the JCR API.</para>
- <para>The <code>main</code> method of the
<code>SequencingClient</code> class creates a
<code>SequencingClient</code> instance,
- and passes a new <code>ConsoleInput</code> instance:</para>
- <programlisting role="JAVA"><![CDATA[
-public static void main( String[] args ) throws Exception {
- SequencingClient client = new SequencingClient();
- client.setRepositoryInformation("repo", "default",
"jsmith", "secret".toCharArray());
- client.setUserInterface(new ConsoleInput(client));
-}
- ]]></programlisting>
- <para>If we look at the <code>ConsoleInput</code> constructor, it
starts the repository, the DNA services, and a thread
- for the user interface. At this point, the constructor returns, but the main
application continues under the user interface thread.
- When the user requests to quit, the user interface thread also shuts down the DNA
services and JCR repository.</para>
- <programlisting role="JAVA"><![CDATA[
-public ConsoleInput( SequencerClient client ) {
- try {
- client.startRepository();
- client.startDnaServices();
-
- System.out.println(getMenu());
- Thread eventThread = new Thread(new Runnable() {
- private boolean quit = false;
- public void run() {
- try {
- while (!quit) {
- // Display the prompt and process the requested operation ...
- }
- } finally {
- try {
- // Terminate ...
- client.shutdownDnaServices();
- client.shutdownRepository();
- } catch (Exception err) {
- System.out.println("Error shutting down sequencing service and
repository: "
- + err.getLocalizedMessage());
- err.printStackTrace(System.err);
- }
- }
- }
- });
- eventThread.start();
- } catch (Exception err) {
- System.out.println("Error: " + err.getLocalizedMessage());
- err.printStackTrace(System.err);
- }
-}
- ]]></programlisting>
- <para>At this point, we've reviewed all of the interesting code in the
example application. However, feel free
- to play with the application, trying different things.</para>
- </sect1>
- <sect1 id="using_dna_review">
- <title>Summarizing what we just did</title>
- <para>In this chapter we covered the different JBoss DNA components used for
automatically sequencing a variety of
- types of information, and how those components can be used in your application.
- Specifically, we described how the <code>SequencingService</code> and
<code>ObservationService</code> can
- be configured and used. And we ended the chapter by reviewing the example
application, which not only uses
- JBoss DNA, but also the repository via the JCR API.</para>
- </sect1>
-</chapter>
Deleted:
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_repositories.xml
===================================================================
---
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_repositories.xml 2009-06-07
15:05:15 UTC (rev 988)
+++
trunk/docs/gettingstarted/src/main/docbook/en-US/content/using_dna_repositories.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -1,273 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ JBoss DNA (
http://www.jboss.org/dna)
- ~
- ~ See the COPYRIGHT.txt file distributed with this work for information
- ~ regarding copyright ownership. Some portions may be licensed
- ~ to Red Hat, Inc. under one or more contributor license agreements.
- ~ See the AUTHORS.txt file in the distribution for a full listing of
- ~ individual contributors.
- ~
- ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- ~ is licensed to you under the terms of the GNU Lesser General Public License as
- ~ published by the Free Software Foundation; either version 2.1 of
- ~ the License, or (at your option) any later version.
- ~
- ~ JBoss DNA is distributed in the hope that it will be useful,
- ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- ~ for more details.
- ~
- ~ You should have received a copy of the GNU Lesser General Public License
- ~ along with this distribution; if not, write to:
- ~ Free Software Foundation, Inc.
- ~ 51 Franklin Street, Fifth Floor
- ~ Boston, MA 02110-1301 USA
- -->
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="using_dna_repositories">
- <title>Using JBoss DNA Repositories</title>
- <para>One of the capabilities of JBoss DNA is to provide access through
- <ulink
url="http://www.jcp.org/en/jsr/detail?id=170">JCR</ulink>
to different kinds of repositories and storage systems.
- Your applications work with the JCR API, but through JBoss DNA you're able to
accesses the content from where the information
- exists - not just a single purpose-built repository. This is fundamentally what makes
JBoss DNA different.</para>
- <para>How does JBoss DNA do this? At the heart of JBoss DNA and it's JCR
implementation is a simple connector
- system that is designed around creating and accessing graphs. The JBoss DNA JCR
implementation actually just sits on
- top of a single repository source, which it uses to access of the repositories
content.
- <figure id="dnajcr-and-connector">
- <title>JBoss DNA's JCR implementation delegates to a repository
source</title>
- <graphic align="center" scale="100"
fileref="dnajcr-and-connector.png"/>
- </figure>
- That single repository source could be an in-memory repository, a JBoss Cache instance,
or a federated repository.
- <figure id="dna-connectors-0.2">
- <title>JBoss DNA can put JCR on top of multiple kinds of systems</title>
- <graphic align="center" scale="100"
fileref="dna-connectors-0.2.png"/>
- </figure>
- And the JBoss DNA project has plans to create other connectors, too. For instance,
we're going to build a connector
- to other JCR repositories. And another to a file system, so that the files and
directories on an area of the file system
- can be accessed through JCR. Of course, if we don't have a connector to suit
your needs, you can write your own.
- <figure id="dna-connectors-future">
- <title>Future JBoss DNA connectors</title>
- <graphic align="center" scale="100"
fileref="dna-connectors-future.png"/>
- </figure>
- </para>
- <note>
- <para>You might be thinking that these connectors are interesting, but what do
they really provide? Is it really useful
- to use JCR to access a relational database rather than JDBC? Or, why access the
files on a file system when there
- are already mechanisms to do that?</para>
- <para>Maybe putting JCR on top of a single system (like a JDBC database)
isn't that interesting. What
- <emphasis>is</emphasis> interesting, though, is accessing the information
in multiple systems <emphasis>as if all that information were
- in a single JCR repository</emphasis>. That's what the federated
repository source is all about. The JBoss DNA connector
- system just makes it possible to interact with all these systems in the same
way.</para>
- <para>Think of it this way: with JBoss DNA, you can use JCR to get to the schemas
of multiple relational databases <emphasis>and</emphasis> the schemas
- defined by DDL files in your SVN repository <emphasis>and</emphasis> the
schemas defined by logical models stored on your file system.
- </para>
- </note>
- <para>So with this very high-level summary, let's dive a little deeper and
look at how to configure and use JBoss DNA and JCR.</para>
- <sect1 id="repository_service">
- <title>Configuring the Repository Service</title>
- <para>The JBoss DNA <emphasis>repository service</emphasis> is the
component that manages the <emphasis>repositories</emphasis>
- and connections to them. The service reads its configuration from a
<code>RepositorySource</code> instance (i.e., the
- "configuration repository") and automatically sets up the repositories
given the <code>RepositorySource</code> instances
- found in the configuration repository.</para>
- <note>
- <para>Configuring JBoss DNA services is more manual and complex than we want. As
you'll see, JBoss DNA uses dependency
- injection to allow a great deal of flexibility in how it can be configured and
customized. But this flexibility
- makes it more difficult for you to use. We understand this, and will soon provide
a much easier way to set up
- and manage JBoss DNA. Current plans are to use the <ulink
url="http://www.jboss.org/jbossmc">JBoss Microcontainer</ulink>
- along with a configuration repository that makes it very easy to set up and manage
JBoss DNA, whether it's used in
- a simple application or a cluster of processes.</para>
- </note>
- <para>To set up the repository service, we need to first set up a few other
objects:
- <itemizedlist>
- <listitem>
- <para>An <emphasis>execution contexts</emphasis>. Execution
contexts define the context (or environment)
- in which the service runs and in which operations against repositories are
performed. <code>ExecutionContext</code>
- instances can be created using JAAS application contexts, meaning that they
contain the information about the subject
- that the software represents. Execution contexts also provide access to the all
of the factories and utilities
- used throughout the services and components, and it is through this mechanism
that you can inject your own behavior.
- For example, if your application already had a notion of namespaces, you could
create an execution context that
- uses your own <code>NamespaceRegistry</code> implementation (which
would use the namespaces defined in your application).</para>
- </listitem>
- <listitem>
- <para>A <emphasis>repository library</emphasis> that manages the
list of <code>RepositorySource</code> instances.
- The library makes sure to inject the environments into each repository source,
and it provides for each source
- a configurable pool of connections.</para>
- </listitem>
- <listitem>
- <para>A <emphasis>configuration repository</emphasis> that
contains descriptions of all of the repository sources
- as well as any information those sources need. Because this is a regular
repository, this could be a simple
- repository with content loaded from an XML file (as in this example). Or it
could be a shared
- central repository with information about all of the JBoss DNA processes across
your company.</para>
- </listitem>
- </itemizedlist>
- With these components in place, we can then instantiate the
<code>RepositoryService</code> and start it (using its
- <code>ServiceAdministrator</code>). During startup, the service reads the
configuration repository and loads any
- defined <code>RepositorySource</code> instances into the repository
library, using the class loader factory
- (available in the <code>ExecutionContext</code>) to obtain.
- </para>
- <para>Here's sample code that shows how to set up and start the repository
service. You can see something similar
- in the example application in the <code>startRepositories()</code> method
of the <code>org.jboss.example.dna.repository.RepositoryClient</code>
class.</para>
- <programlisting role="JAVA"><![CDATA[
- // Create the execution context that we'll use for the services. If we'd want
to use JAAS, we'd
- // create the context by supplying LoginContext, AccessControlContext, or even Subject
with
- // CallbackHandlers. But this example doesn't use JAAS in this example.
- ExecutionContext context = new ExecutionContext();
-
- // Create the library for the RepositorySource instances ...
- RepositoryLibrary sources = new RepositoryLibrary(context);
-
- // Load into the source manager the repository source for the configuration repository
...
- InMemoryRepositorySource configSource = new InMemoryRepositorySource();
- configSource.setName("Configuration");
- sources.addSource(configSource);
-
- // Now instantiate the Repository Service ...
- RepositoryService service = new RepositoryService(sources, configSource.getName(),
context);
- service.getAdministrator().start();
- ]]></programlisting>
- <para>After startup completes, the repositories are ready to be used. The client
application obtains the list of repositories
- and presents them to the user. When the user selects one, the client application
starts navigating that repository
- starting at its root node (e.g., the "/" path). As you type a command to
list the contents of the current node or to
- "change directories" to a different node, the client application obtains the
information for the node using a simple
- procedure:
- <orderedlist>
- <listitem>
- <para>Get a connection to the repository.</para>
- </listitem>
- <listitem>
- <para>Using the connection, find the current node and read its properties and
children, putting the information
- into a simple Java plain old Java object (POJO).</para>
- </listitem>
- <listitem>
- <para>Close the connection to the repository (in a finally block to ensure it
always happens).</para>
- </listitem>
- </orderedlist>
- </para>
- <sect2 id="using_jcr_with_dna">
- <title>Using JCR to read repository</title>
- <para>If we want to perform these steps using JCR, a JCR
<code>Session</code> represents our connection.
- So after we create a <code>JcrRepository</code> instance pointing to our
repository library, we can
- then login to obtain a JCR session:</para>
- <programlisting role="JAVA"><![CDATA[
- JcrRepository jcrRepository = new JcrRepository(context, sources);
- Session session = jcrRepository.login(sourceName);
- ]]></programlisting>
- <para>Now, the above code doesn't do any authentication; it essentially
trusts the caller has the appropriate privileges.
- Normally, your application will need to authenticate the user, so let's look at
how that's done.</para>
- <para>JBoss DNA uses the <ulink
url="http://java.sun.com/j2se/1.5.0/docs/guide/security/jaas/tutoria...
- Authentication and Authorization Service (JAAS)</ulink>, making it possible to
use any existing JAAS security provider.
- There are numerous JAAS providers, but one of the best open-source implementations is
- <ulink
url="http://www.jboss.org/jbosssecurity/">JBoss
Security</ulink>, which can authenticate using LDAP, certificates,
- the operating system, and federated single-sign-on (among others).
- </para>
- <para>
- The JCR API defines a <code>Credentials</code> marker interface, an
instance of which can be passed to the
- <code>Session.login(...)</code> method. Rather than provide a concrete
implementation of this interface, JBoss DNA
- allows you to pass any implementation of <code>Credentials</code> that
also has one of the following methods:
- <itemizedlist>
- <listitem>
- <para><code>getLoginContext()</code> that returns a
<code>javax.security.auth.login.LoginContext</code> instance.</para>
- </listitem>
- <listitem>
- <para><code>getAccessControlContext()</code> that returns a
<code>java.security.AccessControlContext</code> instance.</para>
- </listitem>
- </itemizedlist>
- This way, your application can obtain the JAAS <code>LoginContext</code>
or <code>AccessControlContext</code> however it wants,
- and then merely passes that into DNA through the JCR
<code>Credentials</code>. No interfaces or classes specific to JBoss DNA are
required.
- </para>
- <para>The following code shows how this is done, using an anonymous inner class
for the <code>Credentials</code> implementation.</para>
- <programlisting role="JAVA"><![CDATA[
- CallbackHandler callbackHandler = // as needed by your app, according to JAAS
- final LoginContext loginContext = new
LoginContext("MyAppContextName",callbackHandler);
- Credentials credentials = new Credentials() {
- public LoginContext getLoginContext() { return loginContext; }
- };
- JcrRepository jcrRepository = new JcrRepository(context, sources);
- Session session = jcrRepository.login(credentials, sourceName);
- ]]></programlisting>
- <para>Once you have a JCR session, you can then use it to find the node of
interest and access the necessary information. All of this
- code will use only the JCR API - there's nothing specific to JBoss DNA's
implementation. And remember, when you're finished with
- the session, be sure to logout (usually in a <code>finally</code>
block):</para>
- <programlisting role="JAVA"><![CDATA[
- if (session != null) session.logout();
- ]]></programlisting>
- <para>Like many people recommend with JCR, you can create either long-lived or
short-lived JCR <code>Session</code>s. The
- JBoss DNA implementation of JCR was designed to efficiently do either.</para>
- </sect2>
- <!--
- <sect2 id="using_dna_repositories_with_dna_api">
- <title>Using JBoss DNA's API to read repository</title>
- <para>Although we recommend using JCR, JBoss DNA has an internal command-based
API that completely side-steps JCR and provides
- very simple graph-based operations. For more information, see the
<code>RepositoryClient</code> class in the example.</para>
- <note>
- <para>This API is likely to undergo changes in the next few releases, and using
it at this time is not suggested.</para>
- </note>
- </sect2>
- -->
- </sect1>
- <sect1 id="shutting_down_repository_service">
- <title>Shutting down the Repository Service</title>
- <para>In the first part of this chapter, we saw how to instantiate, configure,
and start the <code>RepositoryService</code>.
- We then saw how to use JCR to access the repository service by creating JCR
<code>Session</code>s, and how to log out of those
- sessions when no longer needed.</para>
- <para>In this short section we'll see how to shut down the
<code>RepositoryService</code> and <code>RepositoryLibrary</code>
- when you're finished with all of the repositories. It's a simple but
important step, since this closes all outstanding
- connections that may be sitting unused in the library's connection
pools.</para>
- <para>Shutting down these components is very straightforward: get the
<code>ServiceAdministrator</code> on each, and call
<code>shutdown()</code>.</para>
- <programlisting role="JAVA"><![CDATA[
- // Shut down the repository service ...
- repositoryService.getAdministrator().shutdown();
-
- // Shut down the manager of the RepositorySource instances, waiting until all
connections are closed
- sources.getAdministrator().shutdown();
- sources.getAdministrator().awaitTermination(1, TimeUnit.SECONDS);
- ]]></programlisting>
- <para>The <code>shutdown()</code> method attempts to close all open
and unused resources (such as open and unused connections in the pool).
- No more connections can be created, and any connections that are currently in use are
not closed but allowed to be used and closed normally.
- When the last connection is used, the service then transitions to a
<emphasis>terminated</emphasis> state, which you can wait for using
- the <code>awaitTermination(int,TimeUnit)</code> method.</para>
- <para>If you want to shutdown the services immediately, then you could call
<code>shutdownNow()</code>, which blocks while it attempts to immediately
- close all connections - <emphasis>even those currently in use</emphasis>.
So, while you generally want to use <code>shutdown()</code>,
- it is good to be aware that this <code>shutdownNow()</code> method does
exist.</para>
- </sect1>
- <sect1 id="example_repository_application_review">
- <title>Reviewing the example repository application</title>
- <para>Recall that the example repository application consists of a client
application that sets up a repository service and the
- repositories defined in a configuration repository, allowing the user to pick a
repository and interactively navigate
- the selected repository. Several repositories are set up, including several in-memory
repositories and one federated repository
- that dynamically federates the content from the other repositories.</para>
- <para>
- The example is comprised of 2 classes and 1 interface, located in the
<code>src/main/java</code> directory:</para>
- <programlisting><![CDATA[
- org/jboss/example/dna/repositories/ConsoleInput.java
- /RepositoryClient.java
- /UserInterface.java
- ]]></programlisting>
- <para><code>RepositoryClient</code> is the class that contains the
main application. It uses an instance of the
- <code>UserInterface</code> interface to methods that will be called at
runtime to obtain information about the
- files that are imported into the in-memory repositories and the JAAS
<code>CallbackHandler</code> implementation
- that will be used by JAAS to prompt the user for authentication information.
Finally, the <code>ConsoleInput</code>
- is an implementation of this that creates a text user interface, allowing the user to
operate the client from the command-line.
- We can easily create a graphical implementation of
<code>UserInterface</code> at a later date, or we can also create a mock
- implementation for testing purposes that simulates a user entering data. This allows
us to check the behavior of the client
- automatically using conventional JUnit test cases, as demonstrated by the code in the
<code>src/test/java</code> directory:</para>
- <programlisting><![CDATA[
- org/jboss/example/dna/sequencers/RepositoryClientTest.java
- /RepositoryClientUsingJcrTest.java
- ]]></programlisting>
- <para>
- The code we presented earlier in this chapter represent the bulk of the JBoss DNA and
JCR-specific code used in the
- <code>RepositoryClient</code>, so we won't cover it in any more detail
here. Please refer to the sample client code
- if you want to see more.
- </para>
- </sect1>
- <sect1 id="using_dna_repositories_review">
- <title>Summarizing what we just did</title>
- <para>In this chapter we covered the different JBoss DNA components used for
accessing repositories through JCR, including
- repositories that federate their content from the content of other repositories.
Specifically, we described how the
- <code>RepositoryService</code> and <code>JcrRepository</code>
can be configured and used.
- </para>
- </sect1>
-</chapter>
-
Added: trunk/docs/gettingstarted/src/main/docbook/en-US/custom.dtd
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/custom.dtd
(rev 0)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/custom.dtd 2009-06-07 22:33:45 UTC
(rev 989)
@@ -0,0 +1,138 @@
+<!ENTITY versionNumber "0.5">
+<!ENTITY copyrightYears "2008-2009">
+<!ENTITY copyrightHolder "Red Hat, Inc.">
+
+<!-- Frequently used URLs -->
+
+<!ENTITY Home "http://www.jboss.org/dna/">
+<!ENTITY Downloads "&Home;downloads.html">
+<!ENTITY Community "&Home;community.html">
+<!ENTITY DocHome
"http://www.jboss.org/file-access/default/members/dna/freezone/">
+<!ENTITY API
"&DocHome;docs/&versionNumber;/apidocs/org/jboss/dna/">
+<!ENTITY JIRA "http://jira.jboss.org/jira/browse/DNA">
+<!ENTITY Roadmap
"&JIRA;?report=com.atlassian.jira.plugin.system.project:roadmap-panel">
+<!ENTITY Subversion "http://anonsvn.jboss.org/repos/dna/">
+<!ENTITY Fisheye "http://fisheye.jboss.org/browse/DNA/">
+<!ENTITY SecureSubversion "https://svn.jboss.org/repos/dna/">
+<!ENTITY Forums
"http://www.jboss.com/index.html?module=bb&op=viewforum&f=272">
+<!ENTITY JSR170 "http://www.jcp.org/en/jsr/detail?id=170">
+<!ENTITY JSR283 "http://www.jcp.org/en/jsr/detail?id=283">
+<!ENTITY JSR203 "http://www.jcp.org/en/jsr/detail?id=203">
+<!ENTITY MailTo "mailto:dna-users@jboss.org">
+<!ENTITY Wikipedia "http://en.wikipedia.org/wiki/">
+<!ENTITY JBossMaven "http://repository.jboss.com/maven2/">
+
+<!ENTITY Java "http://java.sun.com/j2se/1.5.0/docs/api/">
+
+<!ENTITY GettingStarted "<ulink
url='&DocHome;docs/&versionNumber;/manuals/gettingstarted/html/index.html'>Getting
Started</ulink>">
+<!ENTITY ReferenceGuide "<ulink
url='&DocHome;docs/&versionNumber;/manuals/reference/html/index.html'>Getting
Started</ulink>">
+
+<!-- Types in JRE -->
+
+<!ENTITY String "<ulink
url='&Java;java/lang/String.html'><interface>String</interface></ulink>">
+<!ENTITY File "<ulink
url='&Java;java/io/File.html'><classname>File</classname></ulink>">
+<!ENTITY URL "<ulink
url='&Java;java/net/URL.html'><classname>URL</classname></ulink>">
+<!ENTITY URI "<ulink
url='&Java;java/net/URL.html'><classname>URI</classname></ulink>">
+<!ENTITY InputStream "<ulink
url='&Java;java/io/InputStream.html'><interface>InputStream</interface></ulink>">
+<!ENTITY IOException "<ulink
url='&Java;java/io/IOException.html'><classname>IOException</classname></ulink>">
+<!ENTITY ClassLoader "<ulink
url='&Java;java/lang/ClassLoader.html'><interface>ClassLoader</interface></ulink>">
+<!ENTITY AccessControlContext "<ulink
url='&Java;java/security/AccessController.html'><classname>AccessControlContext</classname></ulink>">
+<!ENTITY LoginContext "<ulink
url='&Java;javax/security/auth/login/LoginContext.html'><classname>LoginContext</classname></ulink>">
+<!ENTITY Subject "<ulink
url='&Java;javax/security/auth/Subject.html'><classname>Subject</classname></ulink>">
+<!ENTITY CallbackHandler "<ulink
url='&Java;javax/security/auth/callback/CallbackHandler.html'><interface>CallbackHandler</interface></ulink>">
+<!ENTITY ExecutorService "<ulink
url='&Java;java/util/concurrent/ExecutorService.html'><interface>ExecutorService</interface></ulink>">
+<!ENTITY TimeUnit "<ulink
url='&Java;java/util/concurrent/TimeUnit.html'><interface>TimeUnit</interface></ulink>">
+<!ENTITY UUID "<ulink
url='&Java;java/util/UUID.html'><classname>UUID</classname></ulink>">
+<!ENTITY DataSource "<ulink
url='&Java;javax/sql/DataSource.html'><classname>DataSource</classname></ulink>">
+
+
+<!-- Types in JCR API -->
+
+<!ENTITY Repository
"<interface>Repository</interface>">
+<!ENTITY Session
"<interface>Session</interface>">
+<!ENTITY Credentials
"<interface>Credentials</interface>">
+<!ENTITY SimpleCredentials
"<interface>SimpleCredentials</interface>">
+
+<!-- Types in dna-common -->
+
+<!ENTITY Logger "<ulink
url='&API;common/util/Logger.html'><interface>Logger</interface></ulink>">
+<!ENTITY ClassLoaderFactory "<ulink
url='&API;common/component/ClassLoaderFactory.html'><interface>ClassLoaderFactory</interface></ulink>">
+<!ENTITY StandardClassLoaderFactory "<ulink
url='&API;common/component/StandardClassLoaderFactory.html'><classname>StandardClassLoaderFactory</classname></ulink>">
+
+<!-- Types in dna-graph -->
+
+<!ENTITY Graph "<ulink
url='&API;graph/Graph.html'><classname>Graph</classname></ulink>">
+<!ENTITY GraphBatch "<ulink
url='&API;graph/Graph.Batch.html'><classname>Graph.Batch</classname></ulink>">
+<!ENTITY Subgraph "<ulink
url='&API;graph/Subgraph.html'><interface>Subgraph</interface></ulink>">
+<!ENTITY Node "<ulink
url='&API;graph/Node.html'><interface>Node</interface></ulink>">
+<!ENTITY Workspace "<ulink
url='&API;graph/Workspace.html'><interface>Workspace</interface></ulink>">
+<!ENTITY Results "<ulink
url='&API;graph/Results.html'><interface>Results</interface></ulink>">
+<!ENTITY Location "<ulink
url='&API;graph/Location.html'><classname>Location</classname></ulink>">
+<!ENTITY ExecutionContext "<ulink
url='&API;graph/ExecutionContext.html'><classname>ExecutionContext</classname></ulink>">
+<!ENTITY Name "<ulink
url='&API;graph/property/Name.html'><interface>Name</interface></ulink>">
+<!ENTITY Path "<ulink
url='&API;graph/property/Path.html'><interface>Path</interface></ulink>">
+<!ENTITY PathSegment "<ulink
url='&API;graph/property/Path.Segment.html'><interface>Path.Segment</interface></ulink>">
+<!ENTITY Property "<ulink
url='&API;graph/property/Property.html'><interface>Property</interface></ulink>">
+<!ENTITY ValueFactories "<ulink
url='&API;graph/property/ValueFactories.html'><interface>ValueFactories</interface></ulink>">
+<!ENTITY NamespaceRegistry "<ulink
url='&API;graph/property/NamespaceRegistry.html'><interface>NamespaceRegistry</interface></ulink>">
+<!ENTITY PropertyFactory "<ulink
url='&API;graph/property/PropertyFactory.html'><interface>PropertyFactory</interface></ulink>">
+<!ENTITY PathNotFoundException "<ulink
url='&API;graph/property/PathNotFoundException.html'><classname>PathNotFoundException</classname></ulink>">
+<!ENTITY RepositorySource "<ulink
url='&API;graph/connector/RepositorySource.html'><interface>RepositorySource</interface></ulink>">
+<!ENTITY RepositoryConnection "<ulink
url='&API;graph/connector/RepositoryConnection.html'><interface>RepositoryConnection</interface></ulink>">
+<!ENTITY RepositoryConnectionFactory "<ulink
url='&API;graph/connector/RepositoryConnectionFactory.html'><interface>RepositoryConnectionFactory</interface></ulink>">
+<!ENTITY RepositorySourceListener "<ulink
url='&API;graph/connector/RepositorySourceListener.html'><interface>RepositorySourceListener</interface></ulink>">
+<!ENTITY RepositorySourceCapabilities "<ulink
url='&API;graph/connector/RepositorySourceCapabilities.html'><classname>RepositorySourceCapabilities</classname></ulink>">
+<!ENTITY InMemoryRepository "<ulink
url='&API;graph/connector/inmemory/InMemoryRepository.html'><classname>InMemoryRepository</classname></ulink>">
+<!ENTITY InMemoryRepositorySource "<ulink
url='&API;graph/connector/inmemory/InMemoryRepositorySource.html'><classname>InMemoryRepositorySource</classname></ulink>">
+<!ENTITY FederatedRepository "<ulink
url='&API;graph/connector/federation/FederatedRepository.html'><classname>FederatedRepository</classname></ulink>">
+<!ENTITY FederatedRepositorySource "<ulink
url='&API;graph/connector/federation/FederatedRepositorySource.html'><classname>FederatedRepositorySource</classname></ulink>">
+<!ENTITY Projection "<ulink
url='&API;graph/connector/federation/Projection.html'><classname>Projection</classname></ulink>">
+<!ENTITY CachePolicy "<ulink
url='&API;graph/cache/CachePolicy.html'><interface>CachePolicy</interface></ulink>">
+<!ENTITY Request "<ulink
url='&API;graph/request/Request.html'><classname>Request</classname></ulink>">
+<!ENTITY CompositeRequest "<ulink
url='&API;graph/request/CompositeRequest.html'><classname>CompositeRequest</classname></ulink>">
+<!ENTITY ReadNodeRequest "<ulink
url='&API;graph/request/ReadNodeRequest.html'><classname>ReadNodeRequest</classname></ulink>">
+<!ENTITY CopyBranchRequest "<ulink
url='&API;graph/request/CopyBranchRequest.html'><classname>CopyBranchRequest</classname></ulink>">
+<!ENTITY InvalidRequestException "<ulink
url='&API;graph/request/InvalidRequestException.html'><classname>InvalidRequestException</classname></ulink>">
+<!ENTITY InvalidWorkspaceException "<ulink
url='&API;graph/request/InvalidWorkspaceException.html'><classname>InvalidWorkspaceException</classname></ulink>">
+<!ENTITY UnsupportedRequestException "<ulink
url='&API;graph/request/UnsupportedRequestException.html'><classname>UnsupportedRequestException</classname></ulink>">
+<!ENTITY RequestProcessor "<ulink
url='&API;graph/request/processor/RequestProcessor.html'><classname>RequestProcessor</classname></ulink>">
+<!ENTITY StreamSequencer "<ulink
url='&API;graph/sequencer/StreamSequencer.html'><interface>StreamSequencer</interface></ulink>">
+<!ENTITY SequencerOutput "<ulink
url='&API;graph/sequencer/SequencerOutput.html'><interface>SequencerOutput</interface></ulink>">
+<!ENTITY SequencerContext "<ulink
url='&API;graph/sequencer/SequencerContext.html'><interface>SequencerContext</interface></ulink>">
+<!ENTITY MimeTypeDetector "<ulink
url='&API;graph/mimetype/MimeTypeDetector.html'><interface>MimeTypeDetector</interface></ulink>">
+<!ENTITY MockSequencerOutput "<ulink
url='&API;graph/sequencer/MockSequencerOutput.html'><interface>MockSequencerOutput</interface></ulink>">
+<!ENTITY MockSequencerContext "<ulink
url='&API;graph/sequencer/MockSequencerContext.html'><interface>MockSequencerContext</interface></ulink>">
+
+<!-- Types in dna-repository -->
+
+<!ENTITY DnaEngine "<ulink
url='&API;repository/DnaEngine.html'><classname>DnaEngine</classname></ulink>">
+<!ENTITY DnaConfiguration "<ulink
url='&API;repository/DnaConfiguration.html'><classname>DnaConfiguration</classname></ulink>">
+<!ENTITY RepositoryLibrary "<ulink
url='&API;repository/RepositoryLibrary.html'><classname>RepositoryLibrary</classname></ulink>">
+<!ENTITY RepositoryService "<ulink
url='&API;repository/RepositoryService.html'><classname>RepositoryService</classname></ulink>">
+<!ENTITY ServiceAdministrator "<ulink
url='&API;repository/service/ServiceAdministrator.html'><interface>ServiceAdministrator</interface></ulink>">
+<!ENTITY SequencingService "<ulink
url='&API;repository/sequencer/SequencingService.html'><classname>SequencingService</classname></ulink>">
+<!ENTITY SequencerConfig "<ulink
url='&API;repository/sequencer/SequencerConfig.html'><classname>SequencerConfig</classname></ulink>">
+<!ENTITY SessionFactory "<ulink
url='&API;repository/util/SessionFactory.html'><interface>SessionFactory</interface></ulink>">
+<!ENTITY JndiSessionFactory "<ulink
url='&API;repository/util/JndiSessionFactory.html'><classname>JndiSessionFactory</classname></ulink>">
+<!ENTITY SimpleSessionFactory "<ulink
url='&API;repository/util/SimpleSessionFactory.html'><classname>SimpleSessionFactory</classname></ulink>">
+<!ENTITY JcrExecutionContext "<ulink
url='&API;repository/util/JcrExecutionContext.html'><interface>JcrExecutionContext</interface></ulink>">
+<!ENTITY MimeType "<ulink
url='&API;repository/mimetype/MimeType.html'><classname>MimeType</classname></ulink>">
+<!ENTITY MimeTypeDetectorConfig "<ulink
url='&API;repository/mimetype/MimeTypeDetectorConfig.html'><interface>MimeTypeDetectorConfig</interface></ulink>">
+
+
+<!-- Types in dna-jcr -->
+
+<!ENTITY JcrEngine "<ulink
url='&API;jcr/JcrEngine.html'><classname>JcrEngine</classname></ulink>">
+<!ENTITY JcrConfiguration "<ulink
url='&API;jcr/JcrConfiguration.html'><classname>JcrConfiguration</classname></ulink>">
+<!ENTITY JcrRepository "<ulink
url='&API;jcr/JcrRepository.html'><classname>JcrRepository</classname></ulink>">
+<!ENTITY JcrSession "<ulink
url='&API;jcr/JcrSession.html'><classname>JcrSession</classname></ulink>">
+
+<!-- Types in extensions/ -->
+
+<!ENTITY JBossCacheRepository "<ulink
url='&API;connector/jbosscache/JBossCacheRepository.html'><classname>JBossCacheRepository</classname></ulink>">
+<!ENTITY JBossCacheSource "<ulink
url='&API;connector/jbosscache/JBossCacheSource.html'><classname>JBossCacheSource</classname></ulink>">
+<!ENTITY ImageMetadataSequencer "<ulink
url='&API;sequencer/image/ImageMetadataSequencer.html'><classname>ImageMetadataSequencer</classname></ulink>">
+<!ENTITY ImageMetadata "<ulink
url='&API;sequencer/image/ImageMetadata.html'><classname>ImageMetadata</classname></ulink>">
+<!ENTITY ImageSequencerI18n "<ulink
url='&API;sequencer/image/ImageSequencerI18n.html'><classname>ImageSequencerI18n</classname></ulink>">
+<!ENTITY ApertureMimeTypeDetector "<ulink
url='&API;mimetype/aperture/ApertureMimeTypeDetector.html'><classname>ApertureMimeTypeDetector</classname></ulink>">
+
Modified: trunk/docs/gettingstarted/src/main/docbook/en-US/master.xml
===================================================================
--- trunk/docs/gettingstarted/src/main/docbook/en-US/master.xml 2009-06-07 15:05:15 UTC
(rev 988)
+++ trunk/docs/gettingstarted/src/main/docbook/en-US/master.xml 2009-06-07 22:33:45 UTC
(rev 989)
@@ -25,9 +25,8 @@
~ Boston, MA 02110-1301 USA
-->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
-<!ENTITY versionNumber "0.4">
-<!ENTITY copyrightYear "2008-2009">
-<!ENTITY copyrightHolder "Red Hat, Inc.">
+<!ENTITY % CustomDTD SYSTEM "custom.dtd">
+%CustomDTD;
]>
<book lang="en">
<bookinfo>
@@ -35,7 +34,7 @@
<subtitle>Getting Started Guide</subtitle>
<releaseinfo>&versionNumber;</releaseinfo>
<productnumber>&versionNumber;</productnumber>
- <issuenum>4</issuenum>
+ <issuenum>5</issuenum>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="dna-logo.png" align="center"/>
@@ -53,10 +52,10 @@
</bookinfo>
<xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/preface.xml"/>
<xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/introduction.xml"/>
- <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/understanding_dna.xml"/>
+ <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/use_cases.xml"/>
+ <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/using_dna.xml"/>
<xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/downloading_and_running.xml"/>
- <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/using_dna_for_sequencing.xml"/>
- <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/using_dna_repositories.xml"/>
- <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/custom_sequencers.xml"/>
- <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/future.xml"/>
+ <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/sequencer_example.xml"/>
+ <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/repository_example.xml"/>
+ <xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="content/conclusion.xml"/>
</book>
Modified: trunk/docs/reference/src/main/docbook/en-US/content/development_tools.xml
===================================================================
--- trunk/docs/reference/src/main/docbook/en-US/content/development_tools.xml 2009-06-07
15:05:15 UTC (rev 988)
+++ trunk/docs/reference/src/main/docbook/en-US/content/development_tools.xml 2009-06-07
22:33:45 UTC (rev 989)
@@ -225,14 +225,20 @@
<para>This profile informs Maven of the two JBoss repositories (<ulink
url="http://repository.jboss.org/maven2">snapshots</ulink...
and <ulink
url="http://snapshots.jboss.org/maven2">releases</ulink>) that contain
all of the JARs for JBoss DNA and all dependent libraries.
</para>
+ <para>While you're adding <code>$MAVEN_HOME/bin</code> to your
path, you should also set the <code>$MAVEN_OPTS</code> environment variable
+ to "<code>-Xmx256m</code>". If you don't do this,
you'll likely see an <code>java.lang.OutOfMemoryError</code> sometime
during a full
+ build.
<note>
<para>
- It is a policy of the project that the <emphasis>source code and
JARs</emphasis> for <emphasis>all</emphasis> dependencies
- <emphasis>must</emphasis> be loaded into the JBoss repository. This is
so that the project can always be built
- and that all source code is always available.
+ The JBoss Maven repository provides a central location for not only the artifacts
produced by the
JBoss.org projects (well, at least those
+ that use Maven), but also is where those projects can place the artifacts that they
depend on. JBoss DNA has a policy that
+ the <emphasis>source code and JARs</emphasis> for
<emphasis>all</emphasis> dependencies <emphasis>must</emphasis> be
loaded into the
+ JBoss Maven repository. It may be a little bit more work for the developers, but it
does help ensure that developers have easy
+ access to the source and that the project (and dependencies) can always be rebuilt
when needed.
</para>
<para>
- For more information about the JBoss Maven repository, see the <ulink
url="http://wiki.jboss.org/wiki/Maven">JBoss.org Wiki</ulink>.
+ For more information about the JBoss Maven repository, including instructions for
adding source and JAR artifacts,
+ see the <ulink
url="http://wiki.jboss.org/wiki/Maven">JBoss.org
Wiki</ulink>.
</para>
</note>
<para>