Java – Spring transaction JMSTemplate in the @Transactional method

Spring transaction JMSTemplate in the @Transactional method… here is a solution to the problem.

Spring transaction JMSTemplate in the @Transactional method

In our Spring Boot application, we have a paging loop on the database that will send a JMS message for each page using JMSTemplate. The method to include loops is @Transactional. JMSTemplate is created with the transaction flag set to true.

I’ve been going through the source code of JMSTemplate and as far as I know, if there’s already an external transaction in progress, it doesn’t commit the transaction session, but it puts it into that transaction

Now let’s consider the following code:

@Transactional
public void loopThroughPages(String destination, String from, String to) {
    Pageable pageRequest = PageRequest.of(0, maxPageSize);
    Page<Event> eventPage;
    do {
       eventPage = eventRepo.getEventsInTimeRangeForDestination(from, to, destination, pageRequest);
       if(eventPage.hasContent()) {
          Message<String> eventMessage = buildEventMessage(eventPage.getContent());
          JmsTemplate template = queueService.createTemplate(destination);
          template.send(eventMessage);
          pageRequest = eventPage.nextPageable();
       }
    } while(pageRequest != null && eventPage.hasNext());
}

createTemplate uses CachingConnectionFactory and setSessionTransacted to create a DynamicJmsTemplate to true

I’m not entirely sure right now how this translates into trading. My understanding is that all N page messages are sent in a transaction created from loopThroughPages, and once the loopThroughPages method completes, it will commit all N messages, not after each message is sent. This also means that transactions on the MQ side will remain open until the last page is processed. Is this understanding correct?

Solution

The key point here is trade management.

If you use an XA data source and configure it on your spring boot application, you will have a distributed transaction and the commit/rollback of your transaction will be managed by spring because you have a method annotated with @Transactional, otherwise you will have local transaction management and transactions for your database and messaging system will not be synchronized.

For sending messages, you can configure whether the message is

persisted through properties, which means whether your message is persisted by your messaging system, and from the listener’s perspective, you can configure the acknowledgment mode.
By the way, my advice is to let Spring manage the transactions and everything will be fine, but the real caveat is that if you want distributed transactions between the database and the JMS system, you just need to configure it atomikos to be an available option, otherwise it doesn’t have to manage transactions manually, let Spring manage it for you.

Hope that helps

Related Problems and Solutions