What I need to do is a distributed transaction over three distinct Oracle databases. One of each must be accessed through JDBC, the two others through Hibernate. Here is my Atomikos configuration :
<bean id="mainDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="xaDataSourceClassName" value="${mainDataSource.jdbc.className}" />
<property name="uniqueResourceName" value="${mainDataSource.jdbc.uniqueName}" />
<property name="poolSize" value="${mainDataSource.jdbc.maxPoolSize}" />
<property name="testQuery" value="${mainDataSource.jdbc.testQuery}" />
<property name="xaProperties">
<props>
<prop key="URL">${mainDataSource.jdbc.url}</prop>
<prop key="user">${mainDataSource.jdbc.user}</prop>
<prop key="password">${mainDataSource.jdbc.password}</prop>
</props>
</property>
</bean>
<bean id="optionalDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="xaDataSourceClassName" value="${optionalDataSource.jdbc.className}" />
<property name="uniqueResourceName" value="${optionalDataSource.jdbc.uniqueName}" />
<property name="poolSize" value="${optionalDataSource.jdbc.maxPoolSize}" />
<property name="testQuery" value="${optionalDataSource.jdbc.testQuery}" />
<property name="xaProperties">
<props>
<prop key="URL">${optionalDataSource.jdbc.url}</prop>
<prop key="user">${optionalDataSource.jdbc.user}</prop>
<prop key="password">${optionalDataSource.jdbc.password}</prop>
</props>
</property>
</bean>
<bean id="eventDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="xaDataSourceClassName" value="${eventDataSource.jdbc.className}" />
<property name="uniqueResourceName" value="${eventDataSource.jdbc.uniqueName}" />
<property name="poolSize" value="${eventDataSource.jdbc.maxPoolSize}" />
<property name="testQuery" value="${eventDataSource.jdbc.testQuery}" />
<property name="xaProperties">
<props>
<prop key="URL">${eventDataSource.jdbc.url}</prop>
<prop key="user">${eventDataSource.jdbc.user}</prop>
<prop key="password">${eventDataSource.jdbc.password}</prop>
</props>
</property>
</bean>
<bean id="atomikosTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp"
init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<props>
<prop key="com.atomikos.icatch.service">com.atomikos.icatch.standalone.UserTransactionServiceFactory
</prop>
<prop key="com.atomikos.icatch.tm_unique_name">${transactionmanager.atomikos.tmId}</prop>
<prop key="com.atomikos.icatch.enable_logging">${transactionmanager.atomikos.enablelogging}</prop>
<prop key="com.atomikos.icatch.output_dir">${transactionmanager.atomikos.console}</prop>
<prop key="com.atomikos.icatch.log_base_dir">${transactionmanager.atomikos.tmLog}</prop>
<prop key="com.atomikos.icatch.log_base_name">${transactionmanager.atomikos.tmLogBaseName}</prop>
</props>
</constructor-arg>
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"
depends-on="atomikosTransactionService">
<property name="transactionTimeout" value="300" />
</bean>
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" depends-on="atomikosTransactionService"
destroy-method="close">
<!-- when close is called, should we force transactions to terminate or
not? -->
<property name="forceShutdown" value="true" />
<property name="startupTransactionService" value="false" />
</bean>
<bean id="mainTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
</bean>
<!-- Der mainTransactionManager ist der Default-TransactionManager von Spring. -->
<alias name="mainTransactionManager" alias="transactionManager" />
The Hibernate configuration is inspired by the solution found on this topic :
<!-- inject the Atomikos transaction manager into a Spring Hibernate adapter
for JTA Platform -->
<bean id="springJtaPlatformAdapter"
class="my.domain.spring.hibernate.jta.SpringJtaPlatformAdapter">
<!-- the mainTransactionManager is defined in ora_jtam_atomikos.xml imported -->
<property name="jtaTransactionManager" ref="mainTransactionManager" />
</bean>
<bean id="entityManagerFactoryEVL"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
depends-on="mainTransactionManager,springJtaPlatformAdapter">
<property name="persistenceXmlLocation" value="classpath:evl_persistence.xml" />
<property name="persistenceUnitName" value="evlPersistenceUnit" />
<property name="dataSource" ref="optionalDataSource" />
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaPropertyMap" ref="jpaPropertyMapEVL"></property>
</bean>
<util:map id="jpaPropertyMapEVL">
<entry key="hibernate.hbm2ddl.auto" value="validate" />
<entry key="hibernate.show_sql" value="false" />
<entry key="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<entry key="hibernate.transaction.jta.platform"
value="my.domain.spring.hibernate.jta.SpringJtaPlatformAdapter" />
</util:map>
<bean id="entityManagerFactoryVVL"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
depends-on="mainTransactionManager,springJtaPlatformAdapter">
<property name="persistenceXmlLocation" value="classpath:vvl_persistence.xml" />
<property name="persistenceUnitName" value="vvlPersistenceUnit" />
<property name="dataSource" ref="eventDataSource" />
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaPropertyMap" ref="jpaPropertyMapVVL"></property>
</bean>
<util:map id="jpaPropertyMapVVL">
<entry key="hibernate.hbm2ddl.auto" value="validate" />
<entry key="hibernate.show_sql" value="false" />
<entry key="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<entry key="hibernate.transaction.jta.platform"
value="my.domain.spring.hibernate.jta.SpringJtaPlatformAdapter" />
</util:map>
And the small class named SpringJtaPlatformAdapter :
public class SpringJtaPlatformAdapter extends AbstractJtaPlatform {
private static final long serialVersionUID = -7030175748923257913L;
private static TransactionManager sTransactionManager;
private static UserTransaction sUserTransaction;
#Override
protected TransactionManager locateTransactionManager() {
Assert.notNull(sTransactionManager, "TransactionManager has not been setted");
return sTransactionManager;
}
#Override
protected UserTransaction locateUserTransaction() {
Assert.notNull(sUserTransaction, "UserTransaction has not been setted");
return sUserTransaction;
}
public void setJtaTransactionManager(JtaTransactionManager jtaTransactionManager) {
sTransactionManager = jtaTransactionManager.getTransactionManager();
sUserTransaction = jtaTransactionManager.getUserTransaction();
}
}
When I do run the batch, I could verified that :
the atomikosUserTransaction and atomikosTransactionManager of
Atomikos are constructed first
the mainTransactionManager is initialized right after
the setJtaTransactionManager method of my SpringJtaPlatformAdapter is called, both memory addresses for the sTransactionManager and sUserTransaction are consistent with the ones created before
the locateTransactionManager of the SpringJtaPlatformAdapter is called twice (one for each persistence unit)
my Hibernate code is then performed, my entities are correctly initialized
the database which is accessed through JDBC is updated
the databases which are accessed through Hibernate are NOT updated (as if a rollback took place)
During the run, only one warning appears in the logs :
WARN main SessionFactoryImpl:1530 - HHH000008: JTASessionContext being used with JDBCTransactionFactory; auto-flush will not operate correctly with getCurrentSession()
Maybe that can help, I personnaly don't get the warning message.
According to Maven, I'm using Spring ORM 3.2.0 with Hibernate 4.2.3 and Atomikos 3.8.0.
I am using Atomikos 4.0.0.M4 release with:
<entry key="hibernate.transaction.jta.platform"
value="com.atomikos.icatch.jta.hibernate4.AtomikosPlatform"/>
instead of:
<entry key="hibernate.transaction.manager_lookup_class"
value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" />
The point to note is that Hibernate 4.x moved away from TransactionManager to JtaPlatform which has necessitated the need for the change in configuration.
I am happy with the functionality provided by Atomikos and it has been running stably for me.
One colleague found why my hibernate databases were not updated. I had this in my persistence.xml :
<persistence-unit name="evlPersistenceUnit" transaction-type="RESOUCE_LOCAL">
For Atomikos, I should have placed :
<persistence-unit name="evlPersistenceUnit" transaction-type="JTA">
Now it's working just fine.
Related
I want to use a common transaction manager (JpaTransactionManager) for hibernate and activiti, but i can not! And i have read all internet resources for that! Hear is a simple scenario (which does not even use hibernate!!):
Save variables in task
Save variable in task#execution
Complete task
Scenario implementation (in a spring bean method with #Transactional annotation):
#Component
public class TaskManager {
#Autowired TaskService taskService;
#Autowired RuntimeService runtimeService;
#Transactional
public void completeTask(CompleteTaskRequest request) {
Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult();
if (task == null) {
throw new ActivitiObjectNotFoundException("No task found");
}
taskService.setVariableLocal(task.getId(), "actionDisplayUrl", request.getActionDisplayUrl());
taskService.setVariableLocal(task.getId(), "actionSummaryUrl", request.getActionSummaryUrl());
runtimeService.setVariableLocal(task.getExecutionId(), "prevTaskId", task.getId());
taskService.complete(task.getId());
}
}
It's obvious: if taskService.complete throws error, the whole transaction should be rollbacked, so all saved variables should be rollbacked, and the below test case should be passed:
#Test
#Deployment(resources = "org.activiti.test/CompleteTaskTest.bpmn20.xml")
public void testCompleteTaskWithError() {
Map<String, Object> processVars = new HashMap<>();
processVars.put("error", true); // Causes throwing error in ScriptTaskListener
runtimeService.startProcessInstanceByKey("CompleteTaskTest", processVars);
Task task = taskService.createTaskQuery().taskName("Task 1").singleResult();
CompleteTaskRequest req = new CompleteTaskRequest();
req.setTaskId(task.getId());
req.setActionDisplayUrl("/actions/1234");
req.setActionSummaryUrl("/actions/1234/summary");
try {
taskManager.completeTask(req);
fail("An error expected!");
} catch(Exception e) {
}
// Check variables rollback
assertNull(taskService.getVariableLocal(task.getId(),"actionSummaryUrl"));
assertNull(taskService.getVariableLocal(task.getId(),"actionDisplayUrl"));
assertNull(runtimeService.getVariableLocal(task.getExecutionId(), "prevTaskId"));
}
But it fails, the variables are committed to DB (not rollbacked).
Spring context (Using org.springframework.orm.jpa.JpaTransactionManager as transaction manager):
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="idGenerator" ref="idGenerator"/>
<property name="databaseSchemaUpdate" value="true" />
<property name="jpaEntityManagerFactory" ref="entityManagerFactory" />
<property name="jpaHandleTransaction" value="true" />
<property name="jpaCloseEntityManager" value="true" />
<property name="beans" ref="processEngineBeans" />
<property name="jobExecutorActivate" value="false" />
<property name="asyncExecutorEnabled" value="true" />
<property name="asyncExecutorActivate" value="true" />
</bean>
<aop:config proxy-target-class="true" />
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="processEngineBeans" class="java.util.HashMap">
<constructor-arg index="0" type="java.util.Map">
<map>
</map>
</constructor-arg>
</bean>
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
<bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />
<bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
<bean id="formService" factory-bean="processEngine" factory-method="getFormService" />
<bean id="idGenerator" class="org.activiti.engine.impl.persistence.StrongUuidGenerator" />
<bean id="activitiRule" class="org.activiti.engine.test.ActivitiRule">
<property name="processEngine" ref="processEngine" />
</bean>
<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="packagesToScan" value="org.activiti.test" />
<property name="defaultDataSource" ref="dataSource" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect_resolvers">org.hibernate.engine.jdbc.dialect.internal.DialectResolverSet</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<!-- bean post-processor for JPA annotations -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" >
<property name="proxyTargetClass" value="true" />
</bean>
Versions:
Activiti version: 5.22.0
DB: h2 (Also tested with Oracle in production)
What is wrong with my configurations?
P.S.
The test project is uploaded here.
I have also asked this question in alfresco forum.
UPDATE::
By using org.springframework.jdbc.datasource.DataSourceTransactionManager instead of org.springframework.orm.jpa.JpaTransactionManager the test case passed. But now i can not persist JPA entities.
The problem is solved by resolving conflict between MyBatis (JDBC) and Hibernate (JPA):
jpaVendorAdapter property should be added to entityManagerFactory bean:
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
So entityManagerFactory bean should be like this:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect_resolvers">org.hibernate.engine.jdbc.dialect.internal.DialectResolverSet</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
For more details see answer of this question.
I have tried many different solutions, but getting the exception:
org.hibernate.HibernateException: Unable to locate current JTA transaction
I am using Atomikos, Hibernate 4/5, Spring 4 and Jetty.
How to configure Spring 4 + Hibernate 4/5 (non JPA)?
Atomikos documentation only has an example with JPA.
I would be very grateful for a working example (non JPA, non JEE Application server).
This example changes non JPA:
<context:annotation-config />
<context:component-scan base-package="com.atomikos.icatch.jta.hibernate4" />
<tx:annotation-driven transaction-manager="transactionManager" mode="proxy" proxy-target-class="false" />
<aop:aspectj-autoproxy />
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close" depends-on="dataSource">
<property name="forceShutdown" value="true" />
</bean>
<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
<!-- by default : looks for java:comp/UserTransaction -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="atomikosUserTransaction"></property>
<property name="transactionManager" ref="atomikosTransactionManager"></property>
</bean>
<bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
destroy-method="close" init-method="init" >
<property name="uniqueResourceName" value="atomikos-standalone" />
<property name="maxPoolSize" value="10" />
<property name="minPoolSize" value="5" />
<property name="testQuery" value="SELECT 1" />
<property name="xaDataSource" ref="xaReferent" />
</bean>
<bean id="xaReferent" class="org.h2.jdbcx.JdbcDataSource">
<property name="URL" value="jdbc:h2:~/test-db;MODE=PostgreSQL;MVCC=TRUE;DB_CLOSE_DELAY=-1" />
<property name="user" value="sa" />
<property name="password" value="" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.atomikos.icatch.jta.hibernate4"/>
<property name="jtaTransactionManager" ref="transactionManager" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.transaction.jta.platform">com.atomikos.icatch.jta.hibernate4.AtomikosPlatform</prop>
<prop key="show_sql" >true</prop>
</props>
</property>
</bean>
</beans>
Update
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.atomikos.icatch.jta.hibernate4"/>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory</prop>
<prop key="hibernate.transaction.jta.platform">com.atomikos.icatch.jta.hibernate4.AtomikosPlatform</prop>
<prop key="hbm2ddl.auto">create</prop>
<prop key="connection.release_mode">auto</prop>
<prop key="cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="show_sql">true</prop>
</props>
</property>
</bean>
I want to achieve the following:
i) we have a weblogic queue and external applications would be writing into the queue
ii)I have to write a stand-alone application which can read and write into this queue inside a transaction. i.e. the messages from the queue has to be persisted into DB. So in case of any error at any stage, the transaction should rollback and the message should be available in the queue again.
To achieve this I have done some self study and came across the below URL:
http://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html?page=3
I have understood that I have to use JTA and XA resources for this. I have tried using Atomikos as the JTA Transaction manager following the below URL:
http://www.atomikos.com/Documentation/SpringIntegration
After trying whole day I have comeup with the following incomplete applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.provider.url">t3://somehost.corp.com:8011</prop>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
</props>
</property>
</bean>
<!--
This is an interface not a concreate class. Not sure what needs to go here for weblogic queue connection factory.
<bean id="xaFactory" class="javax.jms.XAConnectionFactory">
<property name="brokerURL" value="t3://somehost.corp.com:8011" />
</bean> -->
<bean id="ConnectionFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="jms/AuditCF" />
<property name="xaConnectionFactory" ref="xaFactory" />
</bean>
<bean id="JtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
</bean>
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
</bean>
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
<bean id="myDestination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jms/AuditQ</value>
</property>
</bean>
<bean id="service" class="com.samples.AccountService">
<property name="jmsTemplate">
<ref bean="jmsTemplate" />
</property>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="ConnectionFactory" />
</property>
<property name="defaultDestination">
<ref bean="myDestination" />
</property>
<property name="destinationResolver" ref="jndiResolver" />
</bean>
<!-- a class that implements javax.jms.MessageListener -->
<bean id="MessageListener" class="com.samples.Messages" />
<bean id="MessageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="transactionManager" ref="JtaTransactionManager" />
<property name="connectionFactory" ref="ConnectionFactory" />
<property name="messageListener" ref="MessageListener" />
<property name="destinationName" value="jms/AuditQ" />
<property name="concurrentConsumers" value="1" />
<property name="receiveTimeout" value="3000" />
<property name="sessionTransacted" value="true" />
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>weblogic.jms.XAConnectionFactory</value>
</property>
</bean>
<bean id="jndiResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="cache">
<value>true</value>
</property>
</bean>
<!-- <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="receiveTimeout">
<value>0</value>
</property>
<property name="destinationResolver" ref="jndiResolver" />
</bean> -->
<bean id="datasource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<!-- set an arbitrary but unique name for the datasource -->
<property name="uniqueResourceName">
<value>XADBMS</value>
</property>
<!-- set the underlying driver class to use, in this example case we use
Oracle -->
<property name="xaDataSourceClassName">
<value>oracle.jdbc.xa.client.OracleXADataSource</value>
</property>
<property name="xaProperties">
<props>
<prop key="user"><user></prop>
<prop key="password"><pwd></prop>
<prop key="URL">jdbc:oracle:thin:#host:3028/DB
</prop>
</props>
</property>
<!-- how many connections in the pool? -->
<property name="poolSize" value="3" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="packagesToScan" value="com.samples">
</property>
<property name="dataSource">
<ref bean="datasource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.connection.isolation">3</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</prop>
<prop key="hibernate.transaction.manager_lookup_class">
com.atomikos.icatch.jta.hibernate4.TransactionManagerLookup
</prop>
</props>
</property>
</bean>
</beans>
As shown in the Spring-Atomikos integration example, the XAConnectionFactory has been mentioned as :
<bean id="xaFactory"
class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
I am unable to find the related configuration I need to do for weblogic queue. I have tried using "weblogic.jms.XAConnectionFactory" as the class, but I get classnotfoundexception for that.
I dont have any experience working with JTA or XA. Kindly guide me.
I'm using Tomcat7 and need JTA for Infinispan Cache. I am using Spring 3.x with Hibernate 4 (non JPA) and Atomikos for JTA. I can't find a transaction manager look up class in the Atomikos library or docs for Hibernate 4. All examples are for Hibernate version 3 or with use of JPA. Infinispan cannot find a transaction manager.
Here is my config:
<bean id="myDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="rsname" />
<property name="xaDataSourceClassName"
value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
<property name="xaProperties">
<props>
<prop key="URL">${db.url}</prop>
<prop key="user">${db.user}</prop>
<prop key="password">${db.pass}</prop>
</props>
</property>
<property name="maxPoolSize" value="50" />
<property name="minPoolSize" value="20" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="mappingLocations" value="classpath*:hibernate/**/*.hbm.xml" />
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=true
hibernate.cache.region.factory_class=org.hibernate.cache.infinispan.InfinispanRegionFactory
hibernate.cache.use_query_cache=true
hibernate.cache.use_second_level_cache=true
</value>
</property>
</bean>
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.J2eeUserTransaction">
<property name="transactionTimeout" value="300" />
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager" depends-on="atomikosTransactionManager,atomikosUserTransaction">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
<property name="allowCustomIsolationLevels" value="true" />
</bean>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" rollback-for="Throwable" />
</tx:attributes>
</tx:advice>
Looking at the spring docs setting the jtaTransactionManager property on the LocalSessionFactoryBean should take care of things.
<property name="jtaTransactionManager" ref="transactionManager" />
Basically adding that to the definition of your bean should be enough.
Another note about your configuration, you are using <tx:annotation-driven /> so basically your <tx:advice .. /> does nothing only takes up space.
i try to config a data source ----> mysql
the other data source ----> h2 in memory (embedded )
with the following config:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost/item"
p:username="" p:password="" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSource">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</prop>
<prop key="net.sf.ehcache.configurationResourceName">/ehcache.xml</prop>
</props>
</property>
<property name="packagesToScan" value="*************" />
</bean>
<!-- Spring transaction management -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="org.h2.tools.Server" class="org.h2.tools.Server" scope="singleton" factory-method="createTcpServer"
init-method="start" depends-on="org.h2.tools.Server-WebServer">
<constructor-arg value="-tcp,-tcpAllowOthers,true,-tcpPort,9092"/>
</bean>
<bean id="org.h2.tools.Server-WebServer" class="org.h2.tools.Server" scope="singleton" factory-method="createWebServer" init-method="start">
<constructor-arg value="-web,-webAllowOthers,true,-webPort,8082"/>
</bean>
<!-- notice that loading the Driver as a bean is unnecessary is most cases! u could safely remove this and the depends-on in the next bean -->
<bean id="H2DatabaseJDBCDriver" class="org.h2.Driver" scope="singleton" init-method="load" depends-on="org.h2.tools.Server"/>
<bean id="H2InMemoryDB"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
depends-on="org.h2.tools.Server">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:appdb1;DB_CLOSE_DELAY=-1" />
<!-- ;TRACE_LEVEL_FILE=3;TRACE_LEVEL_SYSTEM_OUT=3 -->
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="H2InMemoryDBPool" class="org.apache.commons.pool.impl.GenericObjectPool">
<!-- Two connections: InMemoryEntityManagerFactory and transactionManager -->
<property name="minIdle" value="1"/>
<property name="maxWait" value="10"/>
<property name="maxActive" value="10"/>
<property name="maxIdle" value="10"/>
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
</bean>
<bean id="H2InMemoryDBDSConnFactory" class="org.apache.commons.dbcp.DataSourceConnectionFactory">
<constructor-arg><ref bean="H2InMemoryDB"/></constructor-arg>
</bean>
<bean id="H2InMemoryDBPoolableConnFactory" class="org.apache.commons.dbcp.PoolableConnectionFactory">
<constructor-arg index="0"><ref bean="H2InMemoryDBDSConnFactory"/></constructor-arg>
<constructor-arg index="1"><ref bean="H2InMemoryDBPool"/></constructor-arg>
<constructor-arg index="2"><null/></constructor-arg>
<constructor-arg index="3"><null/></constructor-arg>
<constructor-arg index="4"><value>false</value></constructor-arg>
<constructor-arg index="5"><value>true</value></constructor-arg>
</bean>
<bean id="pooledInMemoryDB" class="org.apache.commons.dbcp.PoolingDataSource" depends-on="H2InMemoryDBPoolableConnFactory">
<constructor-arg><ref bean="H2InMemoryDBPool"/></constructor-arg>
</bean>
<bean id="sessionFactory2"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="pooledInMemoryDB">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
<property name="packagesToScan" value="********" />
</bean>
<bean id="transactionManager2"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
but its not work .
so my question is :
do i need to use 2 session factory or using dynamic data source switch ?
Thanks
I did find a typo that may cause you code to break.
Your second transactionmanager refers to the first sessionFactory. I think you want it to refer to the second transactionmanager. Try:
<bean id="transactionManager2"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory2" />
Regarding your question whether one has to use some sort of "dynamic data source switch" as described here, multiple data sources should just be fine.
i use
<jdbc:embedded-database id="embeddedDatasource" type="DERBY">
<jdbc:script location="classpath:test.sql"/>
</jdbc:embedded-database>
instead
it works