Spring Boot
RabbitMQ
MappingJackson2MessageConverter
Custom Object Conversion
Message Queuing

spring boot rabbitmq MappingJackson2MessageConverter custom object conversion

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When Spring Boot talks to RabbitMQ with custom Java objects, the real problem is not RabbitMQ itself. It is message conversion: the sender must turn the object into JSON, and the receiver must turn the JSON back into the expected Java type in a way both sides agree on.

Use The JSON Converter On Both Sides

For RabbitMQ in Spring AMQP, the practical converter is usually Jackson2JsonMessageConverter. That is the component most people mean when they refer to Jackson-based object conversion in RabbitMQ messaging.

Configure it once and apply it to the RabbitTemplate:

java
1import org.springframework.amqp.rabbit.connection.ConnectionFactory;
2import org.springframework.amqp.rabbit.core.RabbitTemplate;
3import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
4import org.springframework.context.annotation.Bean;
5import org.springframework.context.annotation.Configuration;
6
7@Configuration
8public class RabbitConfig {
9
10    @Bean
11    public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
12        return new Jackson2JsonMessageConverter();
13    }
14
15    @Bean
16    public RabbitTemplate rabbitTemplate(
17            ConnectionFactory connectionFactory,
18            Jackson2JsonMessageConverter converter) {
19        RabbitTemplate template = new RabbitTemplate(connectionFactory);
20        template.setMessageConverter(converter);
21        return template;
22    }
23}

Without this, Spring often falls back to a simpler converter that is not what you want for JSON custom objects.

Send And Receive A Custom Object

Suppose the message payload is an OrderCreatedEvent:

java
1import java.math.BigDecimal;
2
3public class OrderCreatedEvent {
4    private String orderId;
5    private BigDecimal total;
6
7    public OrderCreatedEvent() {
8    }
9
10    public OrderCreatedEvent(String orderId, BigDecimal total) {
11        this.orderId = orderId;
12        this.total = total;
13    }
14
15    public String getOrderId() {
16        return orderId;
17    }
18
19    public void setOrderId(String orderId) {
20        this.orderId = orderId;
21    }
22
23    public BigDecimal getTotal() {
24        return total;
25    }
26
27    public void setTotal(BigDecimal total) {
28        this.total = total;
29    }
30}

Publishing is then straightforward:

java
1import java.math.BigDecimal;
2import org.springframework.amqp.rabbit.core.RabbitTemplate;
3import org.springframework.stereotype.Service;
4
5@Service
6public class OrderPublisher {
7    private final RabbitTemplate rabbitTemplate;
8
9    public OrderPublisher(RabbitTemplate rabbitTemplate) {
10        this.rabbitTemplate = rabbitTemplate;
11    }
12
13    public void publish() {
14        OrderCreatedEvent event = new OrderCreatedEvent("A-100", new BigDecimal("19.99"));
15        rabbitTemplate.convertAndSend("orders.exchange", "orders.created", event);
16    }
17}

On the receiving side, the listener can accept the Java type directly if the converter is configured consistently:

java
1import org.springframework.amqp.rabbit.annotation.RabbitListener;
2import org.springframework.stereotype.Component;
3
4@Component
5public class OrderListener {
6
7    @RabbitListener(queues = "orders.queue")
8    public void handle(OrderCreatedEvent event) {
9        System.out.println("Received order " + event.getOrderId());
10    }
11}

This is the main payoff: no manual JSON parsing in the business logic.

Customize The ObjectMapper When The Payload Needs It

If your object contains Java time types, naming conventions, or other custom serialization rules, inject a customized ObjectMapper into the converter.

java
1import com.fasterxml.jackson.databind.ObjectMapper;
2import com.fasterxml.jackson.databind.SerializationFeature;
3import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
4import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
5import org.springframework.context.annotation.Bean;
6
7@Bean
8public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
9    ObjectMapper mapper = new ObjectMapper();
10    mapper.registerModule(new JavaTimeModule());
11    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
12    return new Jackson2JsonMessageConverter(mapper);
13}

This is usually a better fix than forcing the application layer to serialize special fields by hand.

Why Conversion Sometimes Fails

The most common failure mode is that one side sends JSON, but the other side is not actually using the same converter or the same type expectations. Another common problem is missing getters, setters, or a no-argument constructor on the payload type.

If the listener expects a custom object and receives a raw byte[] or String, that usually means the converter configuration never got applied where you thought it did.

Common Pitfalls

  • Configuring the JSON converter for the sender but not the listener side.
  • Expecting custom object conversion while Spring is still using SimpleMessageConverter.
  • Forgetting a no-argument constructor or normal bean accessors on the payload type.
  • Ignoring ObjectMapper customization when the payload includes dates or other special fields.
  • Assuming any Jackson-based class name works interchangeably across Spring Messaging and Spring AMQP without checking the actual RabbitMQ configuration point.

Summary

  • For Spring Boot and RabbitMQ, use the Jackson JSON message converter consistently on both send and receive paths.
  • 'RabbitTemplate.convertAndSend(...) can publish a normal Java object once the converter is configured.'
  • '@RabbitListener can receive the custom object directly when the conversion metadata lines up.'
  • If conversion fails, inspect the converter wiring before changing the business logic.

Course illustration
Course illustration

All Rights Reserved.