Author: rhauch
Date: 2008-05-13 14:56:30 -0400 (Tue, 13 May 2008)
New Revision: 153
Modified:
trunk/docs/gettingstarted/en/master.xml
Log:
Completed the remaining sections/chapters of the document, and made numerous small edits.
Modified: trunk/docs/gettingstarted/en/master.xml
===================================================================
--- trunk/docs/gettingstarted/en/master.xml 2008-05-13 18:30:33 UTC (rev 152)
+++ trunk/docs/gettingstarted/en/master.xml 2008-05-13 18:56:30 UTC (rev 153)
@@ -82,9 +82,9 @@
<chapter id="introduction">
<title>Introduction</title>
<para>There are a lot of choices for how applications can store information
persistently so that it can be accessed at a
- later time and by other processes. The challenge developers face is how to use an
approach that most closely matches the needs
- of their application. This choice becomes more important as developers choose to
focus their efforts on application-specific
- logic, delegating much of the responsibilities for persistence to libraries and
frameworks.</para>
+ later time and by other processes. The challenge developers face is how to use an
approach that most closely matches the
+ needs of their application. This choice becomes more important as developers choose
to focus their efforts on
+ application-specific logic, delegating much of the responsibilities for persistence
to libraries and frameworks.</para>
<para>
Perhaps one of the easiest techniques is to simply store information in
<emphasis>files</emphasis>
@@ -114,8 +114,8 @@
</para>
<para>
<emphasis>Object-relational mapping</emphasis>
- libraries automate the creation of this mapping layer and result in far less code
that is much more maintainable with performance
- that is often as good as (if not better than) handwritten JDBC code. The new
+ libraries automate the creation of this mapping layer and result in far less code
that is much more maintainable with
+ performance that is often as good as (if not better than) handwritten JDBC code.
The new
<ulink
url="http://java.sun.com/developer/technicalArticles/J2EE/jpa/"...
Persistence API (JPA)</ulink>
provide a standard mechanism for defining the mappings (through annotations) and
working with these entity objects. Several
commercial and open-source libraries implement JPA, and some even offer additional
capabilities and features that go beyond
@@ -126,8 +126,9 @@
</para>
<para>
While relational databases and JPA are solutions that work for many applications,
they become more limited in cases when the
- information structure is highly flexible, is not known <emphasis>a
priori</emphasis>, or is subject to frequent change and
- customization. In these situations,
+ information structure is highly flexible, is not known
+ <emphasis>a priori</emphasis>
+ , or is subject to frequent change and customization. In these situations,
<emphasis>content repositories</emphasis>
may offer a better choice for persistence. Content repositories are almost a hybrid
between relational databases and file
systems, and typically provide other capabilities as well, including versioning,
indexing, search, access control,
@@ -149,8 +150,8 @@
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.
+ 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 is building other features as well. One goal of JBoss DNA is
to create federated repositories that
dynamically merge the information from multiple databases, services, applications,
and other JCR repositories. Another is to
@@ -230,8 +231,8 @@
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.
+ 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>
@@ -263,9 +264,9 @@
<listitem>
<para>
<emphasis role="strong">DNA Analyses</emphasis>
- are pluggable components that analyze content and the relationships between
content to generate reports or
- to answer queries. DNA will include some standard analyzers, like
dependency analysis and similarity analysis, that
- are commonly needed by many different solutions. DNA analyzers operate upon
any JCR-compliant repository.
+ are pluggable components that analyze content and the relationships between
content to generate reports or to answer
+ queries. DNA will include some standard analyzers, like dependency analysis
and similarity analysis, that are
+ commonly needed by many different solutions. DNA analyzers operate upon any
JCR-compliant repository.
</para>
</listitem>
<listitem>
@@ -325,9 +326,9 @@
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>
+ 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) - it basically extracts
more useful information from what's already stored in the repository. And it
uses the existing JCR versioning system. Each
@@ -337,9 +338,10 @@
<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
+ 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</ul...
.)
</para>
@@ -353,8 +355,9 @@
<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...
+ - 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>
@@ -564,12 +567,12 @@
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.
+ 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="federation_graph">
@@ -609,18 +612,17 @@
be consulted prior to returning the query results, as the results from one
source might have contributions from another
source.</para>
<note>
- <para> It is hoped that the MetaMatrix query engine can be used for this
purpose, after it is open sourced. This engine
- implements sophisticated query planning and optimization techniques for working
efficiently with multiple sources.
- </para>
+ <para> It is hoped that the MetaMatrix query engine can be used for this
purpose, after it is open sourced. This engine
+ implements sophisticated query planning and optimization techniques for
working efficiently with multiple sources.
+ </para>
</note>
- <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>
+ <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>
@@ -1431,17 +1433,49 @@
====================================================================================================
-->
<chapter id="custom_sequencers">
<title>Creating custom sequencers</title>
- <para>The current release of JBoss DNA comes with a single sequencer that
extracts metadata from image files.
- If you create your own sequencer implementation,
+ <para>The current release of JBoss DNA comes with two sequencers: one that
extracts metadata from a variety of image file formats,
+ and another that extracts some of the ID3 metadata from MP3 audio files. 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 the source can modifying it may be
the easiest way to get started.
+ 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/sequencers/dna-sequenc...
</para>
</note>
- <para>The first step is to <ulink
url="http://maven.apache.org/guides/getting-started/index.html#How_d...
a new Maven 2 project</ulink>
- for your sequencer, and specify the following in your project's
<code>pom.xml</code> dependencies section:
+ <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:
<programlisting>
<dependency>
<groupId>org.jboss.dna</groupId>
@@ -1460,8 +1494,7 @@
</programlisting>
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. Here are
some dependencies you may need,
- depending upon how you want to test:
+ <para>As for testing, you probably will want to add more dependencies, such as
those listed here:
<programlisting>
<dependency>
<groupId>junit</groupId>
@@ -1489,9 +1522,9 @@
<scope>test</scope>
</dependency>
</programlisting>
- If you want to test with JCR and with JBoss DNA, you'll need additional
dependencies for these libraries.
- Strictly speaking, the sequencers do not actually use JCR. Instead, they use
interfaces defined in the <code>dna-spi</code> project.
- This not only simplifies the sequencer implementation, it also dramatically simplifies
testing.
+ 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.
<programlisting>
<dependency>
<groupId>org.jboss.dna</groupId>
@@ -1543,23 +1576,240 @@
</dependency>
</programlisting>
</para>
+ <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></para>
+ <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:
+ <programlisting>
+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 progressMonitor the progress monitor that should be kept
+ * updated with the sequencer's progress and that should be
+ * frequently consulted as to whether this operation has been cancelled.
+ */
+ void sequence( InputStream stream, SequencerOutput output,
+ ProgressMonitor progressMonitor );</programlisting>
+ </para>
+ <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>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.
+ <programlisting>
+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>
+ <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:
+ <programlisting>
+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,
+ ProgressMonitor progressMonitor ) {
+ progressMonitor.beginTask(10, ImageSequencerI18n.sequencerTaskName);
+
+ 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;
+ }
+ progressMonitor.worked(5);
+ if (progressMonitor.isCancelled()) return;
+
+ // 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());
+ }
+
+ progressMonitor.done();
+ }
+}</programlisting>
+ </para>
+ <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>
+ <para>Also note how the progress monitor is used. Reporting progress through
the supplied <code>ProgressMonitor</code> is very easy, and it ensures that
JBoss DNA
+ can accurately monitor and report the status of sequencing activities to the users.
At the beginning of the operation, call
+ <code>beginTask(...)</code> with a meaningful message describing
+ the operation and a total for the amount of work that will be done by this
sequencer. Then perform the sequencing work,
+ periodically reporting work by specifying the incremental amount of work with the
<code>worked(double)</code> method, or
+ by creating a subtask with the <code>createSubtask(double)</code> method
and reporting work against that subtask
+ monitor.
+ </para>
+ <para>Your method should periodically use the ProgressMonitor's
<code>isCancelled()</code> method to check whether the operation has been
+ cancelled.. If this method returns true, the implementation should abort all work
as
+ soon as possible and close any resources that were acquired or opened.
+ </para>
+ <para>
+ Finally, when your sequencing operation is completed, it should call
<code>done()</code> on the progress monitor.
+ </para>
</sect1>
<sect1 id="testing_custom_sequencers">
<title>Testing custom sequencers</title>
- <para></para>
+ <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.
+ <programlisting>
+Sequencer sequencer = new ImageMetadataSequencer();
+MockSequencerOutput output = new MockSequencerOutput();
+ProgressMonitor progress = new SimpleProgressMonitor("Test activity");
+InputStream stream = null;
+try {
+ stream =
this.getClass().getClassLoader().getResource("caution.gif").openStream();
+ sequencer.sequence(stream,output,progress); // 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>
+ <para>It's also useful to test that a sequencer produces no output for
something it should not understand:
+ <programlisting>
+Sequencer sequencer = new ImageMetadataSequencer();
+MockSequencerOutput output = new MockSequencerOutput();
+ProgressMonitor progress = new SimpleProgressMonitor("Test activity");
+InputStream stream = null;
+try {
+ stream =
this.getClass().getClassLoader().getResource("caution.pict").openStream();
+ sequencer.sequence(stream,output,progress); // writes to 'output'
+ assertThat(output.hasProperties(), is(false));
+ assertThat(output.hasReferences(), is(false));
+} finally {
+ stream.close();
+}</programlisting>
+ </para>
+ <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 are produced.
+ </para>
+ <para>It may also be useful to create some integration tests
+ that <link linkend="using_dna">configures JBoss DNA</link> to
use the 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
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>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>
+ <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. JBoss DNA will then create and use the appropriate class
loaders for each extension.
- This will prevent the pollution of the common classpath, allow for easy upgrades,
enable separation of
- the extensions in their own environment, and may even allow for hot redeployment
of newer versions of extensions.
+ 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>
@@ -1578,13 +1828,15 @@
for the list of sequencers we've thought of. If you think of one that's not
there, please add it to JIRA!
</para>
<para>
+ The next release will focus on creating the <link
linkend="federation">federation engine</link> and connectors
+ for several popular and ubiquitous systems. The 0.2 release will likely only federate
information in a read-only manner,
+ but updates will soon follow. Also, during the early part of the next release, the
JBoss DNA project will switch to use JDK 6.
+ Java 5 is being end-of-lifed, so we want to move to a supported JDK. However, a number
of JBoss projects and products continue to
+ require Java 5, so our next release will most likely use JDK 6 with Java 5
compatibility.</para>
+ <para>
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 farter out on our
roadmap, and at this time have not been
- targeted to a particular release. If any of these are of interest to you, please get
involved in the community.
+ 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. If any of these are of interest to you, please
<link linkend="preface">get involved</link> in the community.
</para>
- <para>
- Finally, during the early part of the next release, the JBoss DNA project will switch
to use JDK 6. Java 5 is being
- end-of-lifed, so we want to move to a supported JDK. However, a number of JBoss
projects and products continue to
- require Java 5, so our next release will most likely use JDK 6 with Java 5
compatibility.</para>
</chapter>
</book>
\ No newline at end of file