[dna-commits] DNA SVN: r541 - in trunk/docs/reference/src/main/docbook/en-US: content and 1 other directory.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Thu Sep 25 13:58:08 EDT 2008


Author: rhauch
Date: 2008-09-25 13:58:08 -0400 (Thu, 25 Sep 2008)
New Revision: 541

Modified:
   trunk/docs/reference/src/main/docbook/en-US/content/mimetypes.xml
   trunk/docs/reference/src/main/docbook/en-US/content/testing.xml
   trunk/docs/reference/src/main/docbook/en-US/custom.dtd
Log:
DNA-71 Document development tools and environment
https://jira.jboss.org/jira/browse/DNA-71

Added more content to the Reference Guide.

Modified: trunk/docs/reference/src/main/docbook/en-US/content/mimetypes.xml
===================================================================
--- trunk/docs/reference/src/main/docbook/en-US/content/mimetypes.xml	2008-09-24 21:49:27 UTC (rev 540)
+++ trunk/docs/reference/src/main/docbook/en-US/content/mimetypes.xml	2008-09-25 17:58:08 UTC (rev 541)
@@ -28,17 +28,175 @@
 ]>
 <chapter id="mimetypes">
   <title>MIME types</title>
-  <para></para>
+  <para>
+  	JBoss DNA often needs the ability to determine the MIME type for some binary content.  When uploading content into
+		a repository, we may want to add the MIME type as metadata.  Or, we may want to make some processing decisions
+		based upon the MIME type.  So, JBoss DNA created a small pluggable framework for determining the MIME type by using
+		the name of the file (e.g., extensions) and/or by reading the actual content.  Technically, the framework
+		delegates this to one or more extensions.  And we've provided one extension that does a very good job at 
+		determining the MIME type from a large variety of file types.  But if that isn't sufficient, you can always
+		incorporate your own detector into JBoss DNA.
+  </para>
+	<para>
+		To use this system, you simply invoke a static method and supply the name of the content (e.g., the name of the file, with the extension)
+		and the &InputStream; to the actual binary content:
+	</para>
+	<programlisting>&MimeType;.of(name,content)</programlisting>
+	<para>
+		The result is a &String; containing the <ulink url="http://www.iana.org/assignments/media-types/">MIME type</ulink>
+	  (e.g., "text/plain") or null if the MIME type cannot be determined.  Note that the name or &InputStream; may be
+		null, making this a very versatile utility.
+	</para>
   <sect1 id="detectors">
     <title>JBoss DNA MIME type detectors</title>
-    <para></para>
+    <para>
+    	The principle component in this framework is the concept of a <emphasis role="strong">detector</emphasis>.
+			A detector attempts to determine the MIME type using the name of the content (e.g., the file name)
+			and the actual content itself.  If the detector is able to determine the MIME type, it simply returns
+			it as a string.  If not, it merely returns null.  Note, however, that a detector must be thread-safe.
+    </para>
+		<para>
+			Here is the interface:
+		</para>
+		<programlisting>
+package org.jboss.dna.graph.mimetype;
+ at ThreadSafe
+public interface &MimeTypeDetector; {
+
+    /**
+     * Returns the MIME-type of a data source, using its supplied content and/or
+     * its supplied name, depending upon the implementation. If the MIME-type 
+     * cannot be determined, either a "default" MIME-type or <code>null</code> may 
+     * be returned, where the former will prevent earlier registered MIME-type 
+     * detectors from being consulted.
+     * 
+     * @param name The name of the data source; may be <code>null</code>.
+     * @param content The content of the data source; may be <code>null</code>.
+     * @return The MIME-type of the data source, or optionally <code>null</code> 
+     * if the MIME-type could not be determined.
+     * @throws &IOException; If an error occurs reading the supplied content.
+     */
+    &String; mimeTypeOf( &String; name,
+                       &InputStream; content ) throws &IOException;;
+}</programlisting>
+		<para>
+			Detectors can be added to the &MimeType; class using the <code>addDetector(&MimeTypeDetectorConfig; config)</code>
+			method, where the &MimeTypeDetectorConfig; defines the name of the detector class, the name of the
+			<link linkend="classloaders">class loader</link>, a name, and a description.  It is also possible
+			to set the &ClassLoaderFactory; that the &MimeType; singleton will use.
+		</para>
+		<para>
+			We'll next look at the MIME type detectors that are provided out by JBoss DNA out of the box, and how to write your own. 
+		</para>
     <sect2 id="dna-mimetype-detector-aperture">
       <title>Aperture MIME type detector</title>
