Updated version available: If you are looking for how JPA can be used in JBoss 5 and Spring 3.x versions, look at "Spring JPA web applications (JTA transactions, JBoss 5)". What you find below is a workaround to use JTA transactions in JBoss 4.x versions.
Here's how one might go about deploying a Spring application in JBoss (4.something) that uses JPA with Hibernate as the provider for persistence and JTA for transaction demarcation.
1. Define the Spring configuration file in the web.xml file
<context-param>
<description>Spring configuration file</description>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
2. Define the Spring loader in the web.xml file
<listener>
<description>Spring Loader</description>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
3. Define the persistence unit reference in the web.xml file (which in fact has no effect until the Servlet container supports Servlet spec 2.5):
<persistence-unit-ref>
<description>
Persistence unit for the bank application.
</description>
<persistence-unit-ref-name>persistence/BankAppPU</persistence-unit-ref-name>
<persistence-unit-name>BankAppPU</persistence-unit-name>
</persistence-unit-ref>
* Note that this is what enables "<jee:jndi-lookup>" which has been commented out in the below given Spring configuration file.
* For the above to work well, your web.xml should start like this (note the version 2.5):
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
4. Here's the persistence.xml file. Make the changes to the <jta-data-source> as you have defined in your system (for example in a file like JBOSS_HOME/server/default/deploy/bank-ds.xml - See JBOSS_HOME/docs/examples/jca/ for templates).
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" 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_1_0.xsd">
<persistence-unit name="BankAppPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:BankAppDS</jta-data-source>
<properties>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="jboss.entity.manager.factory.jndi.name" value="java:/BankAppPU"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
5. Here's a sample Spring configuration file (applicationContext.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">
<!-- In a fully J5EE compatible environment, the following xml tag should work in accessing the EMF -->
<!--
<jee:jndi-lookup id="entityManagerFactory" jndi-name="java:/BankAppPU"/>
-->
<!-- Hack for JBoss 4.something until full compliance is reached -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="BankAppPU"/>
</bean>
<!-- Let's access the JTA transaction manager of the application server -->
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:/TransactionManager"/>
<property name="userTransactionName" value="UserTransaction"/>
</bean>
<!-- Let's define a DAO that uses the EMF -->
<bean id="accountHolderDAO" class="bankapp.dao.AccountHolderDAO">
<property name="emf" ref="entityManagerFactory"/>
</bean>
<!-- This is a service object that we want to make transactional.
You will have an interface implemented (AccountManager) in the class.
-->
<bean id="accountManager" class="bankapp.AccountManagerImpl">
<property name="accountHolderDAO" ref="accountHolderDAO"/>
</bean>
<!-- The transactional advice (i.e. what 'happens'; see the <aop:advisor/> bean below) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only transactions -->
<tx:method name="get*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*" read-only="false" />
</tx:attributes>
</tx:advice>
<!-- ensure that the above transactional advice runs for execution
of any operation defined by the AccountManager interface -->
<aop:config>
<aop:pointcut id="accountManagerOperation",
expression="execution(* bankapp.AccountManager.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="accountManagerOperation"/>
</aop:config>
</beans>
6. Here's the sample AccountManagerImpl:
public class AccountManagerImpl implements AccountManager {
/** Creates a new instance of AccountManagerImpl */
public AccountManagerImpl() {
}
private AccountHolderDAO accountHolderDAO;
public AccountHolder createAccountHolder(AccountHolder accountHolder) throws BankException {
return accountHolderDAO.create(accountHolder);
}
public AccountHolderDAO getAccountHolderDAO() {
return accountHolderDAO;
}
public void setAccountHolderDAO(AccountHolderDAO accountHolderDAO) {
this.accountHolderDAO = accountHolderDAO;
}
}
7. Here's the sample AccountHolderDAO:
public class AccountHolderDAO {
/** Creates a new instance of AccountHolderDAO */
public AccountHolderDAO() {
}
private EntityManagerFactory emf;
public EntityManagerFactory getEmf() {
return emf;
}
public void setEmf(EntityManagerFactory emf) {
this.emf = emf;
}
public AccountHolder create(AccountHolder newAccountHolder) throws BankException {
try {
// JTA Transaction assumed to have been started by AccountManager (Spring tx advice)
EntityManager em = emf.createEntityManager();
//em.getTransaction().begin(); - Not required
em.persist(newAccountHolder);
//em.getTransaction().commit(); - Not required
return newAccountHolder;
// JTA Transaction will be completed by Spring tx advice
} catch (Exception e) {
throw new BankException("Account creation failed" + e.getMessage(), e);
}
}
}
You will have some other code accessing the Spring bean "accountManager" and invoke the createAccountHolder() with the required parameters. Things should work well.



Configuring a JBoss + Spring + JPA (Hibernate) + JTA web applica
Refering to: <property name="transactionManagerName" value="java:/TransactionManager"></property>Where is it defined?... or where does it read it ? ... has it to be "java:/TransactionManager", beacuse of jboss.entity.manager.factory.jndi.name? or could be "persistence/TransactionManager" instead of?
It's JBoss convention
java:/TransactionManager is the JNDI name of the JTA transaction manager of the transaction service running within JBoss. The exact name should be available somewhere within that service. It has to be "java:TransactionManager" and does not change based on other things that you do in a JBoss server except if you start tweaking the transaction service - which you never want to do (almost always).
Great!, this definitely works!
Thank you man, I've lost a lot of time trying to find a way to make this work and by reading your post everything started working ok!, I really appreciate you took the time to give such a clear explanation on how to make this work!
help needed
Hi,
Thanks for your post. It is really helpful. But I still have problem getting it work. The jboss start log keeps showing that entitymanager not bound. And JNDI view does not list the persistence unit configured in persistence.xml, even though persistence.xml seems to be processed. I could post the configuration files if you would like to provide some help.
Many thanks.
help needed
Hi,
Thanks for your post.
But I still couldn't get it work. Could you provide some suggestion about my set up? Here is the link to my configuration files:
http://forum.springsource.org/showthread.php?p=255396
Here's the help you need!
The problem will go away by the time you will think that what you have done is not what I have mentioned :)
Hi Kamal Thanks a lot for
Hi Kamal
Thanks a lot for your post. The solution really worked for me !! :)
NameNotFoundException: PersistenceUnit not bound
HI, thanks for the tutorial...
I followed the steps in your tutorial, including this line in applicationContext.xml but i still get this error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: AEDLPersistenceUnit not bound .... .... Caused by: javax.naming.NameNotFoundException: AEDLPersistenceUnit not bound
Is there any extra configuration i have to do in order to make the PU work.
Here you can take a look at my config files: http://forum.springsource.org/showthread.php?p=268339#post268339
Thanks in advance..
Hibernate Dialect must be explicitly set
I solved my earlier problem but now i get this exception
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/spring/applicationContext-jdbc.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: org.hibernate.HibernateException: Hibernate Dialect must be explicitly set
Is there a way to set the dialect?
This is the way i declare my entity manager in applicationContext.xml:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="AEDLPersitenceUnit" />
<property name="jpaVendorAdapter">
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="database" value="MYSQL" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean
I tried without pdaDialect property and doesn't work either. thanks for your time
Errors!
First, follow this guide.
Post new comment