Here is my problem :
I'm running a batch on a Java EE/Spring/Hibernate application. This batch calls a method1. This method calls a method2 which can throw UserException (a class extending RuntimeException). Here is how it looks like : 
@Transactional
public class BatchService implements IBatchService {
 @Transactional(propagation=Propagation.REQUIRES_NEW)
 public User method2(User user) {
   // Processing, which can throw a RuntimeException
 }
 public void method1() {
   // ...
   try {
     this.method2(user);
   } catch (UserException e) {
     // ...
   }
   // ...
 }
}
The exception is catched as the execution continues, but at the end of method1 when the transaction is closed a RollbackException is thrown.
Here is the stack trace :
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:476)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy128.method1(Unknown Source)
at batch.BatchController.method1(BatchController.java:202)
When method2 is not throwing this exception, it works well.
What I have tried:
- Setting @Transactional(noRollbackFor={UserException.class}))onmethod1
- Try and catch in method2
But it didn't change anything.
As the exception is thrown in a different transaction where a rollback happened I don't understand why it doesn't work. I had a look at this : Jpa transaction javax.persistence.RollbackException: Transaction marked as rollbackOnly but it didn't really help me.
I will be very greatful if someone could give me a clue.
Update
I've made it work by setting propagation=Propagation.REQUIRES_NEW on the method called by method2 (which is actually the one which is sending the exception). This method is defined in a class very similar to my BatchService. So I don't see why it works on this level and not on method2.
- I've set method2as public as the annotation@Transactionalis not taken into account if the method is private as said in the documentation :
The @Transactional annotation may be placed before an interface definition, a method on an interface, a class definition, or a public method on a class.
- I also tried to use Exceptioninstead ofRuntimeException(as it is more appropriate) but it also didn't change anything.
Even if it is working the question remains open as it has a strange behaviour and I would like to understand why it's not acting like it should be.
 
     
    