Multiple DataSources, Multiple Transaction Managers. Which one is used? - spring

I have a SI configuration that is made up of multiple data sources.
Say: DataSource A - Connects to Oracle
DataSource B - Connects to DB2
DataSource C - Connects to MySQL
One of the SI sub-flows writes to two of these data sources and I would like to do that in a 1-PC transaction.
So I define a ChainedTransactionManager with DataSource A and DataSource B. Let's call this chainedTransactionMgr
I also have two jdbc templates templateA(with A as it's datasource) and templateB (with B as it's datasource)
Let's say that I have a flow where I send a message to a publish-subscribe channel with two recipients that are service-activators that just use templateA and templateB to write the msg to their respective data source. Will the chained transaction manager be utilized in this flow?

Everything what you say is good and correct.
Only the problem that you have to do all the job in a single thread, because that is only the way how you can involve several resources to one transaction. Actually this is a case when you use publish-subscribe-channel with default configuration, where in the same thread first subscriber will call its templateA; and only after that the second service will call its templateB.
So, the ChainedTransactionManager should be configured with that order, too.
And from here it even doesn't matter if you use XA transaction manager. The main point is single thread.

Related

Spring Transaction Management- Multiple request to same URL

I am trying to create an API in Spring Boot using #Transactional annotation regarding bank fund transfer.
Now I want to know - if there are multiple calls to the same API at the same time, how to manage transaction between them. Suppose for example transferBalance method is called by Transaction X which transfers funds from accounts A to B and another transaction Transaction Y transfer funds from B to C. Both transactions occur at the same time. How would these transactions be handled? What propagation should it have and also what about the isolation?
Check this below changes: for your case check bold description below.
if more than one transaction can also go with SERIALIZED
Isolation level defines how the changes made to some data repository by one transaction affect other simultaneous concurrent transactions, and also how and when that changed data becomes available to other transactions. When we define a transaction using the Spring framework we are also able to configure in which isolation level that same transaction will be executed.
#Transactional(isolation=Isolation.READ_COMMITTED)
public void someTransactionalMethod(Object obj) {
}
READ_UNCOMMITTED isolation level states that a transaction may read data that is still uncommitted by other transactions.
READ_COMMITTED isolation level states that a transaction can't read data that is not yet committed by other transactions.
REPEATABLE_READ isolation level states that if a transaction reads one record from the database multiple times the result of all those reading operations must always be the same.
SERIALIZABLE isolation level is the most restrictive of all isolation levels. Transactions are executed with locking at all levels (read, range and write locking) so they appear as if they were executed in a serialized way.
Your doubt has nothing to do with #Transactional.
Its simple question of concurrency.
Actually both the transaction, form a to b and form b to c can work concurrently.
By putting #Transactional states something like
works out whether a given exception should cause transaction rollback by applying a number of rollback rules, both positive and negative. If no rules are relevant to the exception, it behaves like DefaultTransactionAttribute (rolling back on runtime exceptions).

Configuring transaction across multiple resources using spring framework?

I understand the fact that a transaction that spans multiple transactional resources is called a global transaction.
Question 1:
Is this just an another name for distributed transaction or is that something different?
Question 2:
Have gone through spring's documentation on Transaction Management.
What i could infer from that is
a. JTA is purely designed for distributed transactions.
b. Only through EJBs and EJB CMT, we could enforce distributed transactions.
c. If EJBs, then it mandates an Application Server and indirectly JNDI too.
What is Spring's counterpart to facilitate global/distributed transactions?
Question 3:
If we don't want to go with an application server with JTA capability,
should we be using Atomikos / JOTM like standalone Transaction managers to enforce global transactions?
Question 4:
A simple usecase of updating Table A in DB_1 (MySql) and Table B in DB_2 (Oracle) under a single transaction:
What is Spring's answer to this usecase?
Yes
a) No, not every transaction will be distributed, only if more than one resource is involved. The TM handles the management of the transactions executed on the involved resources
b) No, there are transactionsmanagers usable outside ejb-servers like atomikos, bitronix,... but I am not sure what you mean by enforce, as I wrote earlier, distributed transactions are used when necessary.
c) yes
d) Springs counterpart
if you want to use transactions on multiple resources at the same time yes.
you define two datasources in a way, that they let a TM handle their resources. Both MySql and Oracle provide XA-Datasources which allow it to handle distributed transactions. You define a TM and make it possible to annotate your beans with Transaction Attributes. There are many tutorials out there which show how this can be done.
Additional remarks:
Meanwhile transactions are also included in the CDI-Spec. So you can also use CDI.
Handle the distributed transactions wisely. The two way commit makes it almost impossible to set a reasonable transaction timeout. There are development-sites where distributed transactions only are used between one SQL-DBMS-Resource and one JMS-Resource if necessary.

Clustering the Batch Job & distributing the data load

