Concurrency issue of #Transaction and synchronized in spring - spring

Synchronized does not work even if synchronized is added to the method to solve the concurrency issue within the transaction.
For example, the code is as follows.
#Transactional
public synchronized Post likePost(Long postId) {
var post = postRepository.findById(postId).orElseThrow();
post.incrementLikeCount();
return post;
}
This is known to be a problem that occurs when synchronized is synchronized through Monitor and other transactions are executed before committing within the transaction. (Please point it out if it's wrong.) I referred to the link below.
Spring #Transactional with synchronized keyword doesn't work
As a solution to these problems, applying synchronized before transactions are applied or removing transactions (#Transactional) does not cause concurrency issues, but in the latter case, performance is very inefficient because only one thread per method is accessible.
In the former case, there is no concurrency issue, and the performance test was not bad, is there any problem?

Related

Spring jpa: Do I need to add #Transactional annotation on retrieval queries

I am using EntityManger for the retrieval queries in my spring boot application. An example snippet is given below.
#Repository
public class EntityManagerUtil {
#PersistenceContext
private EntityManager entityManager;
public List<Employee> getAll(){
// Use entityManager here
}
}
I need some clarity on the below questions.
a. Is EntityManger will be created for every call (or) will it be a singleton? (I tried printing entityManager, it is returning the same object for all the calls)
b. Is this approach leads to any connection leaks?
c. Do I need to put #Transactional annotation on reading operations?
I am using spring boot version 2.0.3-release
a) See M Deinum's comments about the injected EntityManager being a proxy. The normal situation for JPA is to have an EntityManager tied to each thread, Spring sets this up for you and provides a proxy to delegate to the actual EntityManager. So this arrangement is safe.
b) Connection leaks happen when you don't return a database connection to the pool. Spring takes care of providing a connection and cleaning up resources so in the normal course of things you shouldn't get connection leaks. If you ignore the facilities Spring gives you like JdbcTemplate and insist on writing your own JDBC code, then you can cause resources to leak. If your code tries to use an EntityManager intended for another thread you will get an exception, it will not fail silently, and it will not (in itself) cause a connection leak.
c) You are using an RDBMS so you will have a transaction.
Apparently some people think transactions are optional, but they really aren't. If you don't specify them then Spring will wrap each operation in its own transaction. Not only are you just better off in general being explicit about this, but you can mark the transaction as readonly, which lets Spring perform some optimizations, see Oliver Drotbohm's answer for details. So maybe you can get by without it for some cases (such as, each http request results in only one database operation), but it is in your interest to use it.

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).

Spring Declarative transaction management with hibernate using #Transactional

