0
votes

I have created an example - SPRING, JPA(EclipseLink persistence provider) with JTA Transaction Manager(JBoss 7). I have observed that all the data in database is being shown in UI properly for the read operations. But when it comes to save/update or delete operation the services layer is not committing the work to database. No exception is caught(I have checked the console/log too and also debugged the code where I can see entityManager.persist/remove is being invoked without any exception).

--Code Listing-- 1. Datasource configuration in standalone.xml

<datasource jta="true" jndi-name="java:/mysql_customerdb3" pool-name="mysql_customerdb3_pool" enabled="true" use-java-context="true" use-ccm="true">
            <connection-url>jdbc:mysql://localhost:3306/customerdb</connection-url>
            <driver>mysql</driver>
            <security>
                <user-name>root</user-name>
                <password>root</password>
            </security>
            <statement>
                <prepared-statement-cache-size>10</prepared-statement-cache-size>
                <share-prepared-statements>true</share-prepared-statements>
            </statement>
        </datasource>
        <drivers>
            <driver name="mysql" module="com.mysql">
                <driver-class>com.mysql.jdbc.Driver</driver-class>
    <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
            </driver>
            <driver name="h2" module="com.h2database.h2">
                <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
            </driver>
        </drivers>
  1. Database driver configuration in module.xml

  2. persistence.xml

    org.eclipse.persistence.jpa.PersistenceProvider java:/mysql_customerdb3 com.springforbeginners.model.Customer

  3. customerdispatcher-servlet.xml

    <context:annotation-config />
    <context:component-scan base-package="com.springforbeginners" />
    
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
        <property name="loadTimeWeaver" ref="loadTimeWeaver" />
        <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
    </bean>
    
    <bean id="loadTimeWeaver" class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" >
    </bean>
    
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManagerName" value="java:jboss/TransactionManager"/>
        <property name="userTransactionName" value="java:jboss/UserTransaction"/>
    </bean> 
    
    <tx:annotation-driven transaction-manager="transactionManager" />
    

  4. CustomerServiceImpl.java

    package com.springforbeginners.service;

    import com.springforbeginners.dao.CustomerDAO; import com.springforbeginners.model.Customer; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;

    @Service public class CustomerServiceImpl implements CustomerService { @Autowired private CustomerDAO customerDAO;

    @Transactional
    @Override
    public void addCustomer(Customer customer) {
        customerDAO.addCustomer(customer);
    }
    
    @Transactional
    @Override
    public List<Customer> listCustomer() {
        return customerDAO.listCustomer();
    }
    
    @Transactional
    @Override
    public void removeCustomer(Integer customerId) {
        customerDAO.removeCustomer(customerId);
    }
    

    }

  5. CustomerDAOImpl.java

    package com.springforbeginners.dao;

    import com.springforbeginners.model.Customer; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.stereotype.Repository;

    @Repository public class CustomerDAOImpl implements CustomerDAO { @PersistenceContext(unitName="CustomerDetailsPU3") private EntityManager entityManager;

    @Override
    public void addCustomer(Customer customer) {
        entityManager.persist(customer);
    }
    
    @Override
    public List<Customer> listCustomer() {
        return entityManager.createQuery("select c from Customer c", Customer.class).getResultList();
    }
    
    @Override
    public void removeCustomer(Integer customerId) {
        Customer customer = (Customer) entityManager.getReference(Customer.class, customerId);
        if (null != customer) {
            entityManager.remove(customer);
        }
    }
    

    }


I do not know what and where exactly is something missing. But with the above code the read operations are working as expected. Problem is with save operations. I have converted the above example to use non-JTA datasource(also modified standalone.xml for jta=false) and to use JpaTransactionManager as below

With non-JTA datasource and 'org.springframework.orm.jpa.JpaTransactionManager' all operations(read as well as save/update/delete) are working fine.

But the JTA version of my example is not working as expected(save operations not committing work to database). Any help/pointers appreciated.

Thanks Prakash


James,

I will be running this application on JBoss. But one datasource on JBoss and other on Glassfish and transaction should span save operation on both datasources simultaneously. This is what I am trying to achieve. I have a web application including spring for service(data) layer currently running on JBoss.

As you said earlier - I will have two persistence.xmls one for JBoss and one for Glassfish. As I am doing this first time I was/am in doubt whether the transaction(that spans two datasources on different servers-in this case JBoss and Glassfish), can this be executed entirely by JBoss(in case if the entire business logic resides in serviceImpl class deployed on JBoss)? In this case I will be using JBoss transaction manager( property name="transactionManagerName" value="java:jboss/TransactionManager" ). Is this sufficient or do I need to similarly have Glassfish transaction manager too? Sorry if this has created the confusion.

Another question from me was that is there a provision for speifying jndi ports in persistence.xml/anywhere else?(Definitely I will have two different persistence.xmls and I will mention the target server as JBoss in one and as Glassfish in another).

Do we have a technique in spring by which business logic can be distributed across different servers like JBoss/Glassfish and still under one single transatcion? I did not know if this can be an option. Were u talking about this scenario in which it will require two different deployment scripts one for each server?

Thanks Prakash

2
Missed database driver configuration in module.xml. Listing below...2. Database driver configuration in module.xml <?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.0" name="com.mysql"> <resources> <resource-root path="mysql-connector-java-5.1.25-bin.jar"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> </dependencies> </module>PRS

2 Answers

2
votes

What is your persistence.xml?

Since you are using JTA, you must define the "eclipselink.target-server"="JBoss"

1
votes

My persistence.xml(modified) now looks like below. Added target server property in persistence.xml. This solved the problem.

  <persistence-unit name="CustomerDetailsPU3" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>java:/mysql_customerdb3</jta-data-source>
    <class>com.springforbeginners.model.Customer</class>
    <properties>
          <property name="eclipselink.target-server" value="JBoss" />
    </properties>
  </persistence-unit>

Thanks Prakash