I have Batch Processing project, wanted to cluster on 5 machines.
Suppose I have input source is database having 1000 records.
I want to split these records equally i.e. 200 records/instance of batch job.
How could we distribute the work load ?
Given below, is the workflow that you may want to follow.
Assumptions:
You have the necessary Domain Objects respective to the DB table.
You have a batch flow configured wherein, there is a
reader/writer/tasklet mechanism.
You have a Messaging System (Messaging Queues are a great way to
make distributed applications talk to each other)
Input object is an object to the queue that contains the set of
input records split as per the required size.
Result object is an object to the queue that contains the processed
records or result value(if scalar)
The chunkSize is configured in a property file. Here 200
Design:
In the application,
Configure a queueReader to read from a queue
Configure a queueWriter to write to a queue
If using the task/tasklet mechanism, configure different queues to carry the input/result objects.
Configure a DB reader which reads from a DB
Logic in the DBReader
Read records from DB one by one and count of records maintained. if
(count%chunkSize==0) then write all the records to the inputMessage
object and write the object to the queue.
Logic in queueReader
Read the messages one by one
For each present message do the necessary processing.
Create a resultObject
Logic in the queueWriter
Read the resultObject (usually batch frameworks provide a way to
ensure that writers are able to read the output from readers)
If any applicable processing or downstream interaction is needed,
add it here.
Write the result object to the outputQueue.
Deployment
Package once, deploy multiple instances. For better performance, ensure that the chunkSize is small to enable fast processing. The queues are managed by the messaging system (The available systems in the market provide ways to monitor the queues) where you will be able to see the message flow.

Simple DataSource (Not XA) in persistence.xml

If I am using "transaction-type" JTA in "persistence.xml" ,
then is it mandatory to use XA type data sources in "" element ?
or we can also using simple data source also .
Thanks !!
That depends. If you want to use JTA and have multiple participants (i.e. datasources, jms connections etc) then you really must have an XA capable datasource. When you don't have this you have problems starting a distributed transaction.
If this is the only participant ever then you might even wonder why do you want JTA transactions and stick with resource local transactions.

Spring Bean Hangs on Method with #Transactional

Just a little background , I'm a new developer who has recently taken over a major project after the senior developer left the company before I could develop a full understanding of how he structured this. I'll try to explain my issue the best I can.
This application creates several MessageListner threads to read objects from JMS queues. Once the object is received the data is manipulated based on some business logic and then mapped to a persistence object to be saved to an oracle database using a hibernate EntityManager.
Up until a few weeks ago there hasn't been any major issues with this configuration in the last year or so since I joined the project. But for one of the queues (the issue is isolated to this particular queue), the spring managed bean that processes the received object hangs at the method below. My debugging has led me to conclude that it has completed everything within the method but hangs upon completion. After weeks of trying to resolve this I'm at end of my rope with this issue. Any help with this would be greatly appreciated.
Since each MessageListner gets its own processor, this hanging method only affects the incoming data on one queue.
#Transactional(propagation = Propagation.REQUIRES_NEW , timeout = 180)
public void update(UserRelatedData userData, User user,Company company,...)
{
...
....
//business logic performed on user object
....
......
entityMgr.persist(user);
//business logic performed on userData object
...
....
entityMgr.persist(userData);
...
....
entityMgr.flush();
}
I inserted debug statements just to walk through the method and it completes everything including entityMgr.flush.().
REQUIRES_NEW may hang in test context because the transaction manager used in unit testing doesn't support nested transactions...
From the Javadoc of JpaTransactionManager:
* <p>This transaction manager supports nested transactions via JDBC 3.0 Savepoints.
* The {#link #setNestedTransactionAllowed "nestedTransactionAllowed"} flag defaults
* to {#code false} though, since nested transactions will just apply to the JDBC
* Connection, not to the JPA EntityManager and its cached entity objects and related
* context. You can manually set the flag to {#code true} if you want to use nested
* transactions for JDBC access code which participates in JPA transactions (provided
* that your JDBC driver supports Savepoints). <i>Note that JPA itself does not support
* nested transactions! Hence, do not expect JPA access code to semantically
* participate in a nested transaction.</i>
So clearly if you don't call (#Java config) or set the equivalent flag in your XML config:
txManager.setNestedTransactionAllowed(true);
or if your driver doesn't support Savepoints, it's "normal" to get problem with REQUIRES_NEW...
(Some may prefer an exception "nested transactions not supported")
This kind of problems can show up when underlying database has locks from uncommitted changes.
What I would suspect is some other code made inserts/deletes on userData table(s) outside transaction or in a transaction which takes very long time to execute since it's a batch job or similar. You should analyze all the code referring to these tables and look for missing #Transactional.
Beside this answer, you may also check for the isolation level of your transaction — perhaps it's too restrictive.
Does the update() method hang forever, or does it throw an exception when the timeout elapses?
Unfortunately I have the same problem with Propagation.REQUIRES_NEW. Removing it resolves the problem. The debugger shows me that the commit method is hanging (invoked from #Transactional aspect implementation).
The problem appears only in the test spring context, when the application is deployed to the application server it works fine.

Resources