Chapter 9. Using Hibernate

Hibernate is a popular persistence engine that provides a simple, yet powerful, alternative to using standard entity beans. Hibernate runs in almost any application server, or even outside of an application server completely. However, when running inside of JBoss, you can choose to deploy your application as a Hibernate archive, called a HAR file, and make Hibernate's simple usage even simpler. JBoss can manage your Hibernate session and other configuration details, allowing you to use Hibernate objects with minimal setup.

In this chapter, we will return the CMP roster application from Chapter 7, Container-Managed Persistence and show how to access the roster database tables with Hibernate. We'll demonstrate how to create a HAR file to package your Hibernate objects, and then we'll show how to access them from a web application in a WAR file. The entire project will be bundled in an EAR file, just like all of our previous examples.

The code for this section is in the examples/hibernate directory. However, the Hibernate example here is intended to be run along side of the CMP roster application in Chapter 7, Container-Managed Persistence. If you don't have the roster application deployed, go back and follow the instructions there. Make sure that you follow the instructions for creating the database schema and populating the database. We will be using the schema and data from that task.

Also, please keep in mind that we'll only be looking at the steps required to deploy a Hibernate application in JBoss. If you need a more general guide to Hibernate, we recommend Hibernate in Action by Christian Bauer and Gavin King (Manning, 2004).

9.1. Creating a Hibernate archive

The Hibernate portion of the application consists of a single Java class, org.jboss.roster.Player, that maps onto the PlayerBean entity bean from the CMP roster application. The Player object is a simple POJO object with no direct coupling to Hibernate. The details of the Hibernate mapping are specified in the Player.hbm.xml file, shown below.

<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    <class name="org.jboss.roster.Player" table="PlayerBean">
       <id name="id" type="string" column="playerID"> 
           <generator class="assigned" />

       <property name="position" type="string" column="POS"    />
       <property name="name"     type="string" column="name"   />
       <property name="salary"   type="float"  column="salary" />

In addition to the Player object and its mapping file, we also need to provide a hibernate-service.xml file that creates an MBean that will manage the Hibernate configuration. The following is the hibernate-service.xml files we are using.

    <mbean code="org.jboss.hibernate.jmx.Hibernate" 
        <attribute name="DatasourceName">java:/DefaultDS</attribute>
        <attribute name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>
        <attribute name="SessionFactoryName">java:/hibernate/SessionFactory</attribute>
        <attribute name="CacheProviderClass">
        <!-- <attribute name="Hbm2ddlAuto">create-drop</attribute> -->

This configuration information should be familiar to any Hibernate user. The JBoss specific details are the mapping to our java:/DefaultDS and the JNDI location where we want our Hibernate SessionFactory bound.

To compile the project and build the hibernate archive, use the compile and package-har Ant targets.

ant -f jboss-build.xml compile
ant -f jboss-build.xml package-har

The contents of the create HAR file look like the following:

$ jar tf jar/roster.har 

Experienced Hibernate users may be wondering where we've told Hibernate what our persistent objects are. The Hibernate deployer determines the set of persistent objects by searching the HAR file for hibernate mapping files. All hibernate objects found are added to the configuration with no further effort required.

9.2. Using the hibernate objects

By deploying the Hibernate archive, we have created a fully configured SessionFactory for use in other parts of our application. In this example, we have created a simple JSP which creates a Session from the SessionFactory and issues a query directly. Normally it would be preferable to put the Hibernate access code in a servlet or in a session bean, but for example purposes we'll keep the code together in the JSP. For reference, the following code fragment shows how we are accessing the Hibernate session in the JSP.

InitialContext ctx      = new InitialContext();
SessionFactory factory  = (SessionFactory)
Session        hsession = factory.openSession();
try {
    Query query = hsession.createQuery("from org.jboss.roster.Player order by name");
    request.setAttribute("players", query.list());
} finally {

To package the complete web application, use the package-web Ant target.

ant -f jboss-build.xml package-web

This creates roster.war in the jar directory containing our simple web application.

9.3. Packaging the complete application

Next, we need to package the entire application into an EAR file. The assemble Ant target does this.

ant -f jboss-build.xml assemble

This creates the HibernateRoster.ear file. The contents of the EAR file our our roster.har and roster.war files, along with the appropriate deployment descriptors.

$ jar tf jar/HibernateRoster.ear 

Just as we need to declare the WAR file in the application.xml file, we also need to declare the HAR file. However, since Hibernate archives are not a standard J2EE deployment type, we need to declare it in the jboss-app.xml file.

<!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 1.4//EN"

Now our application is ready to be deployed.

9.4. Deploying Running the application

Once the EAR file is created, we need to deploy it using the deploy Ant target. This copies the EAR file to the appropriate JBoss deploy directory.

ant -f jboss-build.xml deploy

The deployed application can be accessed at http://localhost:8080/roster/players.jsp. When the page is loaded, you will see a list of players sorted by name. If you don't see any data, make sure that you have deployed the CMP roster application from Chapter 7, Container-Managed Persistence and run it to populate the tables with the shared player data.