I have a IbmMqEndpoint that receives messages. What I want is to put the message back in the original queue if an error occurs during message processing. The follwoing implementation works flawlessly processes error-free messages.
@Bean(name = "ibmMqListenerContainerFactory")
public DefaultJmsListenerContainerFactory ibmMqListenerContainerFactory(
@Qualifier("ibmMqConnectionFactory") ConnectionFactory connectionFactory) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setSessionTransacted(true);
factory.setBackOff(new FixedBackOff(5000L, 3));
factory.setErrorHandler(new ErrorHandler() {
@Override
public void handleError(Throwable t) {
logger.warn("spring jms custom error handling example");
logger.error(t.getCause().getMessage());
throw new MessageSendException("Error", new Exception("Test"));
}
});
return factory;
}
The follwing registers the MessageListener:
private SimpleJmsListenerEndpoint getJmsListenerEndpoint(String endpoint) {
SimpleJmsListenerEndpoint jmsListenerEndpoint = new SimpleJmsListenerEndpoint();
jmsListenerEndpoint.setId(endpoint);
jmsListenerEndpoint.setDestination(endpoint);
jmsListenerEndpoint.setMessageListener(m -> {
try {
byte[] body = m.getBody(byte[].class);
MyMessage myMessage = new MyMessage(body);
messageHandler.accept(myMessage);
} catch MessageSendException | JMSException e) {
throw new MessageSendException(e);
}
});
return jmsListenerEndpoint;
}
However, after the messageListener is set and I send an faulty message and this the MessageSentException gets thrown, the underlying DefaultMessageListenerContainer implementation resets the BackOff-variable currentAttempts by calling backOff.start() in the method
private void waitBeforeRecoveryAttempt() {
BackOffExecution execution = DefaultMessageListenerContainer.this.backOff.start();
DefaultMessageListenerContainer.this.applyBackOffTime(execution);
}
What caught my attention is, that the method handleListenerSetupFailure in DefaultMessageListenerContainer is called. But this isn’t a handler setup failure, is it? I thought this is a message-handling failure, as the setup took place on application boot up.
It could be, that I am on the wrong track regarding the message rewrites to the original queue, but it looks like a good approach with the setSessionTransacted. Are here any Spring JMS Experts that can explain to me how I can implement the three backoff attemtps using the spring-boot framework?