I'm currently using the #Transactional annotation to save data to a database, and would like to know how to change the transaction so it affects other resources like message queues. I didn't set up beans or anything to make dealing with the database transactional - I just added the #Transactional annotation and nothing else.
You are thinking to enter complicated and slow world called two phase commit transactions. For such case you would need to use distributed transactions manager like Atomikos. JEE has JTA (Java Transaction API) abstractions for it.
I would suggest to avoid this world as much as possible, because of slowness.
Here are few Spring Boot examples I created. They combine distributed transactions with database and JMS queue.
Combining even more than two data sources into distributed transactions would be extremely slow.
Related
Is it possible to force Hazelcast to run put(), replace(), and delete() methods on the TransactionalMap on the calling thread? I want the XA transaction to carry over from writing to Hazelcast to writing to the database in the MapStore, but Hazelcast is queueing the changes to be run on other threads, so they aren't in the same transaction context.
I've got it set up as a write-through persistence, but I see that it's queueing the TxnSetOperation and running them on a separate thread.
This is in a Spring Boot application using the Hazelcast autoconfiguration with a JPA / Hibernate store backing to PostgreSQL.
MapStore operations don't run in the same transactional context. If you want transactional persistent updates with Hazelcast, you need to use XA transactions and not enable MapStore. Then you can set the persistent store as a different XA resource in your context. You can have a check the related section in Hazelcast's reference manual: http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#providing-xa-transactions
Alsparlan's answer is partially correct, but there's no way to enlist a resource in a MapStore with the same transactional context as your actions against the Hazelcast TransactionalMap. The link he provided does NOT talk about this (unfortunately), but the Javadoc for TransactionalMap does:
When using MapStore, the call to any MapStore method is outside the transactional boundary. If you need to have an XATransaction spanning Hazelcast operations and one more other XAResources (such as a database), you should not use MapStore. Instead, enlist both resources in a transaction
I've removed my MapStore usage and wired my Spring Boot repositories directly into my services so I can make my changes to Hazelcast and my datasource in the same service methods inside the same transaction. Along with this solution to declaratively enlisting the Hazelcast XAResource this is working for me now.
I am trying to understand the transaction management in Spring, and I have got some doubts.
I read a bit about transaction management in EJB world, which can be CMT or BMT. For CMT, as per the documentation, it is Application server (e.g. JBOSS) which manages the transaction.
Now, coming to Spring transaction management, and considering using Web container only (Apache Tomcat), how does this work?
Does Spring have its own transaction management with capability of handling local transaction and global transaction (which works with 2 phase commit). Do the actual support need to come by the underlying container (in this case Apache tomcat) or support from framework is sufficient?
I am not clear how all these pieces fit together.
Can anyone help me understand this?
Spring doesn't include any kind of transaction capability of its own, it only provides ways to connect to transaction functionality provided by the container or by standalone libraries.
If you run your application on Tomcat and don't provide any transaction manager libraries like bitronix, then you get only local jdbc transactions provided by the servlet container.
When you read the bullet points at https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html notice it says spring is providing abstractions, that means it is providing access through its own apis and using aop to make transactions nonintrusive, but not providing any implementation of transactional functionality. It's facilitating gluing things together, which is the main thing spring does.
Can anybody provide me an example for Spring Transaction management? I have queries like how it basically works? In Java EE , Application server container used to take care of the transaction using EJB's. I wanted to know ,how spring frameworks helps in the same way?
I hope Introduction to Spring Framework transaction management will help.
The Spring Frameworkâs transaction management support doesn't requires an application server.
Spring Frameworks Claims declarative transactions of spring framework offer more powerful and more productive programming model than EJB CMT.
Compared to transaction management using EJB Spring frameworks enables application developers to use a consistent programming model in any environment. Once we write our code once it can benefit from different transaction management strategies in different environments.
The Spring Framework provides both declarative and programmatic transaction management.
programmatic transaction management - developers work with the Spring Framework transaction abstraction, which can run over any underlying transaction infrastructure.
declarative model - developers typically write little or no code related to transaction management, and hence do not depend on the Spring Framework transaction API, or any other transaction API.
Spring framework provides central interface for transaction
management i.e. 'PlatformTransactionManager'
There are many implementations if it, one which you can quickly
relate to is DataSourceTransactionManager.
Now, this transaction manager does the lower level work of beginning,
rollback and commit of transaction for you.
If you see the source of DataSourceTransactionManager you will see
the same kind of transaction management code that you have seen when
you handle transaction using JDBC api
But importantly, all these things happen declaratively as part of
proxy advise using Spring AOP
Begin Transaction
DataSource ds = /*initialize DS here*/
Connection con = ds.getConnection();
con.setAutoCommit(false);
Commit Transaction
com.commit();
from Spring documentation(http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html):
16.2.1 Global transactions
Global transactions enable you to work with multiple transactional
resources, typically relational databases and message queues. The
application server manages global transactions through the JTA, which
is a cumbersome API to use (partly due to its exception model).
Furthermore, a JTA UserTransaction normally needs to be sourced from
JNDI, meaning that you also need to use JNDI in order to use JTA.
Obviously the use of global transactions would limit any potential
reuse of application code, as JTA is normally only available in an
application server environment.
Previously, the preferred way to use global transactions was via EJB
CMT (Container Managed Transaction): CMT is a form of declarative
transaction management (as distinguished from programmatic transaction
management). EJB CMT removes the need for transaction-related JNDI
lookups, although of course the use of EJB itself necessitates the use
of JNDI. It removes most but not all of the need to write Java code to
control transactions. The significant downside is that CMT is tied to
JTA and an application server environment. Also, it is only available
if one chooses to implement business logic in EJBs, or at least behind
a transactional EJB facade. The negatives of EJB in general are so
great that this is not an attractive proposition, especially in the
face of compelling alternatives for declarative transaction
management.
For me it looks like distributed transaction description(XA).
Am I wrong or Spring really calls XA tranactions as global.
I'm using Oracle 11g for my database and its Oracle Streams AQ feature as JMS implementation.
For all I know, it should be possible to implement a Spring based message-driven POJO (MDP) that uses the same data source for both transactional data access and JMS transactions -- all without XA-Transactions (IIRC, this was marketed as a feature of SpringSource Advanced Pack for Oracle).
Is this possible using Hibernate as well? Ideally, my MDP would start a JMS transaction and read a message from a queue, then re-use the transaction for data access through Hibernate. If anything goes wrong, the JMS and database transaction would both be rolled back, without using 2-phase commit (2PC).
I'm not much of a transaction guru, so before I start digging deeper, can anyone confirm that this is possible and makes sense as well?
Update:
What I want is an implementation of the Shared Transaction Resource pattern. The sample code demonstrates it for ActiveMQ and JDBC, but I need to use Oracle Streams AQ and Hibernate.
Update2:
The SpringSource Advanced Pack for Oracle has been open sourced as part of Spring Data JDBC and it "provides the option of using a single local transaction manager for both
database and message access without resorting to expensive distributed 2-phase commit
transaction management".
2PC shouldn't be necessary, as you say, since the appserver should take care of it. However, you'll pretty much have to use JTA (i.e. JavaEE container) transactions, rather than vanilla DataSource transactions, since JMS only works with JTA.
This isn't a big deal, it's just a bit more fiddly:
Your Spring config should use
<jee:jndi-lookup/> to get a
reference to your container's
DataSource, and you inject that
data source into your spring-managed
hibernate SessionFactory.
You then need to introduce a transaction manager into the context (<tx:jta-transaction-manager/> should work in most app-servers).
In your Spring JMS MessageListenerContainer, plug the above transaction manager reference into it.
Does that all make sense, or should I elaborate? This setup should ensure that the container-managed transactions are held across JMS and Hibernate interactions.