-      <para></para>
+      <para>
+      	The &ApertureMimeTypeDetector; class is an implementation of &MimeTypeDetector; that uses the
+				<ulink url="http://aperture.sourceforge.net/">Aperture</ulink> open-source library, which
+				is a very capable utility for determining the MIME type for a wide range of file types,
+				using both the file name and the actual content.
+      </para>
     </sect2>
   </sect1>
   <sect1 id="custom-detectors">
     <title>Writing custom detectors</title>
-    <para></para>
+	  <para>
+	  Creating a custom detector involves the following steps:
+	  <itemizedlist>
+	    <listitem>
+	      <para>Create a Maven 2 project for your detector;</para>
+	    </listitem>
+	    <listitem>
+	      <para>Implement the &MimeTypeDetector; interface with your own implementation, and create unit tests to verify
+	      the functionality and expected behavior;</para>
+	    </listitem>
+	    <listitem>
+	      <para>Add a &MimeTypeDetectorConfig; to the &MimeType; class in your application
+	      as described <link linkend="detectors">earlier</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>
+	  <sect2 id="custom_detector_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="maven">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 detector 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 <emphasis role="strong">dna-mimetype-detector-aperture</emphasis> project is a small, self-contained detector implementation that
+			    that you can use to help you get going.  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="&Subversion;trunk/extensions/dna-mimetype-detector-aperture/">&Subversion;trunk/sequencers/dna-mimetype-detector-aperture/</ulink>
+			  </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_do_I_make_my_first_Maven_project">Maven 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.1</version>
+</dependency>
+<dependency>
+  <groupId>org.jboss.dna</groupId>
+  <artifactId>dna-graph</artifactId>
+  <version>0.1</version>
+</dependency>
+<dependency>
+  <groupId>org.slf4j</groupId>
+  <artifactId>slf4j-api</artifactId>
+</dependency>
+]]></programlisting>
+			<para>These are minimum dependencies required for compiling a detector.  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>
+				After you've created the project, simply implement the &MimeTypeDetector; interface.  And testing should be
+				quite straightforward, MIME type detectors don't require any other components.  In your tests,
+				simply instantiate your &MimeTypeDetector; implementation, supply various combinations of names and/or &InputStream;s,
+				and verify the output is what you expect.
+	  	</para>
+			<para>
+				To use in your application, create a &MimeTypeDetectorConfig; object with the name, description, and class information
+				for your detector, and add to the &MimeType; class using the <code>addDetector(&MimeTypeDetectorConfig; config)</code> method.
+				Then, just use the &MimeType; class.
+			</para>
+		</sect2>
   </sect1>
 </chapter>

Modified: trunk/docs/reference/src/main/docbook/en-US/content/testing.xml
===================================================================
--- trunk/docs/reference/src/main/docbook/en-US/content/testing.xml	2008-09-24 21:49:27 UTC (rev 540)
+++ trunk/docs/reference/src/main/docbook/en-US/content/testing.xml	2008-09-25 17:58:08 UTC (rev 541)
@@ -28,13 +28,103 @@
 ]>
 <chapter id="testing">
   <title>Testing</title>
