This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

I have implemented a scenario using Spring Integration 2.0.1 that utilizes a queue channel backed by a persistent message store, using the Spring provided JdbcMessageStore implementation with an Oracle database.

Below is an overview of my implementation:
1) JMS event driven adapter consuming from a WebLogic JMS queue, delivering the message onto a direct channel.
2) Content based router (xpath router) that will route to one of two possible direct channels (A or B).
3) Xpath splitter consuming from channel A, splits the single message into multiple and sends each message onto the database persisted queue channel.
For the purpose of describing the problem, the alternate path on the B channel is not relevant.
4) Consumer will read messages from the queue channel and perform necessary action.

During performance testing where a single message is broken down into over 2000 individual messages that will be persisted on the queue channel, I have noticed a gradual increase in time taken to perform the database insert. After digging into the code through the debugger, I extracted the following call stack:

Code:

org.springframework.jms.listener.DefaultMessageListenerContainer#0-1@9, prio=5, in group 'Pooled Threads', status: 'RUNNING'
at org.springframework.integration.jdbc.JdbcMessageStore. (JdbcMessageStore.java:295)
at org.springframework.integration.store.MessageGroupQueue.offer(MessageGroupQueue.java:86)
at org.springframework.integration.store.MessageGroupQueue.put(MessageGroupQueue.java:176)
at org.springframework.integration.store.MessageGroupQueue.put(MessageGroupQueue.java:37)
at org.springframework.integration.channel.QueueChannel.doSend(QueueChannel.java:79)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
...
at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288)
at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendMessage(AbstractReplyProducingMessageHandler.java:176)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendReplyMessage(AbstractReplyProducingMessageHandler.java:160)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.produceReply(AbstractReplyProducingMessageHandler.java:125)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleResult(AbstractReplyProducingMessageHandler.java:115)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:101)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.monitor.SimpleMessageHandlerMetrics.handleMessage(SimpleMessageHandlerMetrics.java:108)
...
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:947)
at java.lang.Thread.run(Thread.java:662)

Stepping through the call stack I was able to identify that the increasing lag was in the addMessageToGroup call in the JdbcMessageStore.

The reason for the lag as highlighted above is that after every insert, the full set of persisted messages is fetched and returned. As over 2000 inserts are performed in sequence, the amount of data coming back and being processed increases each iteration, thus causing the whole process to gradually slow down. On average, it resulted in individual inserts being processed at around 345 milliseconds per request. Reviewing the usages of the addMessageToGroup method, I am guessing this was done for use by correlating handlers, however in other cases like the MessageGroupQueue handler it is an unnecessary step that affects performance.

I've also noticed that the same approach is taken with the removeMessageFromGroup method.

Can someone please elaborate on the reasoning for this design decision and whether it would be better to perform the fetch only when required?

Can you please upgrade to 2.2.M2. I understand that you may not officially rely on the milestone build but there were some significant improvements doen to the JdbcMessageStore to address the exact issue you are describing. And another user has already validated it so it would be nice to get another validation from you.
Please let us know.
Thanks