Alex D
Alex D

Reputation: 663

Spring @Transactional doesn't work when deploying to JBoss 7.1.1

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:

<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

Answers (4)

Alex D
Alex D

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

Jukka
Jukka

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

V G
V G

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

Vlad Mihalcea
Vlad Mihalcea

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:

  1. hibernate.transaction.manager_lookup_class
  2. hibernate.transaction.factory_class

Upvotes: 1

Related Questions