🔴 The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
org.springframework.messaging.converter.MessageConversionException: failed to convert serialized payload [B@1234 to type: com.devinhyderabad.dto.User
at org.springframework.messaging.converter.MessageConverter.fromMessage(MessageConverter.java:89)
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.unwrapPayload(MessagingMessageListenerAdapter.java:283)⚡ Quick Fix Works 80% of the time
Register a MappingJackson2MessageConverter bean and set the __TypeId__ header on the message.
@Bean
public MappingJackson2MessageConverter jacksonConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetTypeName(User.class.getName());
return converter;
}🧠 Why this Happens
Tap to expand the deep technical explanation
Spring's `MessageConverter` tried to turn the incoming message bytes into the Java object expected by the listener method. By default, Spring uses simple String/byte conversion. If you are expecting a custom POJO (like `User`), it fails because it doesn't know how to map the JSON fields to the Java class without a dedicated converter.
The HITEC City Parking Spot Analogy:
An interpreter who only speaks English and Spanish is handed a document in French. They throw their hands up and refuse to translate because they don't have the French dictionary.
🔁 How to Reproduce Confirm this is your error
Send a JSON string to a JMS queue using `JmsTemplate`. Have a `@JmsListener` that expects a `User` object. Do not configure a `MessageConverter`.
🛠️ Solutions (5 Ways to Fix)
Register a MappingJackson2MessageConverter bean
👉 Use this when working with JMS and JSON payloads.
This converter uses Jackson to map JSON strings to Java objects. You must set the target type name so it knows what class to instantiate.
@Bean
public MappingJackson2MessageConverter jacksonConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetTypeName(User.class.getName());
return converter;
}Set the __TypeId__ header on the sender
👉 Use this if you are using the default Spring message converter.
Spring's default converter looks for a `__TypeId__` header in the message properties to know which Java class to instantiate. Set it to the fully qualified class name on the producer side.
Message<String> msg = MessageBuilder.withPayload(jsonString)
.setHeader("__TypeId__", "com.devinhyderabad.dto.User")
.build();
jmsTemplate.send("queue", msg);Change listener to accept String
👉 Use this to debug raw payloads.
Accept the raw string and use ObjectMapper manually to parse it inside your listener.
@JmsListener(destination = "queue")
public void listen(String rawJson) {
User user = new ObjectMapper().readValue(rawJson, User.class);
}Ensure payload structure matches the target class
👉 Use this if the converter is configured but mapping fails.
If the JSON has fields that don't exist in your Java class, or is missing required fields, Jackson will fail. Ensure the JSON structure matches your DTO exactly.
// JSON: {"name":"Deva", "email":"a@b.com"}
// DTO: public class User { String name; String email; }Check for content_type mismatches
👉 Use this if the message is sent as `text/plain` but expected as `application/json`.
Some converters are strict about the `content_type` property. Ensure the producer sets it correctly.
// Producer:
MessageProperties props = MessagePropertiesBuilder.newInstance().setContentType("application/json").build();📋 Version Notes
Standard JMS message conversion.
Stricter type resolution, requires explicit target type names.
🛡️ How to Prevent This Next Time
Always explicitly define your `MessageConverter` beans in both producer and consumer applications to avoid relying on Spring's defaults.