Configuring Hibernate to be using in an Enterprise Application based
on J2EE Technology, running on JBoss Application Server 5.0.0 Beta3,
to use CMT (EJB Container Managed Transaction).
Third party Advertisement
Objectives:
To demonstrate capability towards configuring/ using CMT (Container
Managed Transaction) from Stateless Session Bean to Business Object
and to SessionFactory (Hibernate Session Factory) to Database.
Solution:
A demo program, having WEB Layer, EJB Style, Data Access Object and
Database is to be designed and deployed to JBoss Application Server.
Software Environment:
1. JDK 1.5.0_04
2. JBoss 5.0.0 Beta3
3. Hibernate 3.2
4. Apache ANT
Intention of this demonstration is to show a working model of using
Transaction in EJB Container from Session Bean to Database.
Web tier is made very simple, by having a JSP, that uses a helper JavaBean
to call a method on a Remote Session Bean.
Getting Home interface is done by using Service Locator design pattern.
Session Bean is defined as Stateless and could be acting like SessionFacade
and this session bean has CMT (Container Managed Transaction) initiated by
the Application Server (JBoss Application Server).
Business service is defined in POJO and business method gets invoked by
Session Bean, with either Container Managed Transaction scope or Bean
managed Transaction scope, as defined in ejb-jar.xml file.
Business Object calls/ invokes DAO implementation to store/retrieve value
objects. DAO implementation has wrapped Hibernate related api, such as
SessionFactory and Session, and uses various methods like save, saveOrUpdate,
update, get, load of Hibernate Session instance to perform required database
operation.
Third party Advertisement
Now in this entire process, Transaction is getting initiated at Session bean
level and is propagated to business object, then to DAO and to Hibernate
Session and finally database related operations. So the entire business method
execution happens within a distributed application server Transaction.
In case of any type of database exception/ failure, this entire operation
gets rollback by Transaction, thus maintaining database consistency.
This demo has hibernate.cfg.xml file, as explained below:
<session-factory name="<JNDI-Name>">
<!-- properties -->
<property name="connection.datasource">java:OracleDS</property>
<property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="show_sql">true</property>
<!-- property for JTA (Bean Managed Transaction) compatible Hibernate
Transaction Factory -->
<!--
<property name="transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</property>
-->
<!-- property for CMT (Container Managed Transaction) compatible Hibernate
Transaction Factory -->
<property name="transaction.factory_class">
org.hibernate.transaction.CMTTransactionFactory
</property>
<property name="hibernate.transaction.manager_lookup_class">
org.hibernate.transaction.JBossTransactionManagerLookup
</property>
<property name="jta.UserTransaction">UserTransaction</property>
<property name="hibernate.current_session_context_class">
org.hibernate.context.JTASessionContext
</property>
<mapping resource="demo/admin/Application.hbm.xml"/>
</session-factory>
This hibernate.cfg.xml file can define SessionFactory with a JNDI name
, which can be looked up by any utility for accessing single instance
of Hibernate SessionFactory.
The need for binding SessionFactory to JNDI namespace is to avoid
re-creating SessionFactory for every operation, as it is advisable
to use a single SessionFactory for the entire application, but limiting
Session instance retrieved from SessionFactory, to a single business
operation. As SessionFactory creation is resource intensive operation
and it is always stateless.
The section commented in the above hibernate.cfg.xml file, is for
JTA (Java Transaction API). If enabled Programmatic JTA transaction
can be initiated by Session Bean by looking up UserTransaction.
This transaction will be propagated to Hibernate Session and on completion
of Database operation, Session will be flushed and transaction will be
committed (in case of any database exception, transaction will be roll backed).
The section in BOLD, is the CMT (Container Managed Transaction) factory
that is for using CMT transaction defined in the ejb-jar.xml session bean
descriptor file,
<transaction-type>Container<transaction-type>
and for JTA, or programatic UserTransaction, this will be changed to
<transaction-type>Bean<transaction-type>
The datasource defined in hibernate.cfg.xml file has to be defined in
Application Server, in JBoss Application Server, I have created a file
as Oracle-ds.xml with the following contents:
<datasources>
<local-tx-datasource>
<jndi-name>OracleDS</jndi-name>
<connection-url>
jdbc:oracle:thin:@<Oracle database host name/ip>:1521:<NET Configuration service name>
</connection-url>
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
<user-name>db user name</user-name>
<password>encrypted password</password>
</local-tx-datasource>
</datasources>
This datasource file has to be placed in %JBoss_Home%/server/default/deploy
folder, if the server profile is 'default'.
For testing JTA programmatic UserTransaction to be looked /used in Session Bean
and propagating it to Hibernate Session for database operations, there will be
changes as follows:
1. ejb-jar.xml file:
<transaction-type>Bean</transaction-type>
2. hibernate.cfg.xml file:
Un-comment JTATransactionFactory and comment CMTTransactionFactory
section/ tags.
3. Session bean code will be using JNDI to look up UserTransaction from
InitialContext, and beginning this UserTransaction and Committing it
in finally block or rolling back entire Transaction, in case of any
database related Exception.
Add your suggestions here