Atomikos Forum |
|
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.
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.
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.
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?
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
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. |