Atomikos Forum

Spring-AtomikosWithJPA

Hello,

I am trying to setup Java desktop project (J2EE without application server) where i use Spring framework with Atomikos as transaction manager and Oracle Toplink Essentials as JPA provider. Everything works just fine until i attempt to add JPA and entity beans.
I have entity bean Customer:

@Entity(name = "customer")
public class Customer {
    @Id
    @Column(name = "ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
...

Then i have Customer DAO interface:
public interface CustomerDao {
    public Customer findCustomerById(Integer id);
...
}
and Customer DAO implementation CustomerDaoImpl.java:

public class CustomerDaoImpl extends JpaDaoSupport implements CustomerDao {
...

My Spring configuration file is:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

<bean id="datasource"
  class="com.atomikos.jdbc.nonxa.NonXADataSourceBean">
    <property name="user" value="root"/>
    <property name="password" value="root"/>
    <property name="url" value="jdbc:mysql://localhost:3306/JPASample"/>
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="poolSize" value="10"/>
    <property name="connectionTimeout" value="60"/>
</bean>

<bean id="jtaTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
    <property name="forceShutdown" value="true"/>
</bean>

<bean id="jtaUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"/>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="transactionManager" ref="jtaTransactionManager"/>
    <property name="userTransaction" ref="jtaUserTransaction"/>
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
    <property name="dataSource" ref="datasource"/>
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="Spring-DAO-JPA" />
    <property name="dataSource" ref="datasource" />

    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
            <property name="showSql" value="true"/>
            <property name="generateDdl" value="true"/>
            <property name="databasePlatform" value="oracle.toplink.essentials.platform.database.MySQL4Platform"/>
    </bean>
    </property>
    <property name="loadTimeWeaver">
        <bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver"/>
    </property>
</bean>

<bean id="customerDao" class="dao.CustomerDaoImpl">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

</beans>

and persistance.xml is:
<persistence 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"
version="1.0">
    <persistence-unit name="Spring-DAO-JPA" transaction-type="RESOURCE_LOCAL">
<provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<class>entity.beans.Customer</class>
    <properties>
        <property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/JPASample"/>
        <property name="toplink.jdbc.user" value="root"/>
    <property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
        <property name="toplink.jdbc.password" value="root"/>
    </properties>
</persistence-unit>
</persistence>

When i tried to test my CustomerDAOImpl:

public class CustomerDaoTest {

    public static void main(String[] args) {
        UserTransactionImp utx = new UserTransactionImp();
    // open bean XML file
        FileSystemXmlApplicationContext factory = new FileSystemXmlApplicationContext("config.xml");

        try {
          utx.begin();

          CustomerDaoImpl customer = (CustomerDaoImpl) factory.getBean("customerDao");

          Collection<Customer> customers = customer.findCustomers();
...

i got following error: null pointer exception because getJpaTemplate().getEntityManager() is null.

I doubt my Spring config file is bad. Can someone help me with integration of Atomikos JTA and Toplink JPA in Spring. My example works just fine before i introduce Toplink JPA. Is there some example how to combine Atomikos JTA and Oracle Toplink JPA in Spring? I am little confused and wondering do i need and is it possible to combine Atomikos JTA with JPA.

Best regards.
Nenad Milasinovic Send private email
Thursday, October 21, 2010
 
 
Hi,

I am not aware of any working TopLink documentation (alas).

However, your error message suggests a problem at the level of the JPA config in Spring rather than the JTA config of Atomikos. Did you try at the Spring or TopLink forums?

Best
Guy Pardon Send private email
Friday, October 22, 2010
 
 
Hello,

Thank you Guy on your fast reply.

I will appreciate if you can send me some example on how to configure Atomikos transactional manager with Hibernate JPA in Spring. I tried your example with atomikos and without JPA and it works perfectly.

Best regards.
Nenad Milasinovic Send private email
Monday, October 25, 2010
 
 
Can you attach the sample simple application which can be tried at our end to simulate the error that you have been experiencing?

Regards,
Vicky
Vicky Kak Send private email
Monday, October 25, 2010
 
 
Hello,

I tried example with Atomikos configured as transaction manager in Spring and without JPA:

public class Bank {
  private DataSource dataSource;
  public Bank() {}

  public void setDataSource(DataSource dataSource) {
    this.dataSource = dataSource;
  }

  private DataSource getDataSource() {
    return this.dataSource;
  }

  private Connection getConnection() throws SQLException {
    Connection ret = null;
    if (getDataSource() != null) {
      ret = getDataSource().getConnection();
    }
    return ret;
  }

  private void closeConnection(Connection c) throws SQLException {
    if (c != null)
      c.close();
  }

  public Double getBalance(int account) throws SQLException {
    Double res = -1.0;
    Connection conn = null;
    try {
      conn = getConnection();
      Statement s = conn.createStatement();
      String query = "select balance from Accounts where account=" + account + ";";
      ResultSet rs = s.executeQuery(query);
      if (rs == null || !rs.next())
        throw new SQLException();
      res = rs.getDouble(1);
      s.close();
    } finally {
      closeConnection(conn);
    }
    return res;
  }
}

public class BankTest extends TestCase {
  private UserTransactionImp utx;
  private Bank bank;
  private FileSystemXmlApplicationContext factory;

  public BankTest(String name) {
    super(name);
    utx = new UserTransactionImp();
  }

  protected void setUp() throws Exception {
    utx.begin();
    factory = new FileSystemXmlApplicationContext("config.xml");
    bank = (Bank) factory.getBean("bank");
  }

  protected void tearDown() throws Exception {
    utx.rollback();
    factory.close();
  }

  public void testBank() throws Exception {
    int accNo = 1;
    Double initialBalance = bank.getBalance(accNo);
  }

  public static TestSuite suite() {
    return new TestSuite(jdbc.BankTest.class);
  }
}

and Spring config:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
  <bean id="datasource" class="com.atomikos.jdbc.nonxa.NonXADataSourceBean">
    <property name="user" value="root"/>
    <property name="password" value="root"/>
    <property name="url" value="jdbc:mysql://localhost:3306/SpringAdvanced"/>
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="poolSize" value="1"/>
    <property name="connectionTimeout" value="60"/>
</bean>

<bean id="jtaTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
    <property name="forceShutdown" value="true"/>
</bean>

<bean id="jtaUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"/>

<bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="jtaTransactionManager"/>
    <property name="userTransaction" ref="jtaUserTransaction"/>
</bean>

<bean id="bankTarget" class= "jdbc.Bank" init-method="checkTables">
    <property name="dataSource" ref="datasource" />
</bean>

<bean id="bank" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="springTransactionManager" />
    <property name="target" ref="bankTarget" />
    <property name="transactionAttributes">
    <props>
        <prop key="*">PROPAGATION_REQUIRED, -Exception</prop>
    </props>
</property>
</bean>

</beans>

Now i am trying to use JPA entity beans instead to create queries manually. I am interested how to get JPA to work in this example.

Best regards.
Nenad Milasinovic Send private email
Tuesday, October 26, 2010
 
 
Hello,

Meanwhile i succeed to get Hibernate to work, however i have problems to use Atomikos as JTA transaction manager.

Here is my spring config file:

<bean id="dataSource" class="com.atomikos.jdbc.nonxa.NonXADataSourceBean">
    <property name="user" value="root"/>
    <property name="password" value="root"/>
    <property name="url" value="jdbc:mysql://localhost:3306/hibernatetest"/>
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="poolSize" value="10"/>
    <property name="connectionTimeout" value="60"/>
</bean>

<!-- JPA EntityManagerFactory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource">
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="database" value="${jdbc.database}"/>
        <property name="showSql" value="${jdbc.showSql}"/>
        <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.transaction.manager_lookup_class" value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup"/>
            <entry key="hibernate.connection.autocommit" value="false" />
            <entry key="hibernate.connection.release_mode" value="after_transaction"/>
    </map>
    </property>
</bean>

<bean id="jtaTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
    <property name="forceShutdown" value="true"/>
</bean>

<bean id="jtaUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"/>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" >
    <property name="transactionManager" ref="jtaTransactionManager"/>
    <property name="userTransaction" ref="jtaUserTransaction"/>
</bean>

<!-- Property Configurator -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="jdbc.properties"/>
</bean>

<context:component-scan base-package="com.test.dao"/>

<bean id="contactServiceTarget" class="com.test.dao.ContactDAO"></bean>

<!-- enable the configuration of transactional behavior based on annotations  -->
<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="contactService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="proxyTargetClass" value="true"/>
    <property name="transactionManager" ref="transactionManager" />
    <property name="target" ref="contactServiceTarget" />
    <property name="transactionAttributes">
        <props>
        <prop key="*">PROPAGATION_REQUIRED, -Exception</prop>
    </props>
    </property>
</bean>

Now when i test DAO class:

UserTransactionImp utx = new UserTransactionImp();
utx.begin();
ContactDAO contactDAO = (ContactDAO) appContext.getBean("contactService");
contactDAO.persist();
utx.commit();

i got following exception:
<Clearing transaction synchronization>
java.lang.IllegalStateException: This method needs a transaction for the calling thread and none exists.
Possible causes: either you didn't start a transaction,
it rolledback due to timeout, or it was committed already.
ACTIONS: You can try one of the following:
1. Make sure you started a transaction for the thread.
2. Make sure you didn't terminate it yet.
3. Increase the transaction timeout to avoid automatic rollback of long transactions;
  check http://www.atomikos.org/forums/viewtopic.php?t=1259 for how to do this.
    at com.atomikos.icatch.jta.TransactionManagerImp.raiseNoTransaction(Unknown Source)
    at com.atomikos.icatch.jta.TransactionManagerImp.rollback(Unknown Source)
    at com.atomikos.icatch.jta.UserTransactionImp.rollback(Unknown Source)

Any help?
Nenad Milasinovic Send private email
Tuesday, October 26, 2010
 
 
I did try the sample application which is shipped with the AtomikosTransactionsEssentials, it is located here  C:\developer\AtomikosTransactionsEssentials-3.7.0M4\examples\spring\jdbc.

I did made the following changes
1) Changed the Datasource bean poiting to the MySql DB, the configuration looks like this

******************************************************
<bean id="datasource" class="com.atomikos.jdbc.nonxa.NonXADataSourceBean">
    <property name="user" value="root"/>
    <property name="password" value="root"/>
    <property name="url" value="jdbc:mysql://localhost:3306/SpringAdvanced"/>
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="poolSize" value="1"/>
    <property name="connectionTimeout" value="60"/>
</bean>
******************************************************

2) I placed the mysql-connector-java-5.1.13-bin.jar in the $JTA_HOME\lib directory.

After that I was able to call the run.bat from here

C:\developer\AtomikosTransactionsEssentials-3.7.0M4\examples\spring\jdbc>run.bat

This did worked as expected, the MySql DB was populated with the DB as expected.

Would it be possible for you the test the similar stuff at your end?

Thanks,
Vicky
Vicky Kak Send private email
Wednesday, October 27, 2010
 
 
Do you have tm logs, can you enables them when you are getting the issues?
I hope the DB tables are not locked and hence not leading to the tx timeout.
Vicky Kak Send private email
Wednesday, October 27, 2010
 
 
Hi Vik,

I already tried that example and everything works just fine. However i have problems to adapt example to use Entity beans and Hibernate as JPA instead to work with raw jdbc.

Is there any example on how to use Atomikos transactions with Hibernate JPA doing persistance job instead of using raw jdbc approach.

I can send you my project to see what i am doing wrong.
Here is my e-mail where you can contact me: nmilaasinovic@gmail.com.

Best regards.
Nenad Milasinovic Send private email
Wednesday, October 27, 2010
 
 
Please send across the project at my email id i.e vickykak@gmail.com
I will take a deep look at it.

Thanks,
Vicky
Vicky Kak Send private email
Wednesday, October 27, 2010
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics