Reputation: 480
Following scenario: I have a @RabbitListener
picking up messages from RabbitMQ. Sometimes the message runs into an error because I can not find the related business object. In this case I have no possibility to reply to the sender so I just want to ignore this message after certain amount of retry.
My solution: In my @RabbitListener
whenever it is not possible to find the business object I throw a custom runtime exception. In my configuration I have a RetryOperationsInterceptor
with max attempts and a custom recoverer.
What is the best practice for handling such cases? Can I configure diffrent recoverer class when having more than one @RabbitListener
?
See my configuraion:
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setMessageConverter(new CustomMessageConverter());
factory.setConnectionFactory(connectionFactory());
factory.setAcknowledgeMode(AcknowledgeMode.AUTO);
factory.setConcurrentConsumers(1);
factory.setMaxConcurrentConsumers(20);
Advice[] adviceChain = new Advice[] { interceptor() };
factory.setAdviceChain(adviceChain);
return factory;
}
@Bean
RetryOperationsInterceptor interceptor() {
return RetryInterceptorBuilder.stateless()
.maxAttempts(5)
.recoverer(new CustomRejectAndRecoverer())
.build();
}
And this is my CustomRejectAndRecoverer
:
public class CustomRejectAndRecoverer implements MessageRecoverer {
@Override
public void recover(Message message, Throwable cause) {
if (ExceptionUtils.getRootCause(cause) instanceof BusinessObjectNotFoundRuntimeException) {
throw new ListenerExecutionFailedException("Retry Policy Exhausted",
new AmqpRejectAndDontRequeueException(cause), message);
}
}
}
Upvotes: 1
Views: 3333
Reputation: 174769
You currently need a different container factory for each different retry configuration.
In 2.0, we have added a new errorHandler
attribute to the annotation so each listener can have a customized error handler, regardless of the container factory it was created by.
This was in the first milestone release; the current milestone is M2 and M3 will be out shortly. The GA release is expected in June.
Upvotes: 3
Reputation: 121550
If common logic from the shared SimpleRabbitListenerContainerFactory
doesn't fit your requirements for particular @RabbitListener
, you have to declare a new one, with those custom options, e.g. a new MessageRecoverer
on the matter.
For that purpose the @RabbitListener
has attribute:
/**
* The bean name of the {@link org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory}
* to use to create the message listener container responsible to serve this endpoint.
* <p>If not specified, the default container factory is used, if any.
* @return the {@link org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory}
* bean name.
*/
String containerFactory() default "";
Upvotes: 0