[hibernate-commits] Hibernate SVN: r16741 - core/trunk/documentation/manual/src/main/docbook/en-US/content.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Jun 10 13:17:48 EDT 2009


Author: steve.ebersole at jboss.com
Date: 2009-06-10 13:17:48 -0400 (Wed, 10 Jun 2009)
New Revision: 16741

Modified:
   core/trunk/documentation/manual/src/main/docbook/en-US/content/tutorial.xml
Log:
HHH-3953 - Update tutorial chapter


Modified: core/trunk/documentation/manual/src/main/docbook/en-US/content/tutorial.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/content/tutorial.xml	2009-06-10 14:27:12 UTC (rev 16740)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/tutorial.xml	2009-06-10 17:17:48 UTC (rev 16741)
@@ -27,25 +27,17 @@
         <!ENTITY mdash "-">
 ]>
 
-        <!-- todo : need separate sections, one for each tutorial -->
-
 <chapter id="tutorial">
-    <title>Introduction to Hibernate</title>
-    
-    <sect1 id="tutorial-intro">
-        <title>Preface</title>
+    <title>Tutorial</title>
 
-        <para>
-            Intended for new users, this chapter provides an introduction to Hibernate
-      The chapter provides a step-by-step tutorial, starting with a simple
-            application using an in-memory database.  The tutorial is
-            based on an earlier tutorial developed by Michael Gloegl.  All
-            code is contained in the <filename>tutorials/web</filename> directory
-            of the project source.
-        </para>
+    <para>
+        Intended for new users, this chapter provides an step-by-step introduction
+        to Hibernate, starting with a simple application using an in-memory database.  The
+        tutorial is based on an earlier tutorial developed by Michael Gloegl.  All
+        code is contained in the <filename>tutorials/web</filename> directory of the project
+        source.
+    </para>
 
-    </sect1>
-
     <important>
         <para>
             This tutorial expects the user have knowledge of both Java and
@@ -57,11 +49,9 @@
 
     <note>
         <para>
-            There is another tutorial/example application in the
-            <filename>/tutorials/eg</filename> directory of the project source.
-            That example is console-based and, as such, would not have the
-            dependency on a servlet container to execute.  The basic setup is
-            the same as the instructions below.
+            The distribution contains another example application under
+            the <filename>tutorial/eg</filename> project source
+            directory.
         </para>
     </note>
 
@@ -70,34 +60,56 @@
 
         <para>
             For this example, we will set up a small database application that can store
-            events we want to attend, and information about the host(s) of
-            these events.  Although you can use whatever database you feel comfortable using, we will use an in-memory, Java database named HSQLDB
-            to avoid describing installation/setup of any particular database
-            servers. 
+            events we want to attend and information about the host(s) of these events.
         </para>
-            
-        <para>
-            The first thing we need to do is set up the development environment,
-            including all the required dependencies to Hibernate,
-            as well as other libraries.  Hibernate is built using Maven which, 
-            amongst other features, provides <literal>dependency management</literal>;
-            moreover it provides <emphasis>transitive</emphasis>
-            <literal>dependency management</literal>, which simply means that by using
-            Hibernate we can define our dependency on Hibernate. Hibernate
-            itself defines the dependencies it needs which then become transitive
-            dependencies of our project.
-        </para>
 
