Reputation: 1498
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
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