My springboot application is consuming messages from a weblogic jms queue(ReqQueue) and posting the response back to another queue(RespQueue) after processing. I recently upgraded weblogic version from 12.2.1.3 to 12.2.1.4. After that I am facing an issue of receiving duplicate messages in my JmsListener.
Below is my configuration.
@Bean(name = "myFactory")
public JmsListenerContainerFactory<?> myFactory(
@Qualifier("connectionFactory")
ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setErrorHandler(t -> {
logger.error("Error in listener!", t);
});
// factory.setMessageConverter(jacksonJmsMessageConverter());
factory.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
factory.setSessionTransacted(true);
factory.setConcurrency("5-13");
configurer.configure(factory, connectionFactory);
logger.error("**** Message AUTO_ACKNOWLEDGE");
return factory;
}
@Autowired
@Bean(name = "connectionFactory")
public JndiObjectFactoryBean connectionFactory(JndiTemplate provider){
JndiObjectFactoryBean factory = new JndiObjectFactoryBean();
factory.setJndiTemplate(provider);
factory.setJndiName(connectionType);
factory.setProxyInterface(ConnectionFactory.class);
return factory;
}
@JmsListener(destination = "jms/ReqQueue", containerFactory = "myFactory")
public void receive(@Payload Message message,
@Header(JmsHeaders.CORRELATION_ID) String correlationId,
@Header(JmsHeaders.MESSAGE_ID) String messageId,
@Headers Map<String, Object> headers,
MessageHeaders messageHeaders,
JmsMessageHeaderAccessor jmsMessageHeaderAccessor) throws JMSException, JmsHeaderValidationException, JsonParseException, JsonMappingException, IOException, InterruptedException
{
Transaction timeout in connection-factory setting on weblogic is over 5 hours.
I am getting this error in logs:
[WARN] [DefaultMessageListenerContainer-41] [org.springframework.jms.listener.DefaultMessageListenerContainer:895] Setup of JMS message listener invoker failed for destination 'jms/ReqQueue' - trying to recover. Cause: JTA transaction already rolled back (probably due to a timeout)
And I am also seeing duplicate delivery of some messages to the listener until response is successfully posted to the RespQueue. But those messages are being successfully received and executed by the application on the first time.
If I set the message redelivery limit to 0 on weblogic for RespQueue, I can see that few responses are not being posted to the queue.
Could you please help me solve the issue? Thanks.
edit:
In debug logs I found these exceptions.
[DefaultMessageListenerContainer-28] [org.springframework.transaction.jta.WebLogicJtaTransactionManager:743] Initiating transaction commit
[DEBUG] [DefaultMessageListenerContainer-28] [org.springframework.jms.listener.DefaultMessageListenerContainer:884] Setup of JMS message listener invoker failed - already recovered by other invoker
org.springframework.transaction.UnexpectedRollbackException: JTA transaction already rolled back (probably due to a timeout)
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1032)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:251)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1179)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1076)
at java.lang.Thread.run(Thread.java:750)
I Found that JTA transaction timeout value set at domain level was too low. Error is fixed after I set the value for Home>>domain>>configuration>>JTA>>Timeout seconds to a higher value.