Reputation: 663
I have a Spring 3.2.8 app with Hibernate 4.0.1 as a JPA implementation. The app is supposed to be deployed on JBoss 7.1.1, but I haven't managed so far to get the transactions to work.
Everything works just fine when I am loading the context using a Spring integration test:
@ActiveProfiles("dev-local-test") uses an in memory database, works ok
@ActiveProfiles("dev-local") connect directly to an Oracle database, works ok
I have been tried to also use "dev-local" profile when deploying to JBoss, everything works ok except the transactions. For this to work, I have renamed persistence.xml so that JPA engine from JBOSS wouldn't load the persistence unit before Spring context initialization, so I explicitely added the org.hibernate dependency. Also, this still uses JpaTransactionManager
Next I have tried two other variations for the server deploy:
profile "dev-server1" - which still uses a Spring org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean but this time the data source is obtained from the JEE container and the same for the TransactionManager, which is JTA
profile "dev-server-2" - where both the EntityManagerFactory and the JTA Transaction Manager are obtained from the JEE container, and this time I am providing the persistence.xml:
<persistence-unit name="app">
<jta-data-source>java:jboss/datasources/AppDS</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="jboss.entity.manager.factory.jndi.name" value="java:/example/EntityManagerFactory"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
</properties>
</persistence-unit>
No matter what, the transactions won't work when deploying on JBoss. I don't get any exceptions, in all cases (well, except Hibernate lazy init, cause there's no transaction) Does anybody know what is wrong with all the configurations I have tried so far?
Thanks in advance, Alex
`
<beans profile="dev-local, dev-local-test">
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="appDataSource" />
<property name="packagesToScan">
<list>
<value>com.my.project.domain</value>
</list>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<!-- Need this because a bug in Hibernate 4.0.1 on JBoss 7.1.1 -->
<prop key="hibernate.listeners.envers.autoRegister">false</prop>
</props>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
<beans profile="dev-local-test">
<jdbc:embedded-database id="appDataSource">
<jdbc:script location="sql/schema.sql" />
</jdbc:embedded-database>
</beans>
<beans profile="dev-local">
<context:property-placeholder location="classpath:/config/db-dev.properties" />
<bean id="appDataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${app.jdbc.driverClassName}" />
<property name="url" value="${app.jdbc.url}" />
<property name="username" value="${app.jdbc.username}" />
<property name="password" value="${app.jdbc.password}" />
</bean>
</beans>
<beans profile="dev-server-1">
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="appDataSource" />
<property name="packagesToScan">
<list>
<value>com.my.project.domain</value>
</list>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<!-- Need this because a bug in Hibernate 4.0.1 on JBoss 7.1.1 -->
<prop key="hibernate.listeners.envers.autoRegister">false</prop>
</props>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<jee:jndi-lookup id="appDataSource" jndi-name="java:jboss/datasources/AppDS"
expected-type="javax.sql.DataSource" />
<tx:jta-transaction-manager id="transactionManager" />
</beans>
<beans profile="dev-server-2">
<jee:jndi-lookup id="entityManagerFactory" jndi-name="java:/example/EntityManagerFactory"
expected-type="javax.persistence.EntityManagerFactory"/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:/TransactionManager"/>
</bean>
</beans>
`
Upvotes: 3
Views: 2625
Reputation: 663
After hours of trying different stuff, it turned out that the reason was very common and not related with JBoss at all.
I have two main Spring context files, one for the ROOT and one for the dispatcher servlet. In dispatcher servlet context, I had context component scan for the root package, including the service layer, so that's why I end up with non-transactional services.
Upvotes: 0
Reputation: 4663
Configure a normal, non-XA data source in JBoss JNDI tree (via admin UI or XML config), remove persistence.xml alltogether, use LocalContainerEntityManagerFactoryBean and package scanning and JpaTransactionManager only, remove all the JTA stuff from your Spring config and JNDI lookup the JBoss provided datasource and then see what happens.
I'd also check if JBoss kindly provides conflicting versions of Hibernate and/or Spring (if you are bundling those in WEB-INF/lib yourself).
Upvotes: 0
Reputation: 19002
You forgot to specify for your persistence-unit
in persistence.xml the transaction-type
to be JTA:
<persistence-unit name="app" transaction-type="JTA">
As far as I know, if you do not specify one, you should set it in the Jboss settings. Check this answer also.
Upvotes: 1
Reputation: 153690
The Spring JtaTransactionManager is just a façade and if you want to take advantage of JBoss JTA/XA support you also need to configure the specific application server transaction manager.
<bean id="jbossTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple">
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<ref bean="jbossTransactionManager"></ref>
</property>
</bean>
Please check this tutorial.
Also Hibernate 4 introduced the jta platform property:
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/>
Try one of those depending on how you use the JBoss AS. This property should replace:
Upvotes: 1