Spring transactions on recursive calls - java

I have a method that starts a transaction programmatically using transaction template from Spring.
Void methodA() {
TransactionTmeplate..........
Setpropgation to requires new....
/// do my stuff in trasaction
}
So if I have another class which calls this method it creates a transaction, as I would expect. But what happens if this method is entered again from the same calling thread. Does another transaction get created?
Example:
MethodCaller -> methodA (transaction created) -> methodD -> methodA(??)
Following on:
Also if class is #autowired, would two calling threads ever share the same transaction, considering one instance exists?
I would assume not as they have there own own entry on the stack for the method.

The javadoc on Propagation.REQUIRES_NEW is pretty clear, I am not sure whether it could be better explained.
As for the different threads calling your method: the TransactionManager will make sure that threads won't interleave with each other regarding transactions.
But having a method that is re-entrant and always starts a new transaction indicates that your application is not properly layered. Try to do some refactoring, and make sure that the method responsibile for starting a new transaction never gets called recursively.

Related

Does Spring #Transactional annotated on method ensure the flush of data exactly when the method ends?

I have this simplified escenario in a Spring application with Java and Hibernate for persistence provider:
#Transactional
void method1() { // some savings}
#Transactional
void method2() { // some savings}
When I run a parent method (not annotated as transactional)
void parentMethod() {
method1();
method2();
}
Can I make sure that when the method finishes the changes are impacted in the database immediately before the method is called?
Or that changes could be flush to database later, with some delay?
I'm interested on other applications seeing the changes made in database immediately when method1 finishes (and before method2 be called)
Update
My parent method is not defined in the same class, and the class and firm of the my parent method has not #Transactional annotation
Thanks!
To your question ... ensure the flush of data exactly when the method ends? No, not exactly when the method ends, but latest when the method ends.
Within transaction you can flush the current state as many times as you wish. Flushing means that you synchronize your JPA session with database. See Hibernate doc regarding this. Flushing does not mean your changes are durable; if transaction rolls back later on, these changes will be automatically reverted. The commit operation performs different steps, one of them is to ensure that the JPA (e.g. Hibernate) session is synchronized with DB, and, if needed, calls flush. If the session is already synchronized, flush will be skipped.
In the comments you wrote that the class and the method parentMethod are not transactional and that method1() and method2() are defined in a separate class. In such case when the method1() is called, a new transaction will be started. When this method ends, this transaction will be committed. Any changes in the database done by this method will be durable, i.e. no matter what happens later on (exceptions, roll backs in other methods) these changes will remain in the database.
Some information relevant to your case can be found here because following is important:
If these methods are in the same class or not and
If you use Spring own AOP or AspectJ. Besides it depends on the class where your parentMethod is defined. If it is transactional, then these 2 calls will run within the existing transaction and there will be no commit after the 1st one is committed.

EJB Container Manage transaction execution

In the J2EE doc it says,
Although beans with container-managed transactions require less
coding, they have one limitation: When a method is executing, it can
be associated with either a single transaction or no transaction at
all.
Question 1. But what i understand is unless we declare transaction attribute with NotSupported or Never, when the method is executing (suppose with default Required attribute) its guaranteed the method to be run with in a transaction right?
Also I need to know suppose with container manager transaction with default Required attribute below pseudo code happening,
class bean1{
public void m1(){
bean2.m2();
}
}
class bean2{
public void m2(){
}
}
**Question 2.**In this case does m2() in bean2 ran with in a new transaction or ran under same transaction for m1() in bean1?
Question 1. But what i understand is unless we declare transaction
attribute with NotSupported or Never, when the method is executing
(suppose with default Required attribute) its guaranteed the method to
be run with in a transaction right?
Yes, the default for container-managed transaction is Required, which will start a transaction if one does not exist. The paragraph you quoted is somewhat unusual (obviously either a transaction exists or not), so I'm missing context to give a more complete explanation.
Question 2. In this case does m2() in bean2 ran with in a new
transaction or ran under same transaction for m1() in bean1?
Assuming they are both EJBs and no other transaction attributes are applied (i.e., both EJB methods are using the default Required attribute), then both methods will use the same transaction. The semantics for all the transaction attributes are described succinctly in the javadoc for TransactionAttributeType.

Spring transactions and their interaction with the synchronized keyword

I have a DAO class that uses Spring JDBC to access an SQLite database. I have declared transactions on the DAO methods themselves since my service layer never combines queries in a transaction.
Since I use a few worker threads in parallel but only one thread can update an SQLite DB at the same time, I use synchronized to serialize access to the DAO.
At first, I synchronized externally from my service class, for example:
synchronized (dao) {
dao.update(...);
}
Then, I figured I might as well get rid of the external synchronization and put synchronized on the DAO method itself:
public synchronized void update(...) {
// Spring JDBC calls here
}
The strange thing is: my queries now take twice the time they used to!
Why?
Well, one difference is obvious:
synchronized (dao) {
// here you are synchronizing on the transactional proxy
}
public synchronized void update(...) {
// and here you are synchronizing on the target class, *inside* the proxy
}
What the implications of this are depends on your other code, but that's the obvious difference.
My guess is your update method or entire class is annotated with Transactional or wrapped by transactional proxy through other means. This means whenever you call dao's method, the transactional proxy retrieves db connection from the pool, opens a transaction and then calls the real method.
In your first scenario you synchronize before even reaching the proxy, thus no connection and transaction magic happens. In the second scenario you do the waiting call after that.
If there are multiple threads trying to perform simultaneous updates there will be only one doing the update and the rest will be first opening new connections and then waiting for dao access. As a consequence instead of one connection being constantly reused you will have multiple connections in use. I can only guess how this really affects the performance but you can experiment with different pool size starting with one.

Propagation behaviour of transaction

I am using annotation based declarative approach for spring aop.
sample code
ClassA{
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
add()
{
method1();
method2();
method3();
}
}
But I have still doubt on use of propagation.does propagation.Requires_New means that each request will start new transaction.
Second question:
Does failure of any method like method2,method3 will cause the transaction to rollback?
I will be very happy if any can help me to leans transaction propagation.
can someone provide me a real world example where we need a participate in existing transaction.because I visualise that add function that we are using in above example will be independent for all users,or any other function will be independent to each user who is calling. I am not able to find example where other propagation behaviour like PROPAGATION_SUPPORTS ,PROPAGATION_MANDATORY,PROPAGATION_REQUIRES_NEW etc. are used
Answering this comment, not the actual question:
transaction are session specific or
request specific – Vish 3 hours ago
Neither. request and session are both web-specific scopes, while the Spring Transaction abstraction has nothing to do with web technologies.
The scope of #Transactional is per method invocation, as #Transactional is implemented through Spring AOP. The transactional state is kept in ThreadLocal variables which are initialized when the outermost #Transactional method is entered and cleared with commit or rollback when it is left. This whole abstraction works on Java method level, and hence does not require or profit from a web container.
And in response to this Question in the comment below:
thanks #sean,i am stil not able to get
answer where other propagation
behaviour like PROPAGATION_SUPPORTS
,PROPAGATION_MANDATORY,PROPAGATION_REQUIRES_NEW
etc are used. please refer above for
whole question
Here's the list of Propagation values with my comments:
MANDATORY
Support a current transaction, throw an exception if
none exists.
Does not start a new Transaction, just checks whether a transaction is active (must be inside either another #Transactional method call or a programmatically created transaction)
NESTED
Execute within a nested transaction if a current transaction
exists, behave like
PROPAGATION_REQUIRED else.
Start a nested transaction if a transaction exists, start a new transaction otherwise.
NEVER
Execute non-transactionally, throw an exception if a transaction
exists.
Does not start a transaction. Fails if a transaction is present.
NOT_SUPPORTED
Execute non-transactionally, suspend the current transaction if one
exists.
Does not start a transaction. Suspends any existing transaction.
REQUIRED
Support a current transaction, create a new one if none
exists.
If a transaction exists, use that, if not, create a new one. In 95% of cases, this is what you need.
REQUIRES_NEW
Create a new transaction, suspend the current transaction if one
exists.
Always creates a new transaction, no matter if an existing transaction is present. If there is, it will be suspended for the duration of this method execution.
SUPPORTS
Support a current transaction, execute
non-transactionally if none exists.
Can use a transaction if one is present, but doesn't need one (and won't start a new one either)
In most cases, REQUIRED is what you need (hence it's the default in the #Transactional annotation). I have personally never seen any other value but REQUIRED and REQUIRES_NEW in use.
Transaction propagation indicates what should be the behaviour of the given method when it is invoked. REQUIRES_NEW means that a new transaction should always be started, even if there is an ongoing transaction.
If method1(), for example, defines REQUIRES_NEW, than it will execute in a new transaction.
An exception will rollback the current active transaction, yes.
Yes. Requires_New means that each request will start new transaction. and Yes failure in method2,method3 will cause the transaction to rollback, depending on the rollback properties.
check Transactional properties.

Testing simultaneous calls to transactional service

How should I test a service method that is transactional for its simultaneous use (it updates a database row by decreasing a value)?
I have setup a JUnit test class with SpringJunit4ClassRunner and components are #autowired.
Just spawning threads which would call the method doesn't seem to work. I'm not sure whether this has something to do with the Spring proxy mechanism.
What I would like to achieve is to create a situation where simultaneously two threads are "inside" the tested method and other one will fail and rollback. e.g. The row value is 3 and both method calls try to decrease the value by 2; if the method wouldn't work, the value would be -1, which is illegal. But I want that either both of the calls fail and rollback, or failing the one that tries to update it an instant later than the other.
Is this even possible?
The first problem is that the transaction context is bound to one thread (with a thread local). So you have to start a transaction in each of your threads. (I think there is no support for this in spring. You can start transaction programmatically with the transaction manager.)
The code you described: read, decrement, write does only work with the right isolation level (serialized and repeatable read would work).
After this setup is done, you can test the behavior by blocking one thread while he has the database lock. You can use a Latch for this.
The thread without database lock will now still not rollback. It will block until the database lock is available again. The scheme you're describing is quite similiar to Optimistic concurrency control so maybe this is already implemented.

Categories

Resources