My requirement is to save data in 5 tables through 5 methods .
These 5 methods are wrapped under single parent method which is annotated with #Transactional.
Am calling this parent method 100 times in a loop.
Constraints are
Transaction has to be rolled back even if one method fails in one iteration.(i.e 5 methods has to be saved without exception) and the flow should continue for next iteration.
One iteration fail should not rollback all the other iterations. I.,e In 100 iterations if 5th iteration fails and all the other iterations are succeeded, then all the 99 iteration's operations should get committed.
It is OK if transaction is committed after successfully executing all the 5 methods in one iteration.
Issue is
If, 5th iteration is failed, then in next iteration, old values are showing in the entity.
I have used session.clear() method in catch block to avoid that. is that correct? But the issue is,
even after successful insertion of five methods in next iteration, the transaction is getting rolled-back. And all the previous 4 iteration's data state in session is getting cleared.
am using Spring 3.2, Hibernate3, HibernateTransactionManager
I forgot to write the caller method and calling method in different beans. Hence it is getting rolled back. Spring Transaction uses AOP. A proxy is created for the methods which are annotated with #Transactional. This bean method should be called from another bean, which I got form the Spring documentation
You want your iterations succeed or fail independently one from another. You want a failure in any of the 5 steps of the individual iteration to fail entire iteration and to roll back the corresponding transaction.
It is clear that you want to have transaction boundary at the level of the service call that corresponds to a single iteration. Now, the rule of the thumb is to allocate a Hibernate session per transaction. So, a Hibernate session should be created at the beginning of each iteration and be disposed of at the end. That would prevent random junk, like entites that failed to be persisted to the database in the previous trnsactions, from showing up in the Hibernate session.
Hope this helps.
Have a look into propagation levels of spring transactions here and choose whatever best suits your requirements. An example which does what you need is as follow (you may mark myService as #Transactional as well) but you might like to have a look at other levels.
public void myService() {
// call myTaskCaller as many times as you like
}
#Transactional(propagation=Propagation.REQUIRES_NEW)
public void myTaskCaller() {
task1();
task2();
task3();
task4();
task5();
}
private void task1(){}
private void task2(){}
private void task3(){}
private void task4(){}
private void task5(){}

Grails service transactional behaviour

In a Grails app, the default behaviour of service methods is that they are transactional and the transaction is automatically rolled-back if an unchecked exception is thrown. However, in Groovy one is not forced to handle (or rethrow) checked exceptions, so there's a risk that if a service method throws a checked exception, the transaction will not be rolled back. On account of this, it seems advisable to annotate every Grails service class
#Transactional(rollbackFor = Throwable.class)
class MyService {
void writeSomething() {
}
}
Assume I have other methods in MyService, one of which only reads the DB, and the other doesn't touch the DB, are the following annotations correct?
#Transactional(readOnly = true)
void readSomething() {}
// Maybe this should be propagation = Propagation.NOT_SUPPORTED instead?
#Transactional(propagation = Propagation.SUPPORTS)
void dontReadOrWrite() {}
In order to answer this question, I guess you'll need to know what my intention is:
If an exception is thrown from any method and there's a transaction in progress, it will be rolled back. For example, if writeSomething() calls dontReadOrWrite(), and an exception is thrown from the latter, the transaction started by the former will be rolled back. I'm assuming that the rollbackFor class-level attribute is inherited by individual methods unless they explicitly override it.
If there's no transaction in progress, one will not be started for methods like dontReadOrWrite
If no transaction is in progress when readSomething() is called, a read-only transaction will be started. If a read-write transaction is in progress, it will participate in this transaction.
Your code is right as far as it goes: you do want to use the Spring #Transactional annotation on individual methods in your service class to get the granularity you're looking for, you're right that you want SUPPORTS for dontReadOrWrite (NOT_SUPPORTED will suspend an existing transaction, which won't buy you anything based on what you've described and will require your software to spend cycles, so there's pain for no gain), and you're right that you want the default propagation behavior (REQUIRED) for readSomething.
But an important thing to keep in mind with Spring transactional behavior is that Spring implements transaction management by wrapping your class in a proxy that does the appropriate transaction setup, invokes your method, and then does the appropriate transaction tear-down when control returns. And (crucially), this transaction-management code is only invoked when you call the method on the proxy, which doesn't happen if writeSomething() directly calls dontReadOrWrite() as in your first bullet.
If you need different transactional behavior on a method that's called by another method, you've got two choices that I know of if you want to keep using Spring's #Transactional annotations for transaction management:
Move the method being called by the other into a different service class, which will be accessed from your original service class via the Spring proxy.
Leave the method where it is. Declare a member variable in your service class to be of the same type as your service class's interface and make it #Autowired, which will give you a reference to your service class's Spring proxy object. Then when you want to invoke your method with the different transactional behavior, do it on that member variable rather than directly, and the Spring transaction code will fire as you want it to.
Approach #1 is great if the two methods really aren't related anyway, because it solves your problem without confusing whoever ends up maintaining your code, and there's no way to accidentally forget to invoke the transaction-enabled method.
Approach #2 is usually the better option, assuming that your methods are all in the same service for a reason and that you wouldn't really want to split them out. But it's confusing to a maintainer who doesn't understand this wrinkle of Spring transactions, and you have to remember to invoke it that way in each place you call it, so there's a price to it. I'm usually willing to pay that price to not splinter my service classes unnaturally, but as always, it'll depend on your situation.
I think that what you're looking for is more granular transaction management, and using the #Transactional annotation is the right direction for that. That said, there is a Grails Transaction Handling Plugin that can give you the behavior that you're looking for. The caveat is that you will need to wrap your service method calls in a DomainClass.withTransaction closure and supply the non-standard behavior that you're looking for as a parameter map to the withTransaction() method.
As a note, on the backend this is doing exactly what you're talking about above by using the #Transactional annotation to change the behavior of the transaction at runtime. The plugin documentation is excellent, so I don't think you'll find yourself without sufficient guidance.
Hope this is what you're looking for.

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