0

I have an application which uses spring AMQP for consuming and producing messages to other application. I have a scenario where some of the exception occurred i need to re-queue back to RabbitMQ. For some exceptions i need to ignore (Basically i need to ignore the message no need to requeue)

Currently in below code, i have set the configuration as

factory.setDefaultRequeueRejected(false);

But my requirement is to dynamically reject for some messages and re-queue back to RabbitMQ for some messages.

Please suggest

@Bean(name="rabbitListenerContainerFactory")
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        Jackson2JsonMessageConverter messageConverter = new Jackson2JsonMessageConverter();
        DefaultClassMapper classMapper = new DefaultClassMapper();
        Map<String, Class<?>> idClassMapping = new HashMap<String, Class<?>>();
        idClassMapping.put(Constants.JOB_TYPE_ID_, JobListenerDTO.class);
        classMapper.setIdClassMapping(idClassMapping);
        messageConverter.setClassMapper(classMapper);
        factory.setMessageConverter(messageConverter);
        factory.setDefaultRequeueRejected(false);
        factory.setReceiveTimeout(10L);
        return factory;
    }
BIndu_Madhav
  • 577
  • 1
  • 8
  • 21

1 Answers1

5

You can't do it that way around (default false).

To do it selectively you have to set defaultRequeueRejected to true and throw AmqpRejectAndDontRequeueRejected for any you want discarded.

You can encapsulate your desired logic in an ErrorHandler.

The default error handler does exactly that for a certain list of exceptions, as documented here - you can inject a custom FatalExceptionStrategy.

But for conditional rejection, the defaultRequeueRejected must be true.

EDIT

factory.setErrorHandler(new ConditionalRejectingErrorHandler(t -> {
        Throwable cause = t.getCause();
        return cause instanceof MessageConversionException
                || cause instanceof org.springframework.messaging.converter.MessageConversionException
                || cause instanceof MethodArgumentNotValidException
                || cause instanceof MethodArgumentTypeMismatchException
                || cause instanceof NoSuchMethodException
                || cause instanceof ClassCastException
                || cause instanceof MyBadXMLException;
    }));

This adds MyBadXMLException to the standard list.

If you are not using Java 8, use new FatalExceptionStrategy() {...}.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Thanks for reply. Could you please provide me example which show case the use of ErrorHandler? – BIndu_Madhav Sep 15 '16 at 14:51
  • One more query, i have getting input as an xml from the producer. If the xml data is wrong, i am getting XML Exception. Only this exception i don't need to re-queue(How to do this ?). Rest all exceptions i need requeue. For that as you mention, i will set `defaultRequeueRejected ` to `true` – BIndu_Madhav Sep 15 '16 at 14:55
  • I read from rabbitmq link, `The AMQP specification defines the basic.reject method that allows clients to reject individual, delivered messages, instructing the broker to either discard them or requeue them.` Is it not supported in Spring AMQP ? – BIndu_Madhav Sep 16 '16 at 06:10
  • 1
    The container does that for you. Spring AMQP is an abstraction over ampq. If the listener exits normally, the container sends `basicAck`. If the listener throws an exception, it sends `basicReject`. Requeue or not depends on `defaultRequeueRejected` but that can be overridden (when true) by throwing an `AmqpRejectAndDontRequeueException`. – Gary Russell Sep 16 '16 at 12:47
  • If you really want to take responsibility for acks in your listener, set the acknowledge mode to `MANUAL` and see [this answer](http://stackoverflow.com/questions/38728668/spring-rabbitmq-using-manual-channel-acknowledgement-on-a-service-with-rabbit/38730821#38730821) for how to do it. But most people let the container do it. – Gary Russell Sep 16 '16 at 12:47