-  <para></para>
+  <para>
+  	The JBoss DNA project uses automated testing to verify that the software is doing what it's supposed to
+		and not doing what it shouldn't do.  These automated tests are run continuously and also act as regression tests,
+		ensuring that we known if any problems we find and fix reappear later.  All of our tests are executed as part of
+		our <link linkend="maven">Maven</link> build process, and the entire build process (including the tests)
+		is automatically run using <link linkend="hudson">Hudson</link> continuous integration system.
+  </para>
   <sect1 id="unit-tests">
     <title>Unit tests</title>
-    <para></para>
+    <para>
+    	<emphasis role="strong">Unit tests</emphasis> verify the behavior of a single class (or small set of classes) in isolation
+			from other classes.
+ 			We use the JUnit 4.4 testing framework, which has significant improvements over earlier versions and makes
+			it very easy to quickly write unit tests with little extra code.  We also frequently use the Mockito library
+			to help create mock implementations of other classes that are not under test but are used in the tests.
+    </para>
+  	<para>
+			Unit tests should generally run quickly and should not require large assemblies of components.  Additionally,
+			they may rely upon the file resources included in the project, but these tests should require no external resources
+			(like databases or servers).  Note that our unit tests are run during the "test" phase of the standard
+			<ulink url="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html">Maven lifecycle</ulink>.
+			This means that they are executed against the raw .class files created during complication.
+		</para>
+		<para>
+			Developers are expected to run all of the JBoss DNA unit tests in their local environment before committing changes to SVN.
+			So, if you're a developer and you've made changes to your local copy of the source, you can run those tests that are
+			related to your changes using your IDE or with Maven (or any other mechanism).  But before you commit your changes, 
+			you are expected to run a full Maven build using <code>mvn clean install</code> (in the "trunk/" directory).
+			Please do <emphasis>not</emphasis> rely upon continuous integration to run all of the tests for you - the CI
+			system is there to catch the occasional mistakes and to also run the <link linkend="integration-tests">integration tests</link>.
+    </para>
   </sect1>
   <sect1 id="integration-tests">
     <title>Integration tests</title>
-    <para></para>
+    <para>
+    	While <link linkend="unit-tests">unit tests</link> test individual classes in (relative) isolation, the purpose of
+			<emphasis role="strong">integration tests</emphasis> are to verify that assemblies of classes and components are
+			behaving correctly.  These assemblies are often the same ones that end users will actually use.  In fact,
+			integration tests are executed during the "integration-test" phase of the standard
+			<ulink url="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html">Maven lifecycle</ulink>,
+			meaning they are executed against the packaged JARs and artifacts of the project.
+    </para>
+		<para>
+			Integration tests also use the JUnit 4.4 framework, so they are again easy to write and follow the same pattern
+			as unit tests. However, because they're working with larger assemblies of components, they often will take longer
+			to set up, longer to run, and longer to tear down.  They also may require initializing "external resources", like
+			databases or servers.  
+		</para>
+		<para>
+			Note, that while external resources may be required, care should be taken to minimize these dependencies and to
+			ensure that most (if not all) integration tests may be run by anyone who downloads the source code.  This means
+			that these external resources should be available and set up within the tests.  For example, use in-memory databases
+			where possible.  Or, if a database is required, use an open-source database (e.g., MySQL or PostgreSQL).  And when
+			these external resources are not available, it should be obvious from the test class names and/or test method names 
+			that it involved an external resource (e.g., "<code>MySqlConnectorIntegrationTest.shouldFindNodeStoredInDatabase()</code>").
+		</para>
   </sect1>
