Comportamento estranho com @Transactional (propagation = Propagation.REQUIRES_NEW)

Aqui está o meu problema:

Estou executando um lote em um aplicativo Java EE / Spring / Hibernate. Este lote chama ummethod1. Este método chama ummethod2 que pode jogarUserException (uma classe que se estendeRuntimeException). Aqui está como parece:

@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) {
     // ...
   }
   // ...
 }
}

A exceção é capturada à medida que a execução continua, mas no finalmethod1 quando a transação é fechada, uma RollbackException é lançada.

Aqui está o rastreamento de pilha:

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)

Quandomethod2 não está jogando essa exceção, funciona bem.

O que eu tentei:

Configuração@Transactional(noRollbackFor={UserException.class})) emmethod1Tente e peguemethod2

Mas isso não mudou nada.

Como a exceção é lançada em uma transação diferente em que ocorreu uma reversão, não entendo por que ela não funciona. Eu dei uma olhada nisso:Transação Jpa javax.persistence.RollbackException: Transação marcada como rollbackOnly mas isso realmente não me ajudou.

Eu ficarei muito grato se alguém puder me dar uma pista.

Atualizar

Eu fiz isso funcionar definindopropagation=Propagation.REQUIRES_NEW no método chamado pormethod2 (que é realmente aquele que está enviando a exceção). Este método é definido em uma classe muito semelhante à minhaBatchService. Então eu não vejo porque funciona nesse nível e não emmethod2.

Eu coloqueimethod2 tão público quanto a anotação@Transactional não é levado em conta se o método é privado como dito na documentação:

A anotação @Transactional pode ser colocada antes de uma definição de interface, um método em uma interface, uma definição de classe ou um método público em uma classe.

Eu também tentei usarException ao invés deRuntimeException (como é mais apropriado), mas também não mudou nada.

Mesmo que esteja funcionando, a questão permanece em aberto, pois tem um comportamento estranho e eu gostaria de entender por que ela não está agindo como deveria.

questionAnswers(1)

yourAnswerToTheQuestion