Search code examples
javaspringrabbitmqamqpspring-amqp

Getting message object using message listener adapter in spring AMQP


I have created a message listener using spring AMQP which I am using to receive an Order POJO. The message type is application/json and so I have set up a jackson message convertor. Till now things are working fine and I am able to get the order POJO object recreated automatically in my listener. However I want to extend this example and want to check some message property in my listener. Thus instead of using my Order POJO in my handleMessage() I want to use "org.springframework.amqp.core.Message" as the parameter. I can then later convert the body, but in this way I will have all the message related properties in my listener which I can use in my application.

I tried using the handleMessage() with Message parameter but it seems that it tries to convert the message body as well using jackson convertors. I am not sure where to pass the Order POJO class jackson can use to convert my message body but should still be able to convert the Message correctly.

Please find below the important snippets from my code. Please help me as I think I have hit a roadblock on this.

POJO

public class Order {

private int orderid;
private String itemDescription;

TEMPLATE AND CONVERTER SETTINGS

@Bean
public RabbitTemplate rubeExchangeTemplate() {
    logger.info("Lets test autowiring " + rabbitConnectionFactory.getHost());
    RabbitTemplate r = new RabbitTemplate(this.rabbitConnectionFactory);
    r.setExchange("rmq-exchange");
    r.setMessageConverter(jsonMessageConverter());
    return r;
}

@Bean
public MessageConverter jsonMessageConverter()
{
    final Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
    converter.setClassMapper(classMapper());
    return converter;
}

@Bean
public DefaultClassMapper classMapper()
{
    DefaultClassMapper typeMapper = new DefaultClassMapper();
    typeMapper.setDefaultType(Order.class);
    return typeMapper;
}

MESSAGE WHICH I AM SENDING(messageText contains the JSON compliant with the Order POJO)

        Message message = MessageBuilder.withBody(messageText.getBytes())
            .setMessageId("123")
            .setContentType("application/json")
            .setHeader("bar", "baz")
            .build();

LISTENER

@Bean(value = "rube")
public SimpleMessageListenerContainer listenerContainer() {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(cf);
    container.setQueueNames("rmq-rube-queue");
    container.setMessageListener(messageListenerAdapter());
    return container;
}

@Bean
public MessageListenerAdapter messageListenerAdapter() {
    MessageListenerAdapter listener =  new MessageListenerAdapter(pm, converter);
    return listener;
}

Solution

  • Don't use a MessageListenerAdapter in that case, simply implement MessageListener to get the raw message.

    Alternatively, consider using the newer, annotation-based, POJO listener, where you can get access to headers as well as the converted payload...

    @RabbitListener(queues = "foo")
    public void listen(MyPojo pojo, @Header("foo") String fooHeader) { ... }