+  <sect1 id="writing-tests">
+    <title>Writing tests</title>
+		<para>
+			As mentioned in <link linkend="methodology">the introduction</link>, the JBoss DNA project doesn't follow any one methodology
+			or process.  Instead, we simply have a goal that as much code as possible is tested to ensure it behaves as expected.
+			Do we expect 100% of the code is covered by automated tests?  No, but we do want to test as much as we can.
+			Maybe a simple JavaBean class doesn't need many tests, but any class with non-trivial logic should be tested.
+		</para>
+		<para>
+			We do encourage writing tests either before or while you write the code.  Again, we're not blindly following a methodology.
+			Instead, there's a very practical reason: writing the tests early on helps you write classes that are testable.  
+			If you wait until after the class (or classes) are done, you'll probably find that it's not easy to test all
+			of the logic (especially the complicated logic).
+		</para>
+		<para>
+			Another suggestion is to write tests so that they specify and verify the behavior that is expected from a class or component.
+			One challenge developers often have is knowing what they should even test and what the tests should look like.
+			This is where <emphasis role="strong"><ulink url="http://behaviour-driven.org/">Behavior-driven development (BDD)</ulink></emphasis>
+			helps out.  If you think about what a class' behaviors are supposed to be (e.g., requirements), simply capture those
+			requirements as test methods (with no implementations).  For example, a test class for sequencer 
+			implementation might have a test method	<code>shouldNotThrowAnErrorWhenTheSuppliedStreamIsNull() { }</code>.  Then, after you enumerate
+			all the requirements you can think of, go back and start implementing the test methods.
+		</para>
+		<para>
+			If you look at the existing test cases, you'll find that the names of the unit and integration tests in JBoss DNA 
+			follow a naming style, where the test method names are readable sentences.  Actually, we try to name the test methods
+			<emphasis>and</emphasis> the test classes such that they form a concisely-worded requirement.  For example,
+		</para>
+		<programlisting>InMemorySequencerTest.shouldNotThrowAnErrorWhenTheSuppliedStreamIsNull()</programlisting>
+		<para>
+			is easily translated into a readable requirement:
+		</para>
+		<programlisting>InMemorySequencer should not throw an error when the supplied stream is null.</programlisting>
+		<para>
+			In fact, at some point in the future, we'd like to process the source to automatically generate a list of the behavior specifications
+			that are asserted by the tests.
+		</para>
+		<para>
+			But for now, we write tests - a lot of them.  And by following a few simple conventions and practices, we're able
+			to do it quickly and in a way that makes it easy to understand what the code is supposed to do (or not do).
+		</para>
+	</sect1>
 </chapter>

Modified: trunk/docs/reference/src/main/docbook/en-US/custom.dtd
===================================================================
--- trunk/docs/reference/src/main/docbook/en-US/custom.dtd	2008-09-24 21:49:27 UTC (rev 540)
+++ trunk/docs/reference/src/main/docbook/en-US/custom.dtd	2008-09-25 17:58:08 UTC (rev 541)
@@ -26,7 +26,9 @@
 
 <!-- Types in JRE -->
 
+<!ENTITY String							      		"<ulink url='&Java;java/lang/String.html'><interface>String</interface></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>">
@@ -61,6 +63,7 @@
 <!ENTITY RepositoryConnection    			"<ulink url='&API;graph/connectors/RepositoryConnection.html'><interface>RepositoryConnection</interface></ulink>">
 <!ENTITY StreamSequencer		    			"<ulink url='&API;graph/sequencers/StreamSequencer.html'><interface>StreamSequencer</interface></ulink>">
 <!ENTITY SequencerOutput		    			"<ulink url='&API;graph/sequencers/SequencerOutput.html'><interface>SequencerOutput</interface></ulink>">
+<!ENTITY MimeTypeDetector					  	"<ulink url='&API;graph/mimetype/MimeTypeDetector.html'><interface>MimeTypeDetector</interface></ulink>">
 
 <!-- Types in dna-repository -->
 
@@ -74,7 +77,10 @@
 <!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 BasicJcrExecutionContext	  	"<ulink url='&API;repository/util/BasicJcrExecutionContext.html'><classname>BasicJcrExecutionContext</classname></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 JcrRepository			       		"<ulink url='&API;jcr/JcrRepository.html'><classname>JcrRepository</classname></ulink>">
@@ -87,4 +93,5 @@
 <!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/ApertureMimeTypeDetector.html'><classname>ApertureMimeTypeDetector</classname></ulink>">
 




More information about the dna-commits mailing list