Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Integration and AMQP: How to gracefully handle deserialization exceptions?

I use RabbitMQ and Spring Integration to handle incoming JSON messages.

The relevant part of the configuration looks something like this:

<amqp:inbound-channel-adapter channel="incomingChannel" queue-names="..."
      message-converter="jsonConverter" error-handler="errorHandler"
      error-channel="errorChannel" />

I'm using Jackson Databind as the JSON converter.

Sometimes the incoming JSON messages have an incorrect syntax. This results in the following (correct) exception:

org.springframework.amqp.rabbit.listener.ListenerExecutionFailedException: Listener threw exception
Caused by: org.springframework.amqp.support.converter.MessageConversionException: Failed to convert Message content
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token...

The exception is then handled by the errorHandler which simply is a MessagePublishingErrorHandler to errorChannel.

So far so good. The problem is, that the message is still being rejected by the AMQP client, although I am handling it with an error handler. RabbitMQ then redelivers the message over and over. Even configuring a dead letter queue did not help. Any ideas how to handle this scenario correctly?

Exceptions further down the processing (after successful deserialization) are handled just fine: AMQP message acknowledged and error message sent to errorChannel.

Any ideas?

Library versions:

  • Spring Integration: 3.0.1
  • Spring Framework: 4.0.2
  • Jackson Databind: 2.3.1
like image 746
Philipp Jardas Avatar asked Feb 26 '14 14:02

Philipp Jardas


1 Answers

You can set defaultRequeueRejected=false on the listener container.

The attribute is not currently exposed on the channel adapter, but you can define the container as a <bean... class="...SimpleMessageListenerContainer"/> and inject it into adapter using the listener-container attribute.

Or, use a custom ErrorHandler that throws an AmqpRejectAndDontRequeueException.

like image 142
Gary Russell Avatar answered Nov 15 '22 00:11

Gary Russell