Search code examples
jpajboss7.xjtaspring-3spring-data-jpa

Can't make JTA work on jboss AS7.1 with spring 3.1


We're trying to configure a Spring application to work with JTA transactions. It is not like it is failing, but everything we tried just do the select and ignores our persistence operations.

As you can see in the following logs, even though the save statement run there’s no insert statement, neither an exception, neither an error/warning logs

server.log

DEBUG [xxxx.xxxx.persistence] (http--0.0.0.0-8080-1) execute $Proxy363.save(whatever.core.entities.XxxAssignedTime@51a8c542)
DEBUG [org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor$CustomAnnotationTransactionAttributeSource] (http--0.0.0.0-8080-1) Adding transactional method 'save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] (http--0.0.0.0-8080-1) Returning cached instance of singleton bean 'transactionManager'
DEBUG [org.springframework.transaction.jta.JtaTransactionManager] (http--0.0.0.0-8080-1) Participating in existing transaction
INFO  [xxxx.xxxx.impl.BpmnUserBusinessImpl] (http--0.0.0.0-8080-1) Last Assigned Time Updated to *******, Thu Sep 06 15:48:48 ICT 2012

It is like thought the application server thinks everything went right. Whereas if you check the table no insertion or update was made.

The datasource that we intend to use with a spring application is successfully used with JTA transactions by a Java EE war application running in the same application server.

Since we have no idea where the problem might be I'd like to put it all in full context.

  • spring 3.1.2-RELEASE
  • hibernate 4.1.5.Final
  • spring-data-jpa 1.1.1.Final
  • apache axis 1.4
  • jboss AS7.1
  • DB: oracle 10g

We've been trying all sorts of crazy configuration in order to try to make it work, so I will just copy here the simplest one.

standalone.xml

<datasource jta="true" jndi-name="java:jboss/datasources/EngineDS" pool-name="EngineDS" enabled="true" use-java-context="true" use-ccm="true">
    <connection-url>jdbc:oracle:thin:@server:port:****</connection-url>
    <driver>oracle</driver>
    <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
    <pool>
        <min-pool-size>10</min-pool-size>
        <max-pool-size>100</max-pool-size>
        <prefill>true</prefill>
    </pool>
    <security>
        <user-name>****</user-name>
        <password>****</password>
    </security>
    <statement>
        <prepared-statement-cache-size>32</prepared-statement-cache-size>
        <share-prepared-statements>true</share-prepared-statements>
    </statement>
</datasource>
<drivers>
    <driver name="oracle" module="com.oracle.ojdbc6">
        <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
    </driver>
</drivers>

web.xml

[...]
<resource-ref id="DS">
 <res-ref-name>EngineDS</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
 <res-sharing-scope>Shareable</res-sharing-scope>
 <mapped-name>java:jboss/datasources/EngineDS</mapped-name>
</resource-ref>
[...]

spring-jpa-config.xml

<jpa:repositories base-package="whatever.core.repositories" />
<jee:jndi-lookup id="dataSource" jndi-name="EngineDS" cache="true" resource-ref="true" expected-type="javax.sql.DataSource"/>
<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="whatever.core.entities" />
<property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="showSql" value="${hibernate.show_sql}" />
    <property name="generateDdl" value="${jpa.generateDdl}" />
    <property name="databasePlatform" value="${jpa.dialect}" />
    </bean>
    </property>
 </bean>

 <tx:annotation-driven />
 <tx:jta-transaction-manager />

 <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
 <bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>

We had made in the past jboss AS5/Spring 3.0 applications to work with JTA transactions, so it is not like is my first time doing this, and we've been looking around all possible blogs and open source projects I could find. Yet anything that seem to work smoothly to everybody seems to be ignored in my application. I'm sure it should be that we're missing something really stupid somewhere but we've tried so far 70+ different configurations and none seem do a simple insert that otherwise work when not trying JTA.

(The fact that we use axis 1.4 might be relevant or not, but I'd like to tell because our application only triggers actions after a web service call). At this point we are starting to believe in configuration paranormal activity...

Any clue anyone?


Solution

  • It turned out that the configuration above wasn't working due to the fact that I was using org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.

    To have JTA I should lookup for the JBoss container-managed entity manager spring-jpa.config.xml:

    <!-- lookup the container-managed JPA-EMF --> 
    <!-- the JNDI name is specified in META-INF/persistence.xml --> 
    <!-- SEE: https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-BindingEntityManagerFactorytoJNDI --> 
    <jee:jndi-lookup id="defaultPu" jndi-name="java:jboss/defaultPu" />
    

    And in the META-INF/persistence.xml you bind the Entity Manager Factory into JNDI:

    <!-- bind the EMF in JNDI --> 
    <property name="jboss.entity.manager.factory.jndi.name" value="java:jboss/defaultPu" /> 
    

    So, I let Jboss bootstrap JPA, and in such way the JTA transactions work!