JBoss-Hibernate Integration (Hibernate 2)

- Steve Ebersole, JBoss Inc




As of version 3.2.6{FOOTNOTE RED #1 1}, JBoss comes with built-in support for utilizing Hibernate within application code. This support

is provided by 3 high-level components:

  1. Hibernate MBean - provides deployment, lifecycle, and management support around a Hibernate SessionFactory;

  2. HAR Deployer - defines a Hibernate ARchive as a new deployable unit within JBoss AS;

  3. Session Management - provides transparent management of Hibernate sessions.




Please note that versions integrating Hibernate2 into JBossAS are deprecated, in favor of those

inetgrating Hibernate3.  See JBossHibernate3 for details on that integration.


Hibernate MBean

The Hibernate MBean is responsible for constructing a Hibernate SessionFactory and exposing it through JNDI. It also provides

JMX management capabilities around the deployed SessionFactory such that its configuration can be modified at runtime.





It exposes a number of configuration properties which affect its runtime behaviour. The more important of these include:

  • DatasourceName - the JNDI name of the datasource Hibernate should use;

  • Dialect - the RDBMS dialect;

  • SessionFactoryName - the JNDI name where the constructed SessionFactory should be bound;

  • CacheProviderClass - the Hibernate CacheProvider class to use for its second-level cache.

Check out the javadocs for org.jboss.hibernate.jmx.Hibernate for a complete list of the available configuration properties.





Notice that there is no option to specify the mapping documents to load. That is because the Hibernate MBean is meant to work

in conjuction with the HAR Deployer component and gets this information from there.





As an example of configuring the MBean, here is the configuration used in the unit tests:

<mbean code="org.jboss.hibernate.jmx.Hibernate" name="jboss.har:service=Hibernate">
<attribute name="DatasourceName">java:/DefaultDS</attribute>
<attribute name="~SessionFactoryName">java:/hibernate/~SessionFactory</attribute>
<attribute name="Dialect">net.sf.hibernate.dialect.HSQLDialect</attribute>
<attribute name="CacheProviderClass">net.sf.hibernate.cache.HashtableCacheProvider</attribute>
<attribute name="Hbm2ddlAuto">create-drop</attribute>

<attribute name="ShowSqlEnabled">true</attribute> should be used to show the sql output, instead of the former






HAR Deployer

A Hibernate ARchive (or HAR) includes all the resources needed to deploy one or more Hibernate MBean instances. The archive must end

in a .har extension and contain a meta-inf/hibernate-service.xml which defines the Hibernate MBean(s) to deploy as well all the domain

classes and their mappings. The mappings can occur anywhere in the archive; the classes should maintain package structure. When a HAR

is processed by the HAR Deployer, a Hibernate MBean instance is created based on the HAR's meta-inf/hibernate-service.xml and the

contents of the har (the mappings are processed using Hibernate's Configuration.addJar() method).





A HAR can be deployed stand-alone or as part of an EAR. If included in an EAR, the EAR's meta-inf/jboss-app.xml must define the har

as a module as such:


Note the new <har/> module type used to denote the HAR subdeployment.




Session Management

All applications using Hibernate need to deal with the questions relating to the lifecycle of the Sessions they

obtain from the SessionFactory.  When should the session be opened; how should components throughout the application

obtain the "current" session; how should flushing and closing of the session be handled?





The most common usage pattern for Hibernate in J2EE applications running within an application server is to use the

app server DataSource and TransactionManager capabilities.  Typically a session is opened at the beginning of a

"request" and closed at the end of that "request", and in between the session is bound to the "current context" to be

accessible to application components.





The central piece of the Hibernate Session management component in JBoss is the org.jboss.hibernate.session.HibernateContext

class.  HibernateContext exposes a static method named getSession() taking a String parameter which represents the jndi name

of a SessionFactory.  If there is already a session bound to the "current context" for the given session factory name, then

that session is returned; otherwise, a new session is generated, bound to the "current context", and then returned.





So what constitutes the "current context" for a managed session?  The transaction!  This component uses the org.jboss.tm.TransactionLocal

class to associate a session with the current JTA transaction.  The life of the session is then bound to that of the transaction.  When

the session is bound, a Synchronization is registered with that transaction such that when the transaction is about to end the Hibernate

session can be flushed and closed.





There are two other pieces of functionality available through the HibernateContext class: the ability to handle "unmanaged sessions" and

ability for applications to manage the binding/unbinding of the Hibernate session themselves.





An unmanaged session is a session that is controlled by the HibernateContext, meaning it is not automatically flushed and closed.  The session

is created on the same underlying jdbc connection and thus participates in the same JTA transaction.  This is mostly useful for Hibernate

Interceptor implementations.  The methods supporting this functionality are getUnmanagedSession() and releaseUnmanagedSession().  Check out

the javadocs for more info.





HibernateContext also exposes the methods bind(), unbind(), and prepareSession() to allow applications to manage the lifecycle of the Hibernate

session themselves.  Say you have special requirements for obtaining a Hibernate session such as passing in your own JDBC connection or opening

a session with a session-level Interceptor (the MBean does support SessionFactory-level Interceptors).  Then you can write the code which

generates a session and use these HibernateContext methods to expose this session to your application components; the idea being that no code

changes are needed in your components because they are still just using the HibernateContext.getSession() method.  bind() and unbind() are

pretty self-explanatory; prepareSession() is used to perform the transaction Synchronization registration.  Again, see the javadocs for more info.





The one caveat to note here is that due to the use of the TransactionLocal, the JTA transaction must be started prior to the session being

bound to the HibernateContext.




Why the need to pass the JNDI name to the HibernateContext.getSession() method? The HibernateContext class supports multiple simultaneously

deployed SessionFactories. You need to specify from which of those deployed SessionFactories you want the current session.




Bundling other versions of Hibernate2

-- TODO; should be as simple as bundling the version you want to use within the HAR and utilizing a loader-repository, but this needs

to be tested.




Hibernate2 vs. Hibernate3

See the switching doc regarding switching versions of

Hibernate used in the integration.




{FOOTNOTE RED #1 1} The session management code underwent a drastic change from its initial versions and this wiki page has been updated to reflect those

changes.  However, the old page has been saved off at JBossHibernate-old