Yanick Salzmann
Yanick Salzmann

Reputation: 1498

Spring transaction handling JMSTemplate inside @Transactional method

In our spring boot application we have a paging loop over the database which will send a JMS message for every page using a JMSTemplate. The method containing the loop is @Transactional. The JMSTemplate is created with the transacted flag set to true.

I have been browsing through the source code of JMSTemplate and as far as I can see it will not commit a transacted session if there is already a outer transaction going on but will put it into that transaction.

Let's now 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());
}

The createTemplate creates a DynamicJmsTemplate using a CachingConnectionFactory and setSessionTransacted to true

I am now not entirely sure how this translates to the transactions. My understanding is that all N page messages are sent in the transaction created from the loopThroughPages and once the loopThroughPages method finishes it will commit all N messages and not after each message has been sent. That also implies that the transaction on MQ side will stay open until the last page has been processed. Is this understanding correct?

Upvotes: 3

Views: 5838

Answers (1)

Valerio Vaudi
Valerio Vaudi

Reputation: 4532

The key point here is the Transastion managment.

If you use a XA datasource and configure it on your spring boot app you will have a distributed transaction and the commit/rollback for your transaction will be managed by spring since that you have a method annotated with @Transactional otherwise you will have a local transaction managment and the transaction of your database and messaging system will be not syncronized.

For sending message you can by properties configure if the message are persisted or not that it means if your messages will be persisted by your messaging system, while for listener perspective you can configure the acknowledged mode. By the way the my advice is let to spring managed the transaction and all will be fine but the real point of attention is if you want a distributed transaction between database and jms system you have only configure it atomikos can be an available option, otherwise it is sufficient do not manage the transaction by hand and let to Spring manage it for you.

I hope that it can help you

Upvotes: 3

Related Questions