Maciej Miklas
Maciej Miklas

Reputation: 3331

Spring - commit JMS Transaction after JPA transaction

I have two transaction managers: JpaTransactionManager (myJpaTm) and JmsTransactionManager (myJmsTm).

Consider following code:

@Named
public class TestA {
   @Inject TestB testB;

   @Transactional(transactionManager="myJpaTm") 
   public void methoda() {
     // store stuff in db
     testB.methodb();
   }
}

@Named
public class TestB {

   @Transactional(transactionManager="myJmsTm")  
   public void methodb() {
     // send few JMS messages
   }
}

We have outer JPA transaction and inner JMS transaction, both are separated because we are not using distributed transactions.

I would like to commit JMS transaction right after committing JPA transaction. In this case current JMS transaction would need to hook up to parent JPA transaction.

I'am not looking for substitution to distributed transactions, I just would like to send JMS messages after committing data to database.

I know that I just could create another class that could call methoda and afterwards methodb, but I would like to solve it by connection both transactions together.

Upvotes: 3

Views: 2307

Answers (2)

Maciej Miklas
Maciej Miklas

Reputation: 3331

I've found also another option - we can use ChainedTransactionManager from spring-data-commons that will chain two transaction managers in proper order.

@Configuration
public class ChainedTransactionConfiguration {
   @Bean
    public ChainedTransactionManager chainedTransactionManager(
        @Named("myJpaTm") JpaTransactionManager myJpaTm,
        @Named("myJmsTm") JmsTransactionManager myJmsTm) {
    return new ChainedTransactionManager(myJmsTm, myJpaTm);
    }
}

now I have to only set new TM:

@Named
public class TestA {
   @Inject TestB testB;

   @Transactional(transactionManager="chainedTransactionManager") 
   public void methoda() {
     // store stuff in db
     testB.methodb();
   }
}

@Named
public class TestB {

   @Transactional(transactionManager="myJmsTm")  
   public void methodb() {
     // send few JMS messages
   }
}

Upvotes: 2

ritesh.garg
ritesh.garg

Reputation: 3943

I have done this in past using TransactionSynchronizationManager and adding the send message block in afterCommit method for the synchronization. Basically you need to place something like this in your implementation:

@Named
public class TestA{

@Inject
TestB testB;

@Transactional(transactionManager="myJpaTm")
public void methoda() {
   // other db stuff
   if(TransactionSynchronizationManager.isActualTransactionActive()){
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){
                 @Override
                 public void afterCommit(){
                     testB.methodb();
                 }
         });
    }
  }
}

Upvotes: 1

Related Questions