-        <programlisting><![CDATA[.
-<project xmlns="http://maven.apache.org/POM/4.0.0"
+        <note>
+            <para>
+                Although you can use whatever database you feel comfortable using, we
+                will use <ulink url="http://hsqldb.org/">HSQLDB</ulink> (an in-memory,
+                Java database) to avoid describing installation/setup of any particular
+                database servers.
+            </para>
+        </note>
+
+        <sect2 id="tutorial-firstapp-setup">
+            <title>Setup</title>
+
+            <para>
+                The first thing we need to do is to set up the development environment.  We
+                will be using the "standard layout" advocated by alot of build tools such
+                as <ulink url="http://maven.org">Maven</ulink>.  Maven, in particular, has a
+                good resource describing this <ulink url="http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html">layout</ulink>.
+                As this tutorial is to be a web application, we will be creating and making
+                use of <filename>src/main/java</filename>, <filename>src/main/resources</filename>
+                and <filename>src/main/webapp</filename> directories.
+            </para>
+
+            <para>
+                We will be using Maven in this tutorial, taking advantage of its
+                transitive dependency management capabilities as well as the ability of
+                many IDEs to automatically set up a project for us based on the maven descriptor.
+            </para>
+
+        <programlisting><![CDATA[<project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
-    ...
+    <modelVersion>4.0.0</modelVersion>
 
+    <groupId>org.hibernate.tutorials</groupId>
+    <artifactId>hibernate-tutorial</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <name>First Hibernate Tutorial</name>
+
+    <build>
+         <!-- we dont want the version to be part of the generated war file name -->
+         <finalName>${artifactId}</finalName>
+    </build>
+
     <dependencies>
         <dependency>
-            <groupId>${groupId}</groupId>
+            <groupId>org.hibernate</groupId>
             <artifactId>hibernate-core</artifactId>
         </dependency>
 
@@ -106,34 +118,52 @@
             <groupId>javax.servlet</groupId>
             <artifactId>servlet-api</artifactId>
         </dependency>
+
+        <!-- Hibernate uses slf4j for logging, for our purposes here use the simple backend -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+        </dependency>
+
+        <!-- Hibernate gives you a choice of bytecode providers between cglib and javassist -->
+        <dependency>
+            <groupId>javassist</groupId>
+            <artifactId>javassist</artifactId>
+        </dependency>
     </dependencies>
 
 </project>]]></programlisting>
 
-        <note>
-            <para>
-                Essentially we are describing here the
-                <filename>/tutorials/web/pom.xml</filename> file.  See the
-                <ulink url="http://maven.org">Maven</ulink> site for more information.
-            </para>
-        </note>
+            <tip>
+                <para>
+                    It is not a requirement to use Maven.  If you wish to use something else to
+                    build this tutoial (such as Ant), the layout will remain the same.  The only
+                    change is that you will need to manually account for all the needed
+                    dependencies.  If you use something like <ulink url="http://ant.apache.org/ivy/">Ivy</ulink>
+                    providing transitive dependency management you would still use the dependencies
+                    mentioned below.  Otherwise, you'd need to grab <emphasis>all</emphasis>
+                    dependencies, both explicit and transitive, and add them to the project's
+                    classpath.  If working from the Hibernate distribution bundle, this would mean
+                    <filename>hibernate3.jar</filename>, all artifacts in the
+                    <filename>lib/required</filename> directory and all files from either the
+                    <filename>lib/bytecode/cglib</filename> or <filename>lib/bytecode/javassist</filename>
+                    directory; additionally you will need both the servlet-api jar and one of the slf4j
+                    logging backends.
+                </para>
+            </tip>
 
-        <tip>
             <para>
-                While not strictly necessary, most IDEs have integration with Maven
-                to read these POM files and automatically set up a project for you.
+                Save this file as <filename>pom.xml</filename> in the project root directory.
             </para>
-        </tip>
+        </sect2>
 
-        <para>
-            Next, create a class that represents the event you want to store in the database.
-        </para>
-      
+
         <sect2 id="tutorial-firstapp-firstclass">
             <title>The first class</title>
             
             <para>
-                The first persistent class is a simple JavaBean class with some properties:
+                Next, we create a class that represents the event we want to store in the
+                database; it is a simple JavaBean class with some properties:
             </para>
 
             <programlisting><![CDATA[package org.hibernate.tutorial.domain;
@@ -175,57 +205,50 @@
 
             <para>
                 This class uses standard JavaBean naming conventions for property
-                getter and setter methods, as well as private visibility for the fields. Although this is
-                a recommended design, it is not required. Hibernate can also access fields directly,
-                the benefit of accessor methods is robustness for refactoring. The no-argument
-                constructor is required to instantiate an object of this class through reflection.
+                getter and setter methods, as well as private visibility for the
+                fields.  Although this is the recommended design, it is not required.
+                Hibernate can also access fields directly,  the benefit of accessor
+                methods is robustness for refactoring.
             </para>
 
             <para>
-                The <literal>id</literal> property holds a unique identifier value for a particular event.
-                All persistent entity classes (there are less important dependent classes as well) will need
-                such an identifier property if we want to use the full feature set of Hibernate. In fact,
-                most applications, especially web applications, need to distinguish objects by identifier, so you
-                should consider this a feature rather than a limitation. However, we usually do not manipulate
-                the identity of an object, hence the setter method should be private. Only Hibernate will assign
-                identifiers when an object is saved. Hibernate can access public, private,
-                and protected accessor methods, as well as public, private and protected fields directly. The
-                choice is up to you and you can match it to fit your application design.
+                The <literal>id</literal> property holds a unique identifier value
+                for a particular event.  All persistent entity classes (there are
+                less important dependent classes as well) will need such an identifier
+                property if we want to use the full feature set of Hibernate. In fact,
+                most applications, especially web applications, need to distinguish
+                objects by identifier, so you should consider this a feature rather
+                than a limitation.  However, we usually do not manipulate the identity
+                of an object, hence the setter method should be private.  Only Hibernate
+                will assign identifiers when an object is saved.  Hibernate can access
+                public, private, and protected accessor methods, as well as public,
+                private and protected fields directly.  The choice is up to you and
+                you can match it to fit your application design.
             </para>
 
             <para>
-                The no-argument constructor is a requirement for all persistent classes; Hibernate
-                has to create objects for you, using Java Reflection. The constructor can be
-                private, however, package visibility is required for runtime proxy generation and
-                efficient data retrieval without bytecode instrumentation.
+                The no-argument constructor is a requirement for all persistent
+                classes; Hibernate has to create objects for you, using Java
+                Reflection.  The constructor can be private, however package or public
+                visibility is required for runtime proxy generation and efficient data
+                retrieval without bytecode instrumentation.
             </para>
 
             <para>
-                Place the Java source file in a directory called <literal>src</literal> in the
-                development folder, and in its correct package. The directory should now look like this:
+                Save this file to the <filename>src/main/java/org/hibernate/tutorial/domain</filename>
+                directory.
             </para>
-
-            <programlisting><![CDATA[.
-+lib
-  <Hibernate and third-party libraries>
-+src
-  +events
-    Event.java]]></programlisting>
-
-            <para>
-                In the next step, we tell Hibernate about this persistent class.
-            </para>
-                
         </sect2>
 
         <sect2 id="tutorial-firstapp-mapping">
             <title>The mapping file</title>
 
             <para>
-                Hibernate needs to know how to load and store objects of the persistent class.
-                This is where the Hibernate mapping file comes into play. The mapping file
-                tells Hibernate what table in the database it has to access, and what columns
-                in that table it should use.
+                Hibernate needs to know how to load and store objects of the
+                persistent class.  This is where the Hibernate mapping file
+                comes into play. The mapping file tells Hibernate what table in
+                the database it has to access, and what columns in that table
+                it should use.
             </para>
 
             <para>
@@ -237,25 +260,28 @@
         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
         "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 
-<hibernate-mapping>
+<hibernate-mapping package="org.hibernate.tutorial.domain">
 [...]
 </hibernate-mapping>]]></programlisting>
 
             <para>
-                Hibernate DTD is sophisticated. You can use it for
-                auto-completion of XML mapping elements and attributes in your editor or
-                IDE. Opening up the DTD file in your text editor is the
-                easiest way to get an overview of all elements and attributes, and to view
-                the defaults, as well as some comments.  Hibernate will not
-                load the DTD file from the web, but first look it up from the classpath
-                of the application. The DTD file is included in <literal>hibernate3.jar</literal>
-                as well as in the <literal>src/</literal> directory of the Hibernate distribution.
+                Hibernate DTD is sophisticated.  You can use it for auto-completion
+                of XML mapping elements and attributes in your editor or IDE.
+                Opening up the DTD file in your text editor is the easiest way to
+                get an overview of all elements and attributes, and to view the
+                defaults, as well as some comments.  Hibernate will not load the
+                DTD file from the web, but first look it up from the classpath of
+                the application.  The DTD file is included in
+                <filename>hibernate-core.jar</filename> (it is also included in the
+                <filename>hibernate3.jar</filename>, if using the distribution bundle).
             </para>
 
-            <para>
-                We will omit the DTD declaration in future examples to shorten the code. It is,
-                of course, not optional.
-            </para>
+            <important>
+                <para>
+                    We will omit the DTD declaration in future examples to shorten the code. It is,
+                    of course, not optional.
+                </para>
+            </important>
 
             <para>
                 Between the two <literal>hibernate-mapping</literal> tags, include a
@@ -264,25 +290,27 @@
                 a mapping to a table in the SQL database:
             </para>
 
-            <programlisting><![CDATA[<hibernate-mapping>
+            <programlisting><![CDATA[<hibernate-mapping package="org.hibernate.tutorial.domain">
 
-    <class name="events.Event" table="EVENTS">
+    <class name="Event" table="EVENTS">
 
     </class>
 
 </hibernate-mapping>]]></programlisting>
 
             <para>
-                So far we have told Hibernate how to persist and load object of class <literal>Event</literal>
-                to the table <literal>EVENTS</literal>. Each instance is now represented by a row in that table.
-                Now we can continue by mapping the unique identifier property to the tables primary key.
-                As we do not want to care about handling this identifier, we configure Hibernate's
+                So far we have told Hibernate how to persist and load object of
+                class <literal>Event</literal> to the table
+                <literal>EVENTS</literal>. Each instance is now represented by a
+                row in that table.  Now we can continue by mapping the unique
+                identifier property to the tables primary key.  As we do not want
+                to care about handling this identifier, we configure Hibernate's
                 identifier generation strategy for a surrogate primary key column:
             </para>
 
-            <programlisting><![CDATA[<hibernate-mapping>
+            <programlisting><![CDATA[<hibernate-mapping package="org.hibernate.tutorial.domain">
 
-    <class name="events.Event" table="EVENTS">
+    <class name="Event" table="EVENTS">
         <id name="id" column="EVENT_ID">
             <generator class="native"/>
         </id>
@@ -291,29 +319,43 @@
 </hibernate-mapping>]]></programlisting>
 
             <para>
-                The <literal>id</literal> element is the declaration of the identifier property,
-                <literal>name="id"</literal> declares the name of the Java property.
-                Hibernate will use the getter and setter methods to access the property.
-                The column attribute tells Hibernate which column of the
-                <literal>EVENTS</literal> table to use for this primary key. The nested
-                <literal>generator</literal> element specifies the identifier generation strategy.
-                
-		In this case you used <literal>native</literal>, which selects the best strategy depending
-                on the configured database dialect. Hibernate supports database generated, globally
-                unique, as well as application assigned, identifiers. Hibernate supports any strategy you have written
-                an extension for.
+                The <literal>id</literal> element is the declaration of the
+                identifier property.  The <literal>name="id"</literal> mapping
+                attribute declares the name of the JavaBean property and tells
+                Hibernate to use the <literal>getId()</literal> and
+                <literal>setId()</literal> methods to access the property.  The
+                column attribute tells Hibernate which column of the
+                <literal>EVENTS</literal> table holds the primary key value.
             </para>
 
             <para>
-                Finally, include declarations for the persistent properties of the class in
-                the mapping file. By default, no properties of the class are considered
+                The nested <literal>generator</literal> element specifies the
+                identifier generation strategy (aka how are identifier values
+                generated?).  In this case we choose <literal>native</literal>,
+                which offers a level of portability depending on the configured
+                database dialect.  Hibernate supports database generated, globally
+                unique, as well as application assigned, identifiers.  Identifier
+                value generation is also one of Hibernate's many extension points
+                and you can plugin in your own strategy.
+            </para>
+
+            <tip>
+                <para>
+                    <literal>native</literal> is no longer consider the best strategy in terms of portability.  for further
+                    discussion, see <xref linkend="portability-idgen"/>
+                </para>
+            </tip>
+
+            <para>
+                Lastly, we need to tell Hibernate about the remaining entity class
+                properties.  By default, no properties of the class are considered
                 persistent:
             </para>
             
             <programlisting><![CDATA[
-<hibernate-mapping>
+<hibernate-mapping package="org.hibernate.tutorial.domain">
 
-    <class name="events.Event" table="EVENTS">
+    <class name="Event" table="EVENTS">
         <id name="id" column="EVENT_ID">
             <generator class="native"/>
         </id>
@@ -324,27 +366,31 @@
 </hibernate-mapping>]]></programlisting>
             
             <para>
-                Similar to the <literal>id</literal> element, the <literal>name</literal>
-                attribute of the <literal>property</literal> element tells Hibernate which getter
-                and setter methods to use.  In this case, Hibernate will search for
-                <literal>getDate()/setDate()</literal>, as well as <literal>getTitle()/setTitle()</literal>.
+                Similar to the <literal>id</literal> element, the
+                <literal>name</literal> attribute of the
+                <literal>property</literal> element tells Hibernate which getter
+                and setter methods to use.  In this case, Hibernate will search
+                for <literal>getDate()</literal>, <literal>setDate()</literal>,
+                <literal>getTitle()</literal> and <literal>setTitle()</literal>
+                methods.
             </para>
 
-            <para>
-                Why does the <literal>date</literal> property mapping include the
-                <literal>column</literal> attribute, but the <literal>title</literal>
-                does not? Without the <literal>column</literal> attribute, Hibernate
-                by default uses the property name as the column name. This works for
-                <literal>title</literal>, however, <literal>date</literal> is a reserved
-                keyword in most databases so you will need to map it to a different name.
-            </para>
+            <note>
+                <para>
+                    Why does the <literal>date</literal> property mapping include the
+                    <literal>column</literal> attribute, but the <literal>title</literal>
+                    does not? Without the <literal>column</literal> attribute, Hibernate
+                    by default uses the property name as the column name. This works for
+                    <literal>title</literal>, however, <literal>date</literal> is a reserved
+                    keyword in most databases so you will need to map it to a different name.
+                </para>
+            </note>
 
             <para>
-                The <literal>title</literal> mapping also lacks
-                a <literal>type</literal> attribute. The types declared and used in the mapping
-                files are not, as you might expect, Java data types. They are also not SQL
-                database types. These types are called <emphasis>Hibernate mapping types</emphasis>,
-                converters which can translate from Java to SQL data types and vice versa. Again,
+                The <literal>title</literal> mapping also lacks a <literal>type</literal> attribute. The
+                types declared and used in the mapping files are not Java data types; they are not SQL
+                database types either.  These types are called <emphasis>Hibernate mapping types</emphasis>,
+                converters which can translate from Java to SQL data types and vice versa.  Again,
                 Hibernate will try to determine the correct conversion and mapping type itself if
                 the <literal>type</literal> attribute is not present in the mapping. In some cases this
                 automatic detection using Reflection on the Java class might not have the default you
@@ -355,59 +401,64 @@
                 <literal>timestamp</literal> converter.
             </para>
 
+            <tip>
+                <para>
+                    Hibernate makes this mapping type determination using reflection when the mapping files
+                    are processed.  This can take time and resources, so if startup performance is important
+                    you should consider explicitly defining the type to use.
+                </para>
+            </tip>
+
             <para>
-                Save the mapping file as <literal>Event.hbm.xml</literal> in
-                the directory next to the <literal>Event</literal> Java class source file.
-                The naming of mapping files can be arbitrary, however, the <literal>hbm.xml</literal>
-                suffix is a convention in the Hibernate developer community. The directory structure
-                should now look like this:
+                Save this mapping file as
+                <filename>src/main/resources/org/hibernate/tutorial/domain/Event.hbm.xml</filename>.
             </para>
 
-            <programlisting><![CDATA[.
-+lib
-  <Hibernate and third-party libraries>
-+src
-  +events
-    Event.java
-    Event.hbm.xml]]></programlisting>
-
-             <para>
-                 The next section continues with the main configuration of Hibernate.
-             </para>
-
         </sect2>
 
         <sect2 id="tutorial-firstapp-configuration" revision="2">
             <title>Hibernate configuration</title>
 
             <para>
-                You should have a persistent class and its mapping file in place. It is now time to configure
-                Hibernate. Before you do this, you will need a database. HSQL DB, a java-based SQL DBMS,
-                can be downloaded from the HSQL DB website(http://hsqldb.org/). You only need the <literal>hsqldb.jar</literal>
-                from this download. Place this file in the <literal>lib/</literal> directory of the
-                development folder.
+                At this point, you should have the persistent class and its mapping
+                file in place. It is now time to configure Hibernate.  First let's set up
+                HSQLDB to run in "server mode"
             </para>
 
+            <note>
+                <para>
+                    We do this do that the data remains between runs.
+                </para>
+            </note>
+
             <para>
-                Create a directory called <literal>data</literal> in the root of the development directory.
-                This is where HSQL DB will store its data files. Start the database by running
-                <literal>java -classpath ../lib/hsqldb.jar org.hsqldb.Server</literal> in this data directory.
-                You will see it start up and bind to a TCP/IP socket; this is where our application
-                will connect later. If you want to start with a fresh database during this tutorial,
-                shutdown HSQL DB (press <literal>CTRL + C</literal> in the window), delete all files in the
-                <literal>data/</literal> directory, and start HSQL DB again.
+                We will utilize the Maven exec plugin to launch the HSQLDB server
+                by running:
+                <command> mvn exec:java -Dexec.mainClass="org.hsqldb.Server" -Dexec.args="-database.0 file:target/data/tutorial"</command>
+                You will see it start up and bind to a TCP/IP socket; this is where
+                our application will connect later.  If you want to start
+                with a fresh database during this tutorial, shutdown HSQLDB, delete
+                all files in the <filename>target/data</filename> directory,
+                and start HSQLDB again.
             </para>
 
             <para>
-                Hibernate is the layer in your application that connects to this database, so it needs
-                connection information. The connections are made through a JDBC connection pool, which you
-               will also have to configure. The Hibernate distribution contains several open source JDBC connection
-                pooling tools, but you will use the Hibernate built-in connection pool for this tutorial.
-                You will have to copy the required library into your classpath and use different
-                connection pooling settings if you want to use a production-quality third party
-                JDBC pooling software.
+                Hibernate will be connecting to the database on behalf of your application, so it needs to know
+                how to obtain connections.  For this tutorial we will be using a standalone connection
+                pool (as opposed to a <interfacename>javax.sql.DataSource</interfacename>).  Hibernate comes with
+                support for two third-party open source JDBC connection pools:
+                <ulink url="https://sourceforge.net/projects/c3p0">c3p0</ulink> and
+                <ulink url="http://proxool.sourceforge.net/">proxool</ulink>.  However, we will be using the
+                Hibernate built-in connection pool for this tutorial.
             </para>
 
+            <caution>
+                <para>
+                    The built-in Hibernate connection pool is in no way intended for production use.  It
+                    lacks several features found on any decent connection pool.
+                </para>
+            </caution>
+
             <para>
                 For Hibernate's configuration, we can use a simple <literal>hibernate.properties</literal> file, a
                 more sophisticated <literal>hibernate.cfg.xml</literal> file, or even complete
@@ -445,19 +496,22 @@
         <property name="show_sql">true</property>
 
         <!-- Drop and re-create the database schema on startup -->
-        <property name="hbm2ddl.auto">create</property>
+        <property name="hbm2ddl.auto">update</property>
 
-        <mapping resource="events/Event.hbm.xml"/>
+        <mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml"/>
 
     </session-factory>
 
 </hibernate-configuration>]]></programlisting>
 
+            <note>
+                <para>Notice that this configuration file specifies a different DTD</para>
+            </note>
+
             <para>
-                This XML configuration uses a different DTD. You configure
-                Hibernate's <literal>SessionFactory</literal>. SessionFactory is a global factory responsible
-                for a particular database. If you have several databases, for easier startup you should use several
-                <literal>&lt;session-factory&gt;</literal> configurations in
+                You configure Hibernate's <literal>SessionFactory</literal>. SessionFactory is a global
+                factory responsible for a particular database. If you have several databases, for easier
+                startup you should use several <literal>&lt;session-factory&gt;</literal> configurations in
                 several configuration files.
             </para>
 
@@ -465,9 +519,18 @@
                 The first four <literal>property</literal> elements contain the necessary
                 configuration for the JDBC connection. The dialect <literal>property</literal>
                 element specifies the particular SQL variant Hibernate generates.
-                Hibernate's automatic session management for persistence contexts is particularly useful in this context.
+            </para>
 
-                The <literal>hbm2ddl.auto</literal> option turns on automatic generation of
+            <tip>
+                <para>
+                    In most cases, Hibernate is able to properly determine which dialect to use.  See
+                    <xref linkend="portability-dialectresolver"/> for more information.
+                </para>
+            </tip>
+
+            <para>
+                Hibernate's automatic session management for persistence contexts is particularly useful
+                in this context.  The <literal>hbm2ddl.auto</literal> option turns on automatic generation of
                 database schemas directly into the database. This can also be turned
                 off by removing the configuration option, or redirected to a file with the help of
                 the <literal>SchemaExport</literal> Ant task. Finally, add the mapping file(s)
@@ -475,116 +538,83 @@
             </para>
 
             <para>
-                Copy the file into the source directory, so it will end up in the
-                root of the classpath. On startup, Hibernate automatically searches for a file called
-                <literal>hibernate.cfg.xml</literal> in the root of the classpath.
+                Save this file as <filename>hibernate.cfg.xml</filename> into the
+                <filename>src/main/resources</filename> directory.
             </para>
 
         </sect2>
 
-        <sect2 id="tutorial-firstapp-ant" revision="1">
-            <title>Building with Ant</title>
+        <sect2 id="tutorial-firstapp-mvn" revision="1">
+            <title>Building with Maven</title>
 
             <para>
-                We will now build the tutorial with Ant. You will need to have Ant installed.
-                It is available from the <ulink url="http://ant.apache.org/bindownload.cgi">Ant download page</ulink>.
-                Installation instructions for Ant, however, are not be covered here. Please refer to the
-                <ulink url="http://ant.apache.org/manual/index.html">Ant manual</ulink> for further information. After you
-                have installed Ant, you can start to create the buildfile. It will be called
-                <literal>build.xml</literal> and placed directly in the development directory.
+                We will now build the tutorial with Maven.  You will need to
+                have Maven installed; it is available from the
+                <ulink url="http://maven.apache.org/download.html">Maven download page</ulink>.
+                Maven will read the <filename>/pom.xml</filename> file we created
+                earlier and know how to perform some basic project tasks.  First,
+                lets run the <literal>compile</literal> goal to make sure we can compile
+                everything so far:
             </para>
 
-            <para>
-                A basic build file looks like this:
-            </para>
+            <programlisting><![CDATA[[hibernateTutorial]$ mvn compile
+[INFO] Scanning for projects...
+[INFO] ------------------------------------------------------------------------
+[INFO] Building First Hibernate Tutorial
+[INFO]    task-segment: [compile]
+[INFO] ------------------------------------------------------------------------
+[INFO] [resources:resources]
+[INFO] Using default encoding to copy filtered resources.
+[INFO] [compiler:compile]
+[INFO] Compiling 1 source file to /home/steve/projects/sandbox/hibernateTutorial/target/classes
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESSFUL
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 2 seconds
+[INFO] Finished at: Tue Jun 09 12:25:25 CDT 2009
+[INFO] Final Memory: 5M/547M
+[INFO] ------------------------------------------------------------------------]]></programlisting>
 
-            <programlisting><![CDATA[<project name="hibernate-tutorial" default="compile">
-
-    <property name="sourcedir" value="${basedir}/src"/>
-    <property name="targetdir" value="${basedir}/bin"/>
-    <property name="librarydir" value="${basedir}/lib"/>
-
-    <path id="libraries">
-        <fileset dir="${librarydir}">
-            <include name="*.jar"/>
-        </fileset>
-    </path>
-
-    <target name="clean">
-        <delete dir="${targetdir}"/>
-        <mkdir dir="${targetdir}"/>
-    </target>
-
-    <target name="compile" depends="clean, copy-resources">
-      <javac srcdir="${sourcedir}"
-             destdir="${targetdir}"
-             classpathref="libraries"/>
-    </target>
-
-    <target name="copy-resources">
-        <copy todir="${targetdir}">
-            <fileset dir="${sourcedir}">
-                <exclude name="**/*.java"/>
-            </fileset>
-        </copy>
-    </target>
-
-</project>]]></programlisting>
-
-            <para>
-                This will tell Ant to add all files in the library directory ending with <literal>.jar</literal>
-                to the classpath used for compilation. It will also copy all non-Java source files to the
-                target directory, configuration and Hibernate mapping files, for example. If you now run Ant, you
-                will get this output:
-            </para>
-
-            <programlisting><![CDATA[C:\hibernateTutorial\>ant
-Buildfile: build.xml
-
-copy-resources:
-     [copy] Copying 2 files to C:\hibernateTutorial\bin
-
-compile:
-    [javac] Compiling 1 source file to C:\hibernateTutorial\bin
-
-BUILD SUCCESSFUL
-Total time: 1 second ]]></programlisting>
-
         </sect2>
 
         <sect2 id="tutorial-firstapp-helpers" revision="3">
             <title>Startup and helpers</title>
 
             <para>
-                It is time to load and store some <literal>Event</literal> objects, but first
-                you have to complete the setup with some infrastructure code. You have to startup
-                Hibernate by building a global <literal>SessionFactory</literal>
-                object and storing it somewhere for easy access in application code.
-                A <literal>SessionFactory</literal> can open up new <literal>Session</literal>s.
-                A <literal>Session</literal> represents a single-threaded unit of work.  The
-                <literal>SessionFactory</literal> is a thread-safe global object, that is instantiated once.
+                It is time to load and store some <literal>Event</literal>
+                objects, but first you have to complete the setup with some
+                infrastructure code. You have to startup Hibernate by building
+                a global <interfacename>org.hibernate.SessionFactory</interfacename>
+                object and storing it somewhere for easy access in application code.  A
+                <interfacename>org.hibernate.SessionFactory</interfacename> is used to
+                obtain <interfacename>org.hibernate.Session</interfacename> instances.
+                A <interfacename>org.hibernate.Session</interfacename> represents a
+                single-threaded unit of work.  The
+                <interfacename>org.hibernate.SessionFactory</interfacename> is a
+                thread-safe global object that is instantiated once.
             </para>
 
             <para>
-                Create a <literal>HibernateUtil</literal> helper class that takes care
-                of startup and makes accessing a <literal>SessionFactory</literal> convenient.
-                The following example illustrates the implementation:
+                We will create a <literal>HibernateUtil</literal> helper class that
+                takes care of startup and makes accessing the
+                <interfacename>org.hibernate.SessionFactory</interfacename> more convenient.
             </para>
 
-            <programlisting><![CDATA[package util;
+            <programlisting><![CDATA[package org.hibernate.tutorial.util;
 
-import org.hibernate.*;
-import org.hibernate.cfg.*;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
 
 public class HibernateUtil {
 
-    private static final SessionFactory sessionFactory;
+    private static final SessionFactory sessionFactory = buildSessionFactory();
 
-    static {
+    private static SessionFactory buildSessionFactory() {
         try {
             // Create the SessionFactory from hibernate.cfg.xml
-            sessionFactory = new Configuration().configure().buildSessionFactory();
-        } catch (Throwable ex) {
+            return new Configuration().configure().buildSessionFactory();
+        }
+        catch (Throwable ex) {
             // Make sure you log the exception, as it might be swallowed
             System.err.println("Initial SessionFactory creation failed." + ex);
             throw new ExceptionInInitializerError(ex);
@@ -598,39 +628,28 @@
 }]]></programlisting>
 
             <para>
-                This class not only produces the global <literal>SessionFactory</literal> in
-                its static initializer that is called once by the JVM when the class is loaded. It also
-                hides the fact that it uses a static singleton. It might as well lookup the
-                <literal>SessionFactory</literal> from JNDI in an application server.
+                Save this code as
+                <filename>src/main/java/org/hibernate/tutorial/util/HibernateUtil.java</filename>
             </para>
 
             <para>
-                If you give the <literal>SessionFactory</literal> a name in your configuration
-                file, Hibernate will try to bind it to JNDI after it has been built.
-                To avoid this code completely you could also use JMX deployment and let the
-                JMX-capable container instantiate and bind a <literal>HibernateService</literal>
-                to JNDI. These advanced options are discussed in the Hibernate reference
-                documentation.
+                This class not only produces the global
+                <interfacename>org.hibernate.SessionFactory</interfacename> reference in
+                its static initializer; it also hides the fact that it uses a
+                static singleton.  We might just as well have looked up the
+                <interfacename>org.hibernate.SessionFactory</interfacename> reference from
+                JNDI in an application server or any other location for that matter.
             </para>
 
             <para>
-                Place <literal>HibernateUtil.java</literal> in the development source directory in
-                a package next to <literal>events</literal>:
+                If you give the <interfacename>org.hibernate.SessionFactory</interfacename>
+                a name in your configuration, Hibernate will try to bind it to
+                JNDI under that name after it has been built.  Another, better option is to
+                use a JMX deployment and let the JMX-capable container instantiate and bind
+                a <literal>HibernateService</literal> to JNDI. Such advanced options are
+                discussed later.
             </para>
 
-            <programlisting><![CDATA[.
-+lib
-  <Hibernate and third-party libraries>
-+src
-  +events
-    Event.java
-    Event.hbm.xml
-  +util
-    HibernateUtil.java
-  hibernate.cfg.xml
-+data
-build.xml]]></programlisting>
-
             <para>
                 You now need to configure a logging
                 system.  Hibernate uses commons logging and provides two choices: Log4j and
@@ -652,16 +671,19 @@
             <title>Loading and storing objects</title>
 
             <para>
-                You can use Hibernate to load and store objects. Write an
-                <literal>EventManager</literal> class with a <literal>main()</literal> method:
+                We are now ready to start doing some real worjk with Hibernate.
+                Let's start by writing an <literal>EventManager</literal> class
+                with a <literal>main()</literal> method:
             </para>
 
-            <programlisting><![CDATA[package events;
+            <programlisting><![CDATA[package org.hibernate.tutorial;
+
 import org.hibernate.Session;
 
-import java.util.Date;
+import java.util.*;
 
-import util.HibernateUtil;
+import org.hibernate.tutorial.domain.Event;
+import org.hibernate.tutorial.util.HibernateUtil;
 
 public class EventManager {
 
@@ -676,15 +698,12 @@
     }
 
     private void createAndStoreEvent(String title, Date theDate) {
-
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-
         session.beginTransaction();
 
         Event theEvent = new Event();
         theEvent.setTitle(title);
         theEvent.setDate(theDate);
-
         session.save(theEvent);
 
         session.getTransaction().commit();
@@ -693,165 +712,149 @@
 }]]></programlisting>
 
             <para>
-                You can create a new <literal>Event</literal> object and hand it over to Hibernate.
-                Hibernate takes care of the SQL and executes <literal>INSERT</literal>
-                on the database. We will explain the <literal>Session</literal> and
-                <literal>Transaction</literal>-handling code before we run this.
+                In <literal>createAndStoreEvent()</literal> we created a new
+                <literal>Event</literal> object and handed it over to Hibernate.
+                At that point, Hibernate takes care of the SQL and executes an
+                <literal>INSERT</literal> on the database.
             </para>
 
             <para>
-                A <literal>Session</literal> is a single unit of work. For now we will keep things
-                simple and assume a one-to-one granularity between a Hibernate <literal>Session</literal>
-                and a database transaction. To shield our code from the actual underlying transaction
-                system we use the
-                <literal>Transaction</literal> API that is available on the Hibernate <literal>Session</literal>. 
-		In this case plain JDBC, but it could also run with JTA.
+                A <interface>org.hibernate.Session</interface> is designed to
+                represent a single unit of work (a single atmoic piece of work
+                to be performed).  For now we will keep things simple and assume
+                a one-to-one granularity between a Hibernate
+                <interface>org.hibernate.Session</interface> and a database
+                transaction.  To shield our code from the actual underlying
+                transaction system we use the Hibernate
+                <interfacename>org.hibernate.Transaction</interfacename> API.
+                In this particular case we are using JDBC-based transactional
+                semantics, but it could also run with JTA.
             </para>
 
             <para>
-                What does <literal>sessionFactory.getCurrentSession()</literal> do? First, you can call it
-                as many times and anywhere you like, once you get hold of your <literal>SessionFactory</literal>.
-                This is easy thanks to <literal>HibernateUtil</literal>). The <literal>getCurrentSession()</literal>
-                method always returns the "current" unit of work. Remember that we switched the configuration
-                option for this mechanism to "thread" in <literal>hibernate.cfg.xml</literal>? The current unit of work is bound to the current Java thread that executes the application.
-                However, you also have to consider when a unit of work
-                begins and when it ends.
+                What does <literal>sessionFactory.getCurrentSession()</literal> do?
+                First, you can call it as many times and anywhere you like
+                once you get hold of your
+                <interfacename>org.hibernate.SessionFactory</interfacename>.
+                The <literal>getCurrentSession()</literal> method always returns
+                the "current" unit of work.  Remember that we switched
+                the configuration option for this mechanism to "thread" in our
+                <filename>src/main/resources/hibernate.cfg.xml</filename>?
+                Due to that setting, the context of a current unit of work is bound
+                to the current Java thread that executes the application.
             </para>
 
+            <important>
+                <para>
+                    Hibernate offers three methods of current session tracking.
+                    The "thread" based method is not intended for production use;
+                    it is merely useful for prototyping and tutorials such as this
+                    one.  Current session tracking is discussed in more detail
+                    later on.
+                </para>
+            </important>
+
             <para>
-                A <literal>Session</literal> begins when the first call to
-                <literal>getCurrentSession()</literal> is made. It is then bound by Hibernate to the current
-                thread. When the transaction ends, either through commit or rollback, Hibernate automatically
-                unbinds the <literal>Session</literal> from the thread and closes it for you. If you call
-                <literal>getCurrentSession()</literal> again, you get a new <literal>Session</literal> and can
-                start a new unit of work. This <emphasis>thread-bound</emphasis> programming model is the most
-                popular way of using Hibernate, as it allows flexible layering of your code. Transaction
-                demarcation code can be separated from data access code. This will be covered later in this tutorial.
+                A <interface>org.hibernate.Session</interface> begins when the
+                first call to <literal>getCurrentSession()</literal> is made for
+                the current thread.  It is then bound by Hibernate to the current
+                thread.  When the transaction ends, either through commit or
+                rollback, Hibernate automatically unbinds the
+                <interface>org.hibernate.Session</interface> from the thread
+                and closes it for you. If you call
+                <literal>getCurrentSession()</literal> again, you get a new
+                <interface>org.hibernate.Session</interface> and can start a
+                new unit of work.
             </para>
 
             <para>
-                Related to the unit of work scope, should the Hibernate <literal>Session</literal> be used to
-                execute one or several database operations? The above example uses one <literal>Session</literal>
-                for one operation. This is pure coincidence, the example is just not complex enough to show any
-                other approach. The scope of a Hibernate <literal>Session</literal> is flexible but you should
-                never design your application to use a new Hibernate <literal>Session</literal> for
-                <emphasis>every</emphasis> database operation. Even though it is used in
-                the following examples, consider <emphasis>session-per-operation</emphasis>
-                an anti-pattern. A real web application is shown later in the tutorial.
+                Related to the unit of work scope, should the Hibernate
+                <interface>org.hibernate.Session</interface> be used to execute
+                one or several database operations?  The above example uses one
+                <interface>org.hibernate.Session</interface> for one operation.
+                However this is pure coincidence; the example is just not complex
+                enough to show any other approach. The scope of a Hibernate
+                <interface>org.hibernate.Session</interface> is flexible but you
+                should never design your application to use a new Hibernate
+                <interface>org.hibernate.Session</interface> for
+                <emphasis>every</emphasis> database operation. Even though it is
+                used in the following examples, consider
+                <emphasis>session-per-operation</emphasis> an anti-pattern.
+                A real web application is shown later in the tutorial which will
+                help illustrate this.
             </para>
 
             <para>
                 See <xref linkend="transactions"/> for more information
-                about transaction handling and demarcation. The previous example also skipped any error handling and
-                rollback.
+                about transaction handling and demarcation. The previous
+                example also skipped any error handling and rollback.
             </para>
 
             <para>
-                To run this first routine we have to add a callable target to the Ant build file:
+                To run this, we will make use of the Maven exec plugin to call our class
+                with the necessary classpath setup:
+                <command>mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="store"</command>
             </para>
 
-            <programlisting><![CDATA[<target name="run" depends="compile">
-    <java fork="true" classname="events.EventManager" classpathref="libraries">
-        <classpath path="${targetdir}"/>
-        <arg value="${action}"/>
-    </java>
-</target>]]></programlisting>
+            <note>
+                <para>
+                    You may need to perform <command>mvn compile</command> first.
+                </para>
+            </note>
 
             <para>
-                The value of the <literal>action</literal> argument is set on the command line when
-                calling the target:
+                You should see Hibernate starting up and, depending on your configuration,
+                lots of log output. Towards the end, the following line will be displayed:
             </para>
 
-            <programlisting><![CDATA[C:\hibernateTutorial\>ant run -Daction=store]]></programlisting>
-
-            <para>
-                After compilation, you should see Hibernate starting up and, depending on your
-                configuration, lots of log output. At the end, the following line will be displayed:
-            </para>
-
             <programlisting><![CDATA[[java] Hibernate: insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)]]></programlisting>
 
             <para>
-                This is the <literal>INSERT</literal> executed by Hibernate. The question marks
-                represent JDBC bind parameters. To view the values bound as arguments, or to reduce
-                the verbosity of the log, check your <literal>log4j.properties</literal>.
+                This is the <literal>INSERT</literal> executed by Hibernate.
             </para>
 
             <para>
                 To list stored events an option is added to the main method:
             </para>
 
-            <programlisting><![CDATA[if (args[0].equals("store")) {
-    mgr.createAndStoreEvent("My Event", new Date());
-}
-else if (args[0].equals("list")) {
-    List events = mgr.listEvents();
-    for (int i = 0; i < events.size(); i++) {
-        Event theEvent = (Event) events.get(i);
-        System.out.println("Event: " + theEvent.getTitle() +
-                           " Time: " + theEvent.getDate());
-    }
-}]]></programlisting>
+            <programlisting><![CDATA[        if (args[0].equals("store")) {
+            mgr.createAndStoreEvent("My Event", new Date());
+        }
+        else if (args[0].equals("list")) {
+            List events = mgr.listEvents();
+            for (int i = 0; i < events.size(); i++) {
+                Event theEvent = (Event) events.get(i);
+                System.out.println(
+                        "Event: " + theEvent.getTitle() + " Time: " + theEvent.getDate()
+                );
+            }
+        }]]></programlisting>
 
             <para>
                 A new <literal>listEvents() method is also added</literal>:
             </para>
 
-            <programlisting><![CDATA[private List listEvents() {
+            <programlisting><![CDATA[    private List listEvents() {
+        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+        session.beginTransaction();
+        List result = session.createQuery("from Event").list();
+        session.getTransaction().commit();
+        return result;
+    }]]></programlisting>
 
-    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-
-    session.beginTransaction();
-
-    List result = session.createQuery("from Event").list();
-
-    session.getTransaction().commit();
-
-    return result;
-}]]></programlisting>
-
             <para>
-                Use an HQL (Hibernate Query Language) query to load all existing
+                Here, we are using a Hibernate Query Language (HQL) query to load all existing
                 <literal>Event</literal> objects from the database. Hibernate will generate the
                 appropriate SQL, send it to the database and populate <literal>Event</literal> objects
-                with the data. You can create more complex queries with HQL.
+                with the data. You can create more complex queries with HQL. See <xref linkend="query-hql"/>
+                for more information.
             </para>
 
             <para>
-                To execute and test all of this, follow these steps:
+                Now we can call our new functionality, again using the Maven exec plugin:
+                <command>mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="list"</command>
             </para>
 
-            <itemizedlist>
-                <listitem>
-                    <para>
-                        Run <literal>ant run -Daction=store</literal> to store something in the database
-                        and, of course, to generate the database schema before through hbm2ddl.
-                    </para>
-                </listitem>
-                <listitem>
-                    <para>
-                        Disable hbm2ddl by commenting out the property in your <literal>hibernate.cfg.xml</literal>
-                        file. It is only turned on in continuous unit testing.  Another
-                        run of hbm2ddl would <emphasis>drop</emphasis> everything you have stored. The
-                        <literal>create</literal> configuration setting translates into "drop all
-                        tables from the schema, then re-create all tables, when the SessionFactory is built".
-                    </para>
-                </listitem>
-            </itemizedlist>
-
-            <para>
-                If you can call Ant with <literal>-Daction=list</literal>, you will be able to view the events
-                you have stored so far. You can also call the <literal>store</literal> action.
-            </para>
-
-            <para>
-                Most new Hibernate users fail at this point and we regularly receive questions relating to
-                <emphasis>Table not found</emphasis> error messages. However, if you follow the
-                steps outlined above you will not have this problem, as hbm2ddl creates the database
-                schema on the first run, and subsequent application restarts will use this schema. If
-                you change the mapping and/or database schema, you will have to re-enable hbm2ddl.
-            </para>
-
         </sect2>
 
     </sect1>
@@ -860,8 +863,10 @@
         <title>Part 2 - Mapping associations</title>
 
         <para>
-            You have mapped a persistent entity class to a table. You can now build on this by adding some class associations.
-            First you will add people to your application, and store a list of events they participate in.
+            So far we have mapped a single persistent entity class to a table in
+            isolation.  Let's expand on that a bit and add some class associations.
+            We will add people to the application and store a list of events in
+            which they participate.
         </para>
 
         <sect2 id="tutorial-associations-mappinguser" revision="1">
@@ -871,7 +876,7 @@
                 The first cut of the <literal>Person</literal> class looks like this:
             </para>
 
-            <programlisting><![CDATA[package events;
+            <programlisting><![CDATA[package org.hibernate.tutorial.domain;
 
 public class Person {
 
@@ -887,13 +892,18 @@
 }]]></programlisting>
 
             <para>
-                Create a new mapping file called <literal>Person.hbm.xml</literal>. Do not forget the
-                DTD reference at the top:
+                Save this to a file named
+                <filename>src/main/java/org/hibernate/tutorial/domain/Person.java</filename>
             </para>
 
-            <programlisting><![CDATA[<hibernate-mapping>
+            <para>
+                Next, create the new mapping file as
+                <filename>src/main/resources/org/hibernate/tutorial/domain/Person.hbm.xml</filename>
+            </para>
 
-    <class name="events.Person" table="PERSON">
+            <programlisting><![CDATA[<hibernate-mapping package="org.hibernate.tutorial.domain">
+
+    <class name="Person" table="PERSON">
         <id name="id" column="PERSON_ID">
             <generator class="native"/>
         </id>
@@ -924,17 +934,16 @@
             <title>A unidirectional Set-based association</title>
 
             <para>
-                By adding a collection of events to the <literal>Person</literal> class, you can
-                easily navigate to the events for a particular person, without executing an explicit query -
-                by calling <literal>aPerson.getEvents()</literal>. A Java collection, a <literal>Set</literal>, is used
-                because the collection will not contain duplicate elements and the ordering is not relevant to our examples.
+                By adding a collection of events to the <literal>Person</literal>
+                class, you can easily navigate to the events for a particular person,
+                without executing an explicit query - by calling
+                <literal>Person#getEvents</literal>.  Multi-valued associations
+                are represented in Hibernate by one of the Java Collection Framework
+                contracts; here we choose a <interfacename>java.util.Set</interfacename>
+                because the collection will not contain duplicate elements and the ordering
+                is not relevant to our examples:
             </para>
 
-            <para>
-                We need unidirectional, many-valued associations, implemented with a <literal>Set</literal>.
-                Write the code for this in the Java classes and then map it:
-            </para>
-
             <programlisting><![CDATA[public class Person {
 
     private Set events = new HashSet();
@@ -949,17 +958,19 @@
 }]]></programlisting>
 
             <para>
-                Before you map this association, consider the other side. You could just keep this
-                unidirectional. Or, you could create another collection on the <literal>Event</literal>, if you
-                want to be able to navigate it bi-directional, i.e., <literal>anEvent.getParticipants()</literal>.
-                This is not necessary, from a functional perspective. You can always execute an explicit query
-                to retrieve the participants for a particular event. This is a design choice left to you, but what
-                is clear from this discussion is the multiplicity of the association: "many" valued on both sides
-                is called a <emphasis>many-to-many</emphasis> association. Hence, we use Hibernate's
-                many-to-many mapping:
+                Before mapping this association, let's consider the other side.
+                We could just keep this unidirectional or create another
+                collection on the <literal>Event</literal>, if we wanted to be
+                able to navigate it from both directions.  This is not necessary,
+                from a functional perspective. You can always execute an explicit
+                query to retrieve the participants for a particular event.  This
+                is a design choice left to you, but what is clear from this
+                discussion is the multiplicity of the association: "many" valued
+                on both sides is called a <emphasis>many-to-many</emphasis>
+                association. Hence, we use Hibernate's many-to-many mapping:
             </para>
 
-            <programlisting><![CDATA[<class name="events.Person" table="PERSON">
+            <programlisting><![CDATA[<class name="Person" table="PERSON">
     <id name="id" column="PERSON_ID">
         <generator class="native"/>
     </id>
@@ -969,20 +980,24 @@
 
     <set name="events" table="PERSON_EVENT">
         <key column="PERSON_ID"/>
-        <many-to-many column="EVENT_ID" class="events.Event"/>
+        <many-to-many column="EVENT_ID" class="Event"/>
     </set>
 
 </class>]]></programlisting>
 
             <para>
-                Hibernate supports a broad range of collection mappings, a <literal>&lt;set&gt;</literal> being most
-                common. For a many-to-many association, or <emphasis>n:m</emphasis> entity relationship, an
-                association table is required. Each row in this table represents a link between a person and an event.
-                The table name is configured with the <literal>table</literal> attribute of the <literal>set</literal>
-                element. The identifier column name in the association, for the person side, is defined with the
-                <literal>&lt;key&gt;</literal> element, the column name for the event's side with the
-                <literal>column</literal> attribute of the <literal>&lt;many-to-many&gt;</literal>. You also
-                have to tell Hibernate the class of the objects in your collection (the class on the
+                Hibernate supports a broad range of collection mappings, a
+                <literal>set</literal> being most common.  For a many-to-many
+                association, or <emphasis>n:m</emphasis> entity relationship, an
+                association table is required.  Each row in this table represents
+                a link between a person and an event.  The table name is
+                decalred using the <literal>table</literal> attribute of the
+                <literal>set</literal> element.  The identifier column name in
+                the association, for the person side, is defined with the
+                <literal>key</literal> element, the column name for the event's
+                side with the <literal>column</literal> attribute of the
+                <literal>many-to-many</literal>. You also have to tell Hibernate
+                the class of the objects in your collection (the class on the
                 other side of the collection of references).
             </para>
 
@@ -1013,73 +1028,77 @@
                 Now we will bring some people and events together in a new method in <literal>EventManager</literal>:
             </para>
 
-            <programlisting><![CDATA[private void addPersonToEvent(Long personId, Long eventId) {
+            <programlisting><![CDATA[    private void addPersonToEvent(Long personId, Long eventId) {
+        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+        session.beginTransaction();
 
-    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-    session.beginTransaction();
+        Person aPerson = (Person) session.load(Person.class, personId);
+        Event anEvent = (Event) session.load(Event.class, eventId);
+        aPerson.getEvents().add(anEvent);
 
-    Person aPerson = (Person) session.load(Person.class, personId);
-    Event anEvent = (Event) session.load(Event.class, eventId);
+        session.getTransaction().commit();
+    }]]></programlisting>
 
-    aPerson.getEvents().add(anEvent);
-
-    session.getTransaction().commit();
-}]]></programlisting>
-
             <para>
-                After loading a <literal>Person</literal> and an <literal>Event</literal>, simply
-                modify the collection using the normal collection methods. There is no explicit call
-                to <literal>update()</literal> or <literal>save()</literal>; Hibernate automatically
-                detects that the collection has been modified and needs to be updated. This is called <emphasis>automatic
-                dirty checking</emphasis>. You can also try it by modifying the name or the date property of
-                any of your objects. As long as they are in <emphasis>persistent</emphasis> state, that is, bound
-                to a particular Hibernate <literal>Session</literal> (i.e. they have been just loaded or saved in
-                a unit of work), Hibernate monitors any changes and executes SQL in a write-behind fashion. The
-                process of synchronizing the memory state with the database, usually only at the end of a unit of
-                work, is called <emphasis>flushing</emphasis>. In our code, the unit of work ends with a commit,
-                or rollback, of the database transaction. This is defined by the <literal>thread</literal> configuration
-                option for the <literal>CurrentSessionContext</literal> class.
+                After loading a <literal>Person</literal> and an
+                <literal>Event</literal>, simply modify the collection using the
+                normal collection methods. There is no explicit call to
+                <literal>update()</literal> or <literal>save()</literal>;
+                Hibernate automatically detects that the collection has been modified
+                and needs to be updated. This is called
+                <emphasis>automatic dirty checking</emphasis>. You can also try
+                it by modifying the name or the date property of any of your
+                objects.  As long as they are in <emphasis>persistent</emphasis>
+                state, that is, bound to a particular Hibernate
+                <interfacename>org.hibernate.Session</interfacename>, Hibernate
+                monitors any changes and executes SQL in a write-behind fashion.
+                The process of synchronizing the memory state with the database,
+                usually only at the end of a unit of work, is called
+                <emphasis>flushing</emphasis>.  In our code, the unit of work
+                ends with a commit, or rollback, of the database transaction.
             </para>
 
             <para>
-                You can load person and event in different units of work. Or you can modify an object
-                outside of a <literal>Session</literal>, when it is not in persistent state (if it was persistent
-                before, this state is called <emphasis>detached</emphasis>). You can even modify a collection when
-                it is detached:
+                You can load person and event in different units of work.  Or
+                you can modify an object outside of a
+                <interfacename>org.hibernate.Session</interfacename>, when it
+                is not in persistent state (if it was persistent before, this
+                state is called <emphasis>detached</emphasis>).  You can even
+                modify a collection when it is detached:
             </para>
 
-            <programlisting><![CDATA[private void addPersonToEvent(Long personId, Long eventId) {
+            <programlisting><![CDATA[    private void addPersonToEvent(Long personId, Long eventId) {
+        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+        session.beginTransaction();
 
-    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-    session.beginTransaction();
+        Person aPerson = (Person) session
+                .createQuery("select p from Person p left join fetch p.events where p.id = :pid")
+                .setParameter("pid", personId)
+                .uniqueResult(); // Eager fetch the collection so we can use it detached
+        Event anEvent = (Event) session.load(Event.class, eventId);
 
-    Person aPerson = (Person) session
-            .createQuery("select p from Person p left join fetch p.events where p.id = :pid")
-            .setParameter("pid", personId)
-            .uniqueResult(); // Eager fetch the collection so we can use it detached
+        session.getTransaction().commit();
 
-    Event anEvent = (Event) session.load(Event.class, eventId);
+        // End of first unit of work
 
-    session.getTransaction().commit();
+        aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached
 
-    // End of first unit of work
+        // Begin second unit of work
 
-    aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached
+        Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
+        session2.beginTransaction();
+        session2.update(aPerson); // Reattachment of aPerson
 
-    // Begin second unit of work
+        session2.getTransaction().commit();
+    }]]></programlisting>
 
-    Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
-    session2.beginTransaction();
-
-    session2.update(aPerson); // Reattachment of aPerson
-
-    session2.getTransaction().commit();
-}]]></programlisting>
-
             <para>
-                The call to <literal>update</literal> makes a detached object persistent again by binding it to a new unit of work, so any modifications you made to it while detached
-                can be saved to the database. This includes any modifications (additions/deletions) you
-                made to a collection of that entity object.
+                The call to <literal>update</literal> makes a detached object
+                persistent again by binding it to a new unit of work, so any
+                modifications you made to it while detached can be saved to
+                the database. This includes any modifications
+                (additions/deletions) you made to a collection of that entity
+                object.
             </para>
 
             <para>
@@ -1090,29 +1109,35 @@
                 returns it (you might have to modify some of the previous methods to return that identifier):
             </para>
 
-            <programlisting><![CDATA[else if (args[0].equals("addpersontoevent")) {
-    Long eventId = mgr.createAndStoreEvent("My Event", new Date());
-    Long personId = mgr.createAndStorePerson("Foo", "Bar");
-    mgr.addPersonToEvent(personId, eventId);
-    System.out.println("Added person " + personId + " to event " + eventId);
-}]]></programlisting>
+            <programlisting><![CDATA[        else if (args[0].equals("addpersontoevent")) {
+            Long eventId = mgr.createAndStoreEvent("My Event", new Date());
+            Long personId = mgr.createAndStorePerson("Foo", "Bar");
+            mgr.addPersonToEvent(personId, eventId);
+            System.out.println("Added person " + personId + " to event " + eventId);
+        }]]></programlisting>
 
             <para>
-                This is an example of an association between two equally important classes, two entities.
-                As mentioned earlier, there are other classes and types in a typical model, usually "less
-                important". Some you have already seen, like an <literal>int</literal> or a <literal>String</literal>.
-                We call these classes <emphasis>value types</emphasis>, and their instances <emphasis>depend</emphasis>
-                on a particular entity. Instances of these types do not have their own identity, nor are they
-                shared between entities. Two persons do not reference the same <literal>firstname</literal>
-                object, even if they have the same first name. Value types cannot only be found in
-                the JDK , but
-                you can also write dependent classes yourself (<literal>Address</literal> or <literal>MonetaryAmount</literal>,
-                for example). In fact, in a Hibernate application all JDK classes are considered value types.
+                This is an example of an association between two equally important
+                classes : two entities.  As mentioned earlier, there are other
+                classes and types in a typical model, usually "less important".
+                Some you have already seen, like an <literal>int</literal> or a
+                <classname>java.lang.String</classname>.  We call these classes
+                <emphasis>value types</emphasis>, and their instances
+                <emphasis>depend</emphasis> on a particular entity.  Instances of
+                these types do not have their own identity, nor are they shared
+                between entities.  Two persons do not reference the same
+                <literal>firstname</literal> object, even if they have the same
+                first name.  Value types cannot only be found in the JDK , but
+                you can also write dependent classes yourself
+                such as an <literal>Address</literal> or
+                <literal>MonetaryAmount</literal> class.  In fact, in a Hibernate
+                application all JDK classes are considered value types.
             </para>
 
             <para>
-                You can also design a collection of value types. This is conceptually different from a
-                collection of references to other entities, but looks almost the same in Java.
+                You can also design a collection of value types.  This is
+                conceptually different from a collection of references to other
+                entities, but looks almost the same in Java.
             </para>
 
         </sect2>
@@ -1121,37 +1146,44 @@
             <title>Collection of values</title>
 
             <para>
-                You can add a collection of value typed objects to the <literal>Person</literal> entity. If you want to
-                store email addresses, the type you use is <literal>String</literal>, and the collection is
-                again a <literal>Set</literal>:
+                Let's add a collection of email addresses to the
+                <literal>Person</literal> entity.  This will be represented as a
+                <interfacename>java.util.Set</interfacename> of
+                <classname>java.lang.String</classname> instances:
             </para>
-            <programlisting><![CDATA[private Set emailAddresses = new HashSet();
+            <programlisting><![CDATA[    private Set emailAddresses = new HashSet();
 
-public Set getEmailAddresses() {
-    return emailAddresses;
-}
+    public Set getEmailAddresses() {
+        return emailAddresses;
+    }
 
-public void setEmailAddresses(Set emailAddresses) {
-    this.emailAddresses = emailAddresses;
-}]]></programlisting>
+    public void setEmailAddresses(Set emailAddresses) {
+        this.emailAddresses = emailAddresses;
+    }]]></programlisting>
 
             <para>
                 The mapping of this <literal>Set</literal> is as follows:
             </para>
 
-            <programlisting><![CDATA[<set name="emailAddresses" table="PERSON_EMAIL_ADDR">
-    <key column="PERSON_ID"/>
-    <element type="string" column="EMAIL_ADDR"/>
-</set>]]></programlisting>
+            <programlisting><![CDATA[        <set name="emailAddresses" table="PERSON_EMAIL_ADDR">
+            <key column="PERSON_ID"/>
+            <element type="string" column="EMAIL_ADDR"/>
+        </set>]]></programlisting>
 
             <para>
-                The difference compared with the earlier mapping is the <literal>element</literal> part which tells Hibernate that the collection
-                does not contain references to another entity, but a collection of elements of type
-                <literal>String</literal>. The lowercase name tells you it is a Hibernate mapping type/converter.
-                Again the <literal>table</literal> attribute of the <literal>set</literal> element determines
-                the table name for the collection. The <literal>key</literal> element defines the foreign-key column
-                name in the collection table. The <literal>column</literal> attribute in the <literal>element</literal>
-                element defines the column name where the <literal>String</literal> values will actually be stored.
+                The difference compared with the earlier mapping is the use of
+                the <literal>element</literal> part which tells Hibernate that the
+                collection does not contain references to another entity, but is
+                rather a collection whose elements are values types, here specifically
+                of type <literal>string</literal>.  The lowercase name tells you
+                it is a Hibernate mapping type/converter.  Again the
+                <literal>table</literal> attribute of the <literal>set</literal>
+                element determines the table name for the collection.   The
+                <literal>key</literal> element defines the foreign-key column
+                name in the collection table. The <literal>column</literal>
+                attribute in the <literal>element</literal> element defines the
+                column name where the email address values will actually
+                be stored.
             </para>
 
             <para>
@@ -1183,24 +1215,21 @@
                 linking persons and events. It is the same code in Java:
             </para>
 
-            <programlisting><![CDATA[private void addEmailToPerson(Long personId, String emailAddress) {
+            <programlisting><![CDATA[    private void addEmailToPerson(Long personId, String emailAddress) {
+        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+        session.beginTransaction();
 
-    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
-    session.beginTransaction();
+        Person aPerson = (Person) session.load(Person.class, personId);
+        // adding to the emailAddress collection might trigger a lazy load of the collection
+        aPerson.getEmailAddresses().add(emailAddress);
 
-    Person aPerson = (Person) session.load(Person.class, personId);
+        session.getTransaction().commit();
+    }]]></programlisting>
 
-    // The getEmailAddresses() might trigger a lazy load of the collection
-    aPerson.getEmailAddresses().add(emailAddress);
-
-    session.getTransaction().commit();
-}]]></programlisting>
-
             <para>
-                This time we did not use a <emphasis>fetch</emphasis> query to initialize the collection.
-                Hence, the call to its getter method will trigger an additional select to initialize
-                it, so we can add an element to it. Monitor the SQL log and try to optimize this with
-                an eager fetch.
+                This time we did not use a <emphasis>fetch</emphasis> query to
+                initialize the collection.  Monitor the SQL log and try to
+                optimize this with an eager fetch.
             </para>
 
         </sect2>
@@ -1209,35 +1238,44 @@
             <title>Bi-directional associations</title>
 
             <para>
-                Next you will map a bi-directional association. You will make the association between
-                person and event work from both sides in Java. The database schema does not
-                change, so you will still have many-to-many multiplicity. A relational database is more flexible
-                than a network programming language, so it does not need a navigation
-                direction; data can be viewed and retrieved in any possible way.
+                Next you will map a bi-directional association.  You will make
+                the association between person and event work from both sides
+                in Java.  The database schema does not change, so you will still
+                have many-to-many multiplicity.
             </para>
 
+            <note>
+                <para>
+                    A relational database is more flexible than a network
+                    programming language, in that it does not need a navigation
+                    direction; data can be viewed and retrieved in any possible
+                    way.
+                </para>
+            </note>
+
             <para>
-                First, add a collection of participants to the <literal>Event</literal> Event class:
+                First, add a collection of participants to the
+                <literal>Event</literal> class:
             </para>
 
-            <programlisting><![CDATA[private Set participants = new HashSet();
+            <programlisting><![CDATA[    private Set participants = new HashSet();
 
-public Set getParticipants() {
-    return participants;
-}
+    public Set getParticipants() {
+        return participants;
+    }
 
-public void setParticipants(Set participants) {
-    this.participants = participants;
-}]]></programlisting>
+    public void setParticipants(Set participants) {
+        this.participants = participants;
+    }]]></programlisting>
 
             <para>
                 Now map this side of the association in <literal>Event.hbm.xml</literal>.
             </para>
 
-            <programlisting><![CDATA[<set name="participants" table="PERSON_EVENT" inverse="true">
-    <key column="EVENT_ID"/>
-    <many-to-many column="PERSON_ID" class="events.Person"/>
-</set>]]></programlisting>
+            <programlisting><![CDATA[        <set name="participants" table="PERSON_EVENT" inverse="true">
+            <key column="EVENT_ID"/>
+            <many-to-many column="PERSON_ID" class="events.Person"/>
+        </set>]]></programlisting>
 
             <para>
                 These are normal <literal>set</literal> mappings in both mapping documents.
@@ -1273,23 +1311,23 @@
                 correctly set both sides (for example, in <literal>Person</literal>):
             </para>
 
-            <programlisting><![CDATA[protected Set getEvents() {
-    return events;
-}
+            <programlisting><![CDATA[    protected Set getEvents() {
+        return events;
+    }
 
-protected void setEvents(Set events) {
-    this.events = events;
-}
+    protected void setEvents(Set events) {
+        this.events = events;
+    }
 
-public void addToEvent(Event event) {
-    this.getEvents().add(event);
-    event.getParticipants().add(this);
-}
+    public void addToEvent(Event event) {
+        this.getEvents().add(event);
+        event.getParticipants().add(this);
+    }
 
-public void removeFromEvent(Event event) {
-    this.getEvents().remove(event);
-    event.getParticipants().remove(this);
-}]]></programlisting>
+    public void removeFromEvent(Event event) {
+        this.getEvents().remove(event);
+        event.getParticipants().remove(this);
+    }]]></programlisting>
 
             <para>
                 The get and set methods for the collection are now protected. This allows classes in the
@@ -1309,7 +1347,6 @@
                 and in many-to-many association you can select either side.
             </para>
 
-	<para>In the next section we will turn this into a small web application.</para>
         </sect2>
 
     </sect1>
@@ -1328,50 +1365,51 @@
             <title>Writing the basic servlet</title>
 
             <para>
-                Create a new class in your source directory in the <literal>events</literal>
-                package:
+                First we need create our basic processing servlet.  Since our
+                servlet only handles HTTP <literal>GET</literal> requests, we
+                will only implement the <literal>doGet()</literal> method:
             </para>
 
-            <programlisting><![CDATA[package events;
+            <programlisting><![CDATA[package org.hibernate.tutorial.web;
 
 // Imports
 
 public class EventManagerServlet extends HttpServlet {
 
-    // Servlet code
-}]]></programlisting>
+    protected void doGet(
+            HttpServletRequest request,
+            HttpServletResponse response) throws ServletException, IOException {
 
-            <para>
-                The servlet handles HTTP <literal>GET</literal> requests only. It is for this reason that the method
-                we implement is <literal>doGet()</literal>:
-            </para>
+        SimpleDateFormat dateFormatter = new SimpleDateFormat( "dd.MM.yyyy" );
 
-            <programlisting><![CDATA[protected void doGet(HttpServletRequest request,
-                     HttpServletResponse response)
-        throws ServletException, IOException {
+        try {
+            // Begin unit of work
+            HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
 
-    SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");
+            // Process request and render page...
 
-    try {
-        // Begin unit of work
-        HibernateUtil.getSessionFactory()
-                .getCurrentSession().beginTransaction();
-
-        // Process request and render page...
-
-        // End unit of work
-        HibernateUtil.getSessionFactory()
-                .getCurrentSession().getTransaction().commit();
-
-    } catch (Exception ex) {
-        HibernateUtil.getSessionFactory()
-                .getCurrentSession().getTransaction().rollback();
-        throw new ServletException(ex);
+            // End unit of work
+            HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
+        }
+        catch (Exception ex) {
+            HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();
+            if ( ServletException.class.isInstance( ex ) ) {
+                throw ( ServletException ) ex;
+            }
+            else {
+                throw new ServletException( ex );
+            }
+        }
     }
 
 }]]></programlisting>
 
             <para>
+                Save this servlet as
+                <filename>src/main/java/org/hibernate/tutorial/web/EventManagerServlet.java</filename>
+            </para>
+
+            <para>
                 The pattern applied here is called <emphasis>session-per-request</emphasis>.
                 When a request hits the servlet, a new Hibernate <literal>Session</literal> is
                 opened through the first call to <literal>getCurrentSession()</literal> on the
@@ -1412,32 +1450,33 @@
                 Now you can implement the processing of the request and the rendering of the page.
             </para>
 
-<programlisting><![CDATA[// Write HTML header
-PrintWriter out = response.getWriter();
-out.println("<html><head><title>Event Manager</title></head><body>");
+<programlisting><![CDATA[        // Write HTML header
+        PrintWriter out = response.getWriter();
+        out.println("<html><head><title>Event Manager</title></head><body>");
 
-// Handle actions
-if ( "store".equals(request.getParameter("action")) ) {
+        // Handle actions
+        if ( "store".equals(request.getParameter("action")) ) {
 
-    String eventTitle = request.getParameter("eventTitle");
-    String eventDate = request.getParameter("eventDate");
+            String eventTitle = request.getParameter("eventTitle");
+            String eventDate = request.getParameter("eventDate");
 
-    if ( "".equals(eventTitle) || "".equals(eventDate) ) {
-        out.println("<b><i>Please enter event title and date.</i></b>");
-    } else {
-        createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate));
-        out.println("<b><i>Added event.</i></b>");
-    }
-}
+            if ( "".equals(eventTitle) || "".equals(eventDate) ) {
+                out.println("<b><i>Please enter event title and date.</i></b>");
+            }
+            else {
+                createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate));
+                out.println("<b><i>Added event.</i></b>");
+            }
+        }
 
-// Print page
-printEventForm(out);
-listEvents(out, dateFormatter);
+        // Print page
+       printEventForm(out);
+       listEvents(out, dateFormatter);
 
-// Write HTML footer
-out.println("</body></html>");
-out.flush();
-out.close();]]></programlisting>
+       // Write HTML footer
+       out.println("</body></html>");
+       out.flush();
+       out.close();]]></programlisting>
 
             <para>
                 This coding style, with a mix of Java and HTML, would not scale
@@ -1448,14 +1487,14 @@
                 trivial and only outputs HTML:
             </para>
 
-            <programlisting><![CDATA[private void printEventForm(PrintWriter out) {
-    out.println("<h2>Add new event:</h2>");
-    out.println("<form>");
-    out.println("Title: <input name='eventTitle' length='50'/><br/>");
-    out.println("Date (e.g. 24.12.2009): <input name='eventDate' length='10'/><br/>");
-    out.println("<input type='submit' name='action' value='store'/>");
-    out.println("</form>");
-}]]></programlisting>
+            <programlisting><![CDATA[    private void printEventForm(PrintWriter out) {
+        out.println("<h2>Add new event:</h2>");
+        out.println("<form>");
+        out.println("Title: <input name='eventTitle' length='50'/><br/>");
+        out.println("Date (e.g. 24.12.2009): <input name='eventDate' length='10'/><br/>");
+        out.println("<input type='submit' name='action' value='store'/>");
+        out.println("</form>");
+    }]]></programlisting>
 
             <para>
                 The <literal>listEvents()</literal> method uses the Hibernate
@@ -1463,27 +1502,28 @@
                 a query:
             </para>
 
-            <programlisting><![CDATA[private void listEvents(PrintWriter out, SimpleDateFormat dateFormatter) {
+            <programlisting><![CDATA[    private void listEvents(PrintWriter out, SimpleDateFormat dateFormatter) {
 
-    List result = HibernateUtil.getSessionFactory()
-                    .getCurrentSession().createCriteria(Event.class).list();
-    if (result.size() > 0) {
-        out.println("<h2>Events in database:</h2>");
-        out.println("<table border='1'>");
-        out.println("<tr>");
-        out.println("<th>Event title</th>");
-        out.println("<th>Event date</th>");
-        out.println("</tr>");
-        for (Iterator it = result.iterator(); it.hasNext();) {
-            Event event = (Event) it.next();
+        List result = HibernateUtil.getSessionFactory()
+                .getCurrentSession().createCriteria(Event.class).list();
+        if (result.size() > 0) {
+            out.println("<h2>Events in database:</h2>");
+            out.println("<table border='1'>");
             out.println("<tr>");
-            out.println("<td>" + event.getTitle() + "</td>");
-            out.println("<td>" + dateFormatter.format(event.getDate()) + "</td>");
+            out.println("<th>Event title</th>");
+            out.println("<th>Event date</th>");
             out.println("</tr>");
+            Iterator it = result.iterator();
+            while (it.hasNext()) {
+                Event event = (Event) it.next();
+                out.println("<tr>");
+                out.println("<td>" + event.getTitle() + "</td>");
+                out.println("<td>" + dateFormatter.format(event.getDate()) + "</td>");
+                out.println("</tr>");
+            }
+            out.println("</table>");
         }
-        out.println("</table>");
-    }
-}]]></programlisting>
+    }]]></programlisting>
 
             <para>
                 Finally, the <literal>store</literal> action is dispatched to the
@@ -1491,14 +1531,14 @@
                 the <literal>Session</literal> of the current thread:
             </para>
 
-            <programlisting><![CDATA[protected void createAndStoreEvent(String title, Date theDate) {
-    Event theEvent = new Event();
-    theEvent.setTitle(title);
-    theEvent.setDate(theDate);
+            <programlisting><![CDATA[    protected void createAndStoreEvent(String title, Date theDate) {
+        Event theEvent = new Event();
+        theEvent.setTitle(title);
+        theEvent.setDate(theDate);
 
-    HibernateUtil.getSessionFactory()
-                    .getCurrentSession().save(theEvent);
-}]]></programlisting>
+        HibernateUtil.getSessionFactory()
+                .getCurrentSession().save(theEvent);
+    }]]></programlisting>
 
             <para>
                 The servlet is now complete. A request to the servlet will be processed
@@ -1517,26 +1557,11 @@
             <title>Deploying and testing</title>
 
             <para>
-                To deploy this application you have to create a web archive, or what is known as a WAR. Add the
-                following Ant target to your <literal>build.xml</literal>:
+                To deploy this application for testing we must create a
+                Web ARchive (WAR).  First we must define the WAR descriptor
+                as <filename>src/main/webapp/WEB-INF/web.xml</filename>
             </para>
 
-<programlisting><![CDATA[<target name="war" depends="compile">
-    <war destfile="hibernate-tutorial.war" webxml="web.xml">
-        <lib dir="${librarydir}">
-          <exclude name="jsdk*.jar"/>
-        </lib>
-
-        <classes dir="${targetdir}"/>
-    </war>
-</target>]]></programlisting>
-
-            <para>
-                This target creates a file called <literal>hibernate-tutorial.war</literal>
-                in your project directory. It packages all libraries and the <literal>web.xml</literal>
-                descriptor, which is expected in the base directory of your project:
-            </para>
-
             <programlisting><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
 <web-app version="2.4"
     xmlns="http://java.sun.com/xml/ns/j2ee"
@@ -1545,7 +1570,7 @@
 
     <servlet>
         <servlet-name>Event Manager</servlet-name>
-        <servlet-class>events.EventManagerServlet</servlet-class>
+        <servlet-class>org.hibernate.tutorial.web.EventManagerServlet</servlet-class>
     </servlet>
 
     <servlet-mapping>
@@ -1555,20 +1580,19 @@
 </web-app>]]></programlisting>
 
             <para>
-                Before you compile and deploy the web application, an additional library
-                is required: <literal>jsdk.jar</literal>. This is the Java servlet development kit.
-                If you do not have this library already, get it from the Sun website and copy it to
-                your library directory. However, it will be only used for compilation and excluded
-                from the WAR package.
+                To build and deploy call <literal>mvn package</literal> in your
+                project directory and copy the <filename>hibernate-tutorial.war</filename>
+                file into your Tomcat <filename>webapps</filename> directory.
             </para>
 
-            <para>
-                To build and deploy call <literal>ant war</literal> in your project directory
-                and copy the <literal>hibernate-tutorial.war</literal> file into your Tomcat
-                <literal>webapp</literal> directory. If you do not have Tomcat installed, download
-                it and follow the installation instructions. You do not have to change any Tomcat
-                configuration to deploy this application though.
-            </para>
+            <note>
+                <para>
+                    If you do not have Tomcat installed, download it from
+                    <ulink url="http://tomcat.apache.org/"/> and follow the
+                    installation instructions.  Our application requires
+                    no changes to the standard Tomcat configuration.
+                </para>
+            </note>
 
             <para>
                 Once deployed and Tomcat is running, access the application at
@@ -1587,21 +1611,10 @@
 
         <para>
             This tutorial covered the basics of writing a simple standalone Hibernate application
-            and a small web application.
+            and a small web application.  More tutorials are available from the Hibernate
+            <ulink url="http://hibernate.org">website</ulink>.
         </para>
 
-        <para>
-            If you already feel confident with Hibernate, continue browsing through the reference
-            documentation table of contents for topics you find interesting. The most popular are
-            transactional processing (<xref linkend="transactions"/>), fetch
-            performance (<xref linkend="performance"/>), or the usage of the API (<xref linkend="objectstate"/>)
-            and the query features (<xref linkend="objectstate-querying"/>).
-        </para>
-
-        <para>
-            More tutorials are available from the Hibernate website.
-        </para>
-
     </sect1>
 
 </chapter>




More information about the hibernate-commits mailing list