skip to content

What is a JMS MessageConverter in Spring, and what does the default SimpleMessageConverter do?

level: juniorimportance: must knowfreq 55%

answer

  1. toMessage / fromMessage — two methods
  2. Default = SimpleMessageConverter
  3. String→Text, byte[]→Bytes, Map→Map, Serializable→Object
  4. convertAndSend / receiveAndConvert
  5. Boot auto-wires a single MessageConverter bean

basics

~10 s

A MessageConverter turns your Java objects into a jakarta.jms.Message (and back), so you send objects instead of raw messages. The default, SimpleMessageConverter, maps String, byte[], Map, and Serializable to matching message types automatically.

solid answer

~40 s

Spring's org.springframework.jms.support.converter.MessageConverter is a two-method strategy: toMessage(Object, Session) builds a jakarta.jms.Message when you send, and fromMessage(Message) rebuilds the object when you receive. JmsTemplate.convertAndSend and @JmsListener use it so your code deals in domain objects, not TextMessage/BytesMessage plumbing. The out-of-the-box implementation is SimpleMessageConverter: a String becomes a TextMessage, a byte[] becomes a BytesMessage, a Map<String,?> becomes a MapMessage, and any other java.io.Serializable becomes an ObjectMessage (Java serialization). Anything not matching those categories throws MessageConversionException. It's zero-config and fine for simple/homogeneous JVM-to-JVM cases, but ObjectMessage ties both ends to identical classes and carries Java-serialization risk, so JSON converters are usually preferred for real payloads.

code

java · 21 lines
java
// Send a domain object without touching JMS Message types
@Service
class OrderPublisher {
    private final JmsTemplate jmsTemplate;
    OrderPublisher(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; }

    void publish(OrderCreated event) {
        // The configured MessageConverter turns 'event' into a jakarta.jms.Message.
        // With the default SimpleMessageConverter and a Serializable event,
        // this produces an ObjectMessage.
        jmsTemplate.convertAndSend("orders", event);
    }
}

@Component
class OrderListener {
    @JmsListener(destination = "orders")
    void onOrder(OrderCreated event) { // fromMessage produced this argument
        // handle event
    }
}

go deeper

for a junior

Know the two methods and that a converter maps objects to/from JMS messages; name SimpleMessageConverter as the default.

for a middle

Recite the four SimpleMessageConverter mappings and where the converter is wired (JmsTemplate, listener factory).

for a senior

Explain ObjectMessage coupling and security downsides and why JSON is usually preferred.

for a principal

Frame converter choice as a contract/interop/security decision across services and languages.

## The problem it solves The JMS API speaks in terms of `jakarta.jms.Message` subtypes: `TextMessage` (a String body), `BytesMessage` (raw bytes), `MapMessage` (name/value pairs), `ObjectMessage` (a serialized Java object), and `StreamMessage`. Writing producer/consumer code directly against these is verbose. Spring introduces the **`MessageConverter`** abstraction so you can send and receive *domain objects*. ## The interface `org.springframework.jms.support.converter.MessageConverter` has exactly two methods: - `Message toMessage(Object object, Session session)` — called on the **send** side to serialize your object into a JMS `Message`. - `Object fromMessage(Message message)` — called on the **receive** side to deserialize the JMS `Message` back into an object. Both may throw `MessageConversionException` (and `JMSException`). ## Where it plugs in - **`JmsTemplate`** holds a converter; `convertAndSend(destination, object)` and `receiveAndConvert(destination)` use it. Set it via `JmsTemplate.setMessageConverter(...)`. - **Listeners**: `@JmsListener` methods are backed by a `DefaultJmsListenerContainerFactory`, which also has `setMessageConverter(...)`. The converter turns the incoming `Message` into the listener method's argument. - **Spring Boot**: if you declare a single `@Bean` of type `MessageConverter`, Boot auto-injects it into both the auto-configured `JmsTemplate` and the default listener container factory. ## SimpleMessageConverter (the default) If you configure nothing, Spring uses `SimpleMessageConverter`. Its mapping rules are fixed: | Java type (send) | JMS Message produced | |---|---| | `String` | `TextMessage` | | `byte[]` | `BytesMessage` | | `Map<String,?>` | `MapMessage` | | any other `java.io.Serializable` | `ObjectMessage` | On receive it reverses these: `TextMessage`→`String`, `BytesMessage`→`byte[]`, `MapMessage`→`Map`, `ObjectMessage`→the deserialized object. A payload that fits none of these categories (e.g. a non-serializable object) causes `MessageConversionException`. ## Gotchas - **`ObjectMessage` uses Java serialization.** Both the producer and consumer must have the *same class* (and compatible `serialVersionUID`) on their classpath. This couples deployments tightly and makes cross-language messaging impossible. - **Security.** Deserializing untrusted `ObjectMessage` payloads is a classic remote-code-execution vector. For anything crossing a trust boundary, prefer JSON (`MappingJackson2MessageConverter`). - **It is not JSON.** SimpleMessageConverter does *not* produce JSON; a plain POJO becomes a binary `ObjectMessage`, not text. ## When to use what - SimpleMessageConverter: quick internal prototypes, or when you genuinely send String/byte[]/Map. - `MappingJackson2MessageConverter`: real domain objects, versioned schemas, or cross-service/cross-language messaging.

  • Why is ObjectMessage (via SimpleMessageConverter) often discouraged in production?
    It relies on Java serialization: both ends need identical classes/serialVersionUID, it blocks non-JVM consumers, and deserializing untrusted payloads is a well-known RCE risk. JSON with MappingJackson2MessageConverter avoids all three.
  • How do you replace the default converter application-wide in Spring Boot?
    Declare a single @Bean of type MessageConverter (e.g. a configured MappingJackson2MessageConverter). Boot's auto-configuration injects it into the JmsTemplate and the default JmsListenerContainerFactory automatically.

saying these in an interview costs you the question

  • Thinking SimpleMessageConverter serializes POJOs to JSON (it produces a binary ObjectMessage)
  • Believing a converter is optional/absent — there's always one; the default is SimpleMessageConverter
  • Not realizing ObjectMessage requires identical classes on both sides

context