It seems that Hibernate transactional cache mode requires the use of a JTA transaction manager. In an app server such as Glassfish, Weblogic, etc, Spring can use the JTA transaction manager. Tomcat does not have a JTA transaction manager.
Is there one that people use in this scenario? Or do people just not use transactional cache mode with Tomcat?
It depends on you ORM implementation, for example for JPA Spring has a transaction manager for using outside Java EE containers. here's how you declare it:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
I usually use annotations to demarcate transaction boundaries (with #Transaction), to do this you just have to add to the configuration file this other line:
<tx:annotation-driven transaction-manager="transactionManager" />
present in this XSD namespace: "http://www.springframework.org/schema/tx"
Atomikos is one JTA transaction manager that can be bundled with your app to work in a Tomcat deployment.
Related
This might be a repetitive question for you, but I couldn't find (atleast I couldn't understand) a satisfactory answer, hence asking again.
I am working with two data sources (MySQL and Oracle). Following is a flow of execution:
Main method-A calls method-B (Which writes into Oracle DB) then it(Method-A) calls method-C (Which writes into mySQL DB) then it(Method-A) calls method-D(Which writes into Oracle DB).
If failure occurs at any of place, everything should be rolled back. Currently only changes in Oracle DB are getting rolled back & mySQL DB is not getting rolled back.
I have defined two transactional managers.
=========> First <=========
<tx:annotation-driven transaction-manager="txManager" mode='proxy' proxy-target-class='true’/>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<bean id=“SessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean” parent="AbstractSessionFactory" depends-on="AppConfigHelper”>
<property name="hibernateProperties”>
...
ORACLE DB Properties
</property>
</bean>
<aop:aspectj-autoproxy/>
==============================
=========> Second <=========
<tx:annotation-driven transaction-manager="txManager2" mode='proxy' proxy-target-class='true'/>
<bean id="txManager2" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory2" />
<qualifier value="CherryTransaction" />
</bean>
<aop:aspectj-autoproxy/>
<bean id="SessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" parent="AbstractSessionFactory2" depends-on="AppConfigHelper">
<property name="hibernateProperties">
...
MYSQL DB Properties
</property>
</bean>
==============================
On top of method-A I have used #Transactional annotation
On top of method-B I have used #Transactional annotation
On top of method-C I have used #Transactional("txManager2")
annotation
On top of method-D I have used #Transactional annotation
Question Is:
Why is MySQL changes are not getting rolled back?
Is the only way to get this working is to use Global transaction management using JTA? (Its a legacy system, and this is the only place where I need to interact with two DBs)
Can you please point me to an example / tutorial where this kind case is handled?
Sincerely thanks for reading this!
For that to work, AFAIK you'd need to use JTA. Even that won't help if you're using a storage engine in MySQL that doesn't support transactions. With MySQL, only InnoDB and BDB storage engines support transactions.
If you are using MySQL with storage engine that supports transactions, you need to configure XA drivers for both Oracle and MySQL datasource and ensure that both datasources are enlisted in the transaction of your container. Spring then needs to participate in the same transaction. You can't use HibernateTransactionManager for this, but need the JtaTransactionManager, as explained in this thread.
So, what you need for this to work is
Use InnoDB or BDB storage engines on MySQL
Configure XA datasources in your application server instead of regular ones
Use JtaTransactionManager on Spring configuration
I am trying to use JtaTransactionManager in spring/hibernate. I have below configuration.
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransactionName" value="java:comp/UserTransaction"></property>
</bean>
Now can i mark my service methods with #Transactional ? or do i need any extra configuration to use #Transactional ? do i need to add ?
An annotation is nothing more then metadata, so only slapping an annotation on there and expect it to magically work isn't going to happen.
To make #Transactional work you need to tell spring that you want to use annotation to drive your transactions. For this add the <tx:annotation-driven /> tag to your configuration.
However that probably isn't going to be all there is needed as you also need to configure hibernate appropriately for JTA.
A small tip instead of defining the bean, use the shorter <tx:jta-transaction-manager />. This will do some detection on which app server you are running and configure the appropriate transaction manager for you. See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#transaction-application-server-integration for more information.
Somebody knows an example with EJB3 and Mybatis where the container controls the transaction, the only part of code I founded was:
SQLMapConfig.xml
<transactionManager type="EXTERNAL">
<property name="SetAutoCommitAllowed" value="false"/>
<dataSource type="JNDI">
<property name="DataSource" value="java:comp/env/jdbc/sisds"/>
</dataSource>
</transactionManager>
But I have many questions, for example,
When the container make the commit?
When the container release the session to the pool?
Thanks in Advance
The container commits the transaction based on how your EJBs are configured. If you are using bean managed transactions, then you have to manage the UserTransaction yourself.
Regardless, you have to manage the MyBatis SqlSession yourself. Setting the tx type to EXTERNAL (MANAGED in Mybatis 3), simply means that MyBatis never calls commit on the DB connection - it relies on the container to commit.
I'm using Spring in Glassfish and I have the need to configure it so it also works outside of the container, mainly for development purposes.
What I'm uncertain of, and couldn't find the answer to, was whether I can use the LocalContainerEntityManagerFactoryBean class without a container.
From its name, LocalContainer, it seems I can but in the docs it says:
FactoryBean that creates a JPA
EntityManagerFactory according to
JPA's standard container bootstrap
contract
so I'm uncertain about this issue.
Thanks,
Ittai
I just wanted to note that Spring supports running the JPA stuff outside of a container, and doesn't require anything in the way of a transaction manager. The question to ask is whether you are using Spring's declarative transaction management (e.g., "#Transactional").
If you are, then you need to provide an implementation of "PlatformTransactionManager." Here still, you do NOT need to use full on JTA support (as provided by Atomikos in the above example. YOu can simply use a JpaTransactionManager instance (which expects a reference to the entity manager factory) provided you are not doing anything with "XA" etc. If you are doing XA, then Atomikos, or Bitronix or any of a number of other options are just fine. You might look at this example http://blog.springsource.com/2011/08/15/configuring-spring-and-jta-without-full-java-ee/ which demonstrates how to use JTA (with JPA and JMS, for example).
So, reiterating, if you're just doing simple JPA (connecting to one database) then you don't need JTA, and you definitely don't need GlassFish. If you need XA, then you can still use a third party JTA provider as the responder above suggested, and you still don't need Glassfish.
Finally, if you truly wish to maintain both GlassFish + JTA, and a separate JPA that works only locally for rapid development on a faster container, you might consider the imminent Spring 3.1, which features "profiles" to allow you to conditionally define beans per environment (e.g., "production," or "dev," or "cloud," or whatever you'd like.)
Yes, it's possible, but you need to provide a transaction manager (like Atomikos). The rest of the configuration is the same.
This is an example:
<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp"
init-method="init" destroy-method="shutdownForce">
</bean>
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close" depends-on="userTransactionService">
<property name="forceShutdown" value="true" />
</bean>
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"
depends-on="userTransactionService">
<property name="transactionTimeout" value="300" />
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"
depends-on="userTransactionService">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
....
</bean>
I have a web application using JPA and JTA with Spring. I would like to support both JBoss and Tomcat. When running on JBoss, I'd like to use JBoss' own TransactionManager, and when running on Tomcat, I'd like to use JOTM.
I have both scenarios working, but I now find that I seem to need two separate Spring configurations for the two cases. With JOTM, I need to use Spring's JotmFactoryBean:
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction">
<bean class="org.springframework.transaction.jta.JotmFactoryBean"/>
</property>
</bean>
In JBoss, though, I just need to fetch "TransactionManager" from JNDI:
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="resourceRef" value="true" />
<property name="jndiName" value="TransactionManager" />
<property name="expectedType"
value="javax.transaction.TransactionManager" />
</bean>
</property>
</bean>
Is there a way to configure this so that the appropriate TransactionManager - JBoss or JOTM - is used, without the need for two different configuration files?
I think you have missed the point of JNDI. JNDI was pretty much written to solve the problem you have!
I think you can take it up a level, so instead of using the "userTransaction" or "transactionManager from JNDI" depending on your situation. Why not add the "JtaTransactionManager" to JNDI. That way you push the configuration to the JNDI where it is supposed to be instead of creating even more configuration files [ like there aren't enough already ;) ].
You can use PropertyConfigurerPlaceholder to inject bean references as well as simple values.
For example if you call your beans 'jotm' and 'jboss' then you could inject your TM like:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE">
<property name="location" value="classpath:/path/to/application.properties"/>
</bean>
<bean id="jotm">...</bean>
<bean id="jboss">...</bean>
<bean id="bean-requiring-transaction-manager">
<property name="transactionManager" ref="${transaction.strategy}"/>
</bean>
Then you can swap transaction managers using
transaction.strategy=jotm in a properties file
-Dtransaction.strategy=jotm as a system property
This is one possible approach. See my blog for a more complete example.
Hope this helps.
If you are using Spring 2.5 you can use <tx:jta-transaction-manager/>. I have not used it with JBoss but it should work for you according to section 9.8 Application server-specific integration from the Spring reference manual.
The <tx:jta-transaction-manager/> approach will look for a transaction manager in several default locations listed here. If your JBoss transaction manager is not in one of those locations, I suggest you move it, if possible, or move it in Tomcat so that both containers have their TM in the same JNDI location.
Just adding my experience here so I don't have to re-suffer the experience again.
As bmatthews68, Chochos and these posters have said, use <tx:jta-transaction-manager/> in your Spring bean file; it definitely provides the appropriate level of abstraction and there's no need to do anything extra on the Spring side.
As for Tomcat, I declared <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60" /> in the default/shared conf/context.xml file, which binds to java:comp/UserTransaction. As this is one of the places searched for by Spring, you shouldn't need to do anything else.
One gotcha though: if like me you use Maven, make sure you exclude any dependencies on the javax.transaction:jta jar or set the scope to provided. Otherwise you will experience classloader issues.