Using Hibernate JPA within Glassfish

Glassfish provides TopLink as its default JPA provider.  However it’s possible for applications to instead use Hibernate within a Glassfish deployment.  The challenge is to determine where to install the Hibernate libraries so that the application references Hibernate instead of TopLink.  While googling for an answer I saw several recommendations suggesting that the Hibernate libraries be installed within Glassfish’s server lib directory, thereby in essence removing TopLink and replacing it with Hibernate.

Although installing Hibernate directly within Glassfish’s server lib directory will accomplish the goal, it isn’t the best solution in that this affects every application at a global level.  Instead the following solution scopes the selection of JPA provider to that of an individual application, effectively isolating it so that its architecture choices don’t affect that of other applications.

The solution is to include the Hibernate libraries directly within the application’s EAR as shown in the following image:

Simply including the Hibernate JARs in the same directory as the application’s component WARs won’t work – Glassfish won’t recognize the Hibernate JARs.  Instead we have to store the Hibernate JARs within the EAR’s “lib” directory so that Glassfish loads the Hibernate JARs into the application’s individual classloader.  See the chapter titled “Class Loader Hierarchy” within the Glassfish Application Development Guide for a good explanation of the Glassfish classloader hierarchy.

If you look closely at the above EAR layout you’ll notice that we’ve packaged our application’s persistent object layer  – a separate development project – into its own JAR file (persistence-0.1.0.jar).  By doing so we can use JUnit to verify that the persistence layer works properly separate from the application.  The following image shows a screen snapshot of the persistence project within Eclipse, including the Maven POM file that includes the various Hibernate libraries (click image for full size):

We also have to update the application’s persistence.xml file (shown below).  Line 5 instructs Glassfish that we want to use Hibernate instead of Toplink as the chosen JPA provider.  In line 6 we configure Hibernate to use the JTA-managed data source we installed using the Glassfish admin console.  Line 8 informs Hibernate that we’ve chosen MySQL as our back-end SQL database.  Finally Line 12 ties Hibernate into Glassfish’s container-managed transactions so that the database is rolled back if a transaction fails.  Note that this file is one place where we have to include Glassfish-specific information in our application.

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">

 <persistence-unit name="debatePU" transaction-type="JTA">
 <provider>org.hibernate.ejb.HibernatePersistence</provider>
 <jta-data-source>jdbc/debateDS</jta-data-source>
 <properties>
 <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
 <!-- GLASSFISH SPECIFIC: The following property is necessary for
      deployment within Glassfish.  Note that each application
      server vendor has its own unique value. -->
 <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup" />
 </properties>
 </persistence-unit>

</persistence>

Once we have the persistent object model packaged into a JAR file, the next step is to build the application’s EAR file.  Fortunately there is a Maven setting for easily creating an EAR lib directory to contain the application’s third-party libraries.  The following is the Maven POM file we use to build our application’s EAR.  Of special interest is the setting at the file’s end instructing Maven to build the EAR lib directory.

<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>
 <parent>
 <artifactId>debate</artifactId>
 <groupId>com.snlb.debate</groupId>
 <version>0.1.0</version>
 </parent>
 <groupId>com.snlb.debate</groupId>
 <artifactId>earglassfish</artifactId>
 <version>0.1.0</version>
 <packaging>ear</packaging>
 <dependencies>

 <dependency>
 <groupId>com.snlb.debate</groupId>
 <artifactId>business</artifactId>
 <version>0.1.0</version>
 <type>ejb</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>com.snlb.debate</groupId>
 <artifactId>uibrowser</artifactId>
 <version>0.1.0</version>
 <type>war</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>com.snlb.debate</groupId>
 <artifactId>uiphone</artifactId>
 <version>0.1.0</version>
 <type>war</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>com.snlb.debate</groupId>
 <artifactId>serviceweb</artifactId>
 <version>0.1.0</version>
 <type>war</type>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>com.snlb.debate</groupId>
 <artifactId>servicerest</artifactId>
 <version>0.1.0</version>
 <type>war</type>
 <scope>compile</scope>
 </dependency>

 </dependencies>
 <build>
 <plugins>

 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-ear-plugin</artifactId>
 <version>2.4.2</version>
 <configuration>
 <displayName>Debate</displayName>
 <modules>
 <ejbModule>
 <groupId>com.snlb.debate</groupId>
 <artifactId>business</artifactId>
 </ejbModule>
 <webModule>
 <groupId>com.snlb.debate</groupId>
 <artifactId>uibrowser</artifactId>
 </webModule>
 <webModule>
 <groupId>com.snlb.debate</groupId>
 <artifactId>uiphone</artifactId>
 </webModule>
 <webModule>
 <groupId>com.snlb.debate</groupId>
 <artifactId>serviceweb</artifactId>
 </webModule>
 <webModule>
 <groupId>com.snlb.debate</groupId>
 <artifactId>servicerest</artifactId>
 </webModule>
 </modules>
 <generateApplicationXml>true</generateApplicationXml>
 <!-- The following setting builds the EAR file in a format suitable for Glassfish deployment.
 With this we don't have to copy the libs into Glassfish's appserver lib directory -->
 <defaultLibBundleDir>lib</defaultLibBundleDir>
 </configuration>
 </plugin>

 </plugins>
 </build>
</project>

 

About the Author

Steve Nies is currently serving as the Chief Architect at Geenius, Inc. He has over 20 years of enterprise software development experience and 13 years experience as a Java architect. When not developing Java applications Steve enjoys spending time with his family, swimming, hiking, and building personal robots.
About these ads
This entry was posted in Technology Issues and Solutions. Bookmark the permalink.

One Response to Using Hibernate JPA within Glassfish

  1. Thanks for solution, that works in Glassfish now.
    But I have one problem.
    I hardcode jndi-source in persistence.xml so how can I write unit-test now ?
    In unit test I want to create simple datasource (without jndi) and pass it to EntityManager.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s