Spring Bean Hangs on Method with #Transactional - spring

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.

Related

How to deal with Spring hibernate no lock aquired exception inside a transaction

I have applied #Transactional in my interface, and inside my serviceImpl, the corresponding method is calling some other methods, one method is reading, another method is writing. Although I have anotated as Transactional, when I am giving concurrent request, my insert method is throwing org.hibernate.exception.LockAcquisitionException: error.
Another problem is, this insert method is a shared method and it performs the insert method like Dao.save(obj) . Dao.save() is a generic method So i can not do anything here. I have to apply something on interface to avoid no lock aquired exception.
Is it possible to tell wait untill lock is aquired? Or retry if transaction is failed? Or lock all the tables until the transaction is completed so that another request can not access the relevent resources?
My hibernate version is 3.x, And database is mysql 5.6
The best way to do this is,
Mark your methods transactional
In your mysql database settings set the transaction isolation level as SERIALIZABLE

Can the rollback of Spring declarative transaction be postponed

Question:
Is there a way to allow Spring declarative transaction to postpone the rollback on exception ?
Use case:
I have to process several entities together in a single transaction.
The result of processing a single entity are a few new records in the DB and a few updates to existing ones.
If processing of any of those entities results in an exception, the transaction needs to be rolled back. So, all entities must be processed successfully in order for transaction to be committed.
The twist: I want to detect all the entities for which processing ends up with exception in one go. I do not want to run processing once, fail on entity No5, fix the issues on entity No5, and then run processing again only to be greeted by an exception on entity No7.
So, what I am trying to achieve is to gather all the errors on entities that are in a faulty state and notify someone to fix them. Due to this, I want the transaction that encapsulates all entities processing to carry on till the last entity and only then I want a rollback to happen.
What I tried so far:
Using propagation = NESTED like this:
#Transactional
void processAllEntities() {
entities = fetchEntities();
for (entity : entities) {
processSingleEntity();
}
}
#Transactional(propagation = NESTED)
void processSingleEntity(entity) {
do stuff;
}
Please note that methods above are in different #Component annotated classes and processAllEntities() is invoked from a third class.
This failed because JpaDialect does not support savepoints.
I tried to switch to DataSourceTransactionManager as suggested in the javadoc of Propagation.NESTED but then nothing is persisted since this transaction manager seems to be JPA unaware and my whole model is mapped with JPA annotations and I'm using spring-data-jpa for persistence.
Any ideas and feedback are welcome. Thanks.

Why does Hibernate not support nested transactions outside of Spring?

I am using Hibernate4 but not Spring. In the application I am developing I want to log a record of every Add, Update, Delete to a separate log table. As it stands at the moment my code does two transactions in sequence, and it works, but I really want to wrap them up into one transaction.
I know Hibernate does not support nested transactions, only in conjunction with Spring framework. I´ve read about savepoints, but they´re not quite the same thing.
Nothing in the standards regarding JPA and JTA specification has support for nested transactions.
What you most likely mean with support by spring is #Transactional annotations on multiple methods in a call hierarchie. What spring does in that situation is to check is there an ongoing transaction if not start a new one.
You might think that the following situation is a nested transaction.
#Transactional
public void method1(){
method2(); // method in another class
}
#Transactional(propagation=REQUIRES_NEW)
public void method2(){
// do something
}
What happens in realitiy is simplified the following. The type of transactionManager1 and transactionManager2 is javax.transaction.TransactionManager
// call of method1 intercepted by spring
transactionManager1.begin();
// invocation of method1
// call of method 2 intercepted by spring (requires new detected)
transactionManager1.suspend();
transactionManager2.begin();
// invocation of method2
// method2 finished
transactionManager2.commit();
transactionManager1.resume();
// method1 finished
transactionManager1.commit();
In words the one transaction is basically on pause. It is important to understand this. Since the transaction of transactionManager2 might not see changes of transactionManager1 depending on the transaction isolation level.
Maybe a little background why I know this. I've written a prototype of distributed transaction management system, allowing to transparently executed methods in a cloud environment (one method gets executed on instance, the next method might be executed somewhere else).

Inject Session object to DAO bean instead of Session Factory?

In our application we are using Spring and Hibernate.
In all the DAO classes we have SessionFactory auto wired and each of the DAO methods are calling getCurrentSession() method.
Question I have is why not we inject Session object instead of SessionFactory object in prototype scope? This will save us the call to getCurrentSession.
I think the first method is correct but looking for concrete scenarios where second method will throw errors or may be have bad performance?
When you define a bean as prototype scope a new instance is created for each place it needs to be injected into. So each DAO will get a different instance of Session, but all invocations of methods on the DAO will end up using the same session. Since session is not thread safe it should not be shared across multiple threads this will be an issue.
For most situations the session should be transaction scope, i.e., a new session is opened when the transaction starts and then is closed automatically once the transaction finishes. In a few cases it might have to be extended to request scope.
If you want to avoid using SessionFactory.currentSession - then you will need to define your own scope implementation to achieve that.
This is something that is already implemented for JPA using proxies. In case of JPA EntityManager is injected instead of EntityManagerFactory. Instead of #Autowired there is a new #PersistenceContext annotation. A proxy is created and injected during initialization. When any method is invoked the proxy will get hold of the actual EntityManager implementation (using something similar to SessionFactory.getCurrentSession) and delegate to it.
Similar thing can be implemented for Hibernate as well, but the additional complexity is not worth it. It is much simpler to define a getSession method in a BaseDAO which internally call SessionFactory.getCurrentSession(). With this the code using the session is identical to injecting session.
Injecting prototype sessions means that each one of your DAO objects will, by definition, get it's own Session... On the other hand SessionFactory gives you power to open and share sessions at will.
In fact getCurrentSession will not open a new Session on every call... Instead, it will reuse sessions binded to the current session context (e.g., Thread, JTA Transacion or Externally Managed context).
So let's think about it; assume that in your business layer there is a operation that needs to read and update several database tables (which means interacting, directly or indirectly, with several DAOs)... Pretty common scenario right? Customarily when this kind of operation fails you will want to rollback everything that happened in the current operation right? So, for this "particular" case, what kind of strategy seems appropriate?
Spanning several sessions, each one managing their own kind of objects and bound to different transactions.
Have a single session managing the objects related to this operation... Demarcate the transactions according to your business needs.
In brief, sharing sessions and demarcating transactions effectively will not only improve your application performance, it is part of the functionality of your application.
I would deeply recommend you to read Chapter 2 and Chapter 13 of the Hibernate Core Reference Manual to better understand the roles that SessionFactory, Session and Transaction plays within the framework. It will also teach will about Units of work as well as popular session patterns and anti-patterns.

Spring,Hibernate - Batch processing of large amounts of data with good performance

Imagine you have large amount of data in database approx. ~100Mb. We need to process all data somehow (update or export to somewhere else). How to implement this task with good performance ? How to setup transaction propagation ?
Example 1# (with bad performance) :
#Singleton
public ServiceBean {
procesAllData(){
List<Entity> entityList = dao.findAll();
for(...){
process(entity);
}
}
private void process(Entity ent){
//data processing
//saves data back (UPDATE operation) or exports to somewhere else (just READs from DB)
}
}
What could be improved here ?
In my opinion :
I would set hibernate batch size (see hibernate documentation for batch processing).
I would separated ServiceBean into two Spring beans with different transactions settings. Method processAllData() should run out of transaction, because it operates with large amounts of data and potentional rollback wouldnt be 'quick' (i guess). Method process(Entity entity) would run in transaction - no big thing to make rollback in the case of one data entity.
Do you agree ? Any tips ?
Here are 2 basic strategies:
JDBC batching: set the JDBC batch size, usually somewhere between 20 and 50 (hibernate.jdbc.batch_size). If you are mixing and matching object C/U/D operations, make sure you have Hibernate configured to order inserts and updates, otherwise it won't batch (hibernate.order_inserts and hibernate.order_updates). And when doing batching, it is imperative to make sure you clear() your Session so that you don't run into memory issues during a large transaction.
Concatenated SQL statements: implement the Hibernate Work interface and use your implementation class (or anonymous inner class) to run native SQL against the JDBC connection. Concatenate hand-coded SQL via semicolons (works in most DBs) and then process that SQL via doWork. This strategy allows you to use the Hibernate transaction coordinator while being able to harness the full power of native SQL.
You will generally find that no matter how fast you can get your OO code, using DB tricks like concatenating SQL statements will be faster.
There are a few things to keep in mind here:
Loading all entites into memory with a findAll method can lead to OOM exceptions.
You need to avoid attaching all of the entities to a session - since everytime hibernate executes a flush it will need to dirty check every attached entity. This will quickly grind your processing to a halt.
Hibernate provides a stateless session which you can use with a scrollable results set to scroll through entities one by one - docs here. You can then use this session to update the entity without ever attaching it to a session.
The other alternative is to use a stateful session but clear the session at regular intervals as shown here.
I hope this is useful advice.

Resources