skip to content

Message & MessageHeaders

A Message is a payload plus immutable headers, built through MessageBuilder, with standard headers such as id, timestamp and reply channel. Interviewers ask what belongs in headers versus the payload, and correlation data is the usual example.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

5

What is Spring's Message<T> abstraction, and what are its two parts?

level: juniorimportance: must knowfreq 70%

answer

  1. payload + headers
  2. org.springframework.messaging
  3. getPayload / getHeaders
  4. id + timestamp auto
  5. GenericMessage default impl

basics

~10 s

Message<T> is Spring's generic container for something being sent. It has two parts: a payload (the body of type T) and MessageHeaders (a map of metadata like an id and timestamp).

solid answer

~40 s

Message<T> (in org.springframework.messaging) is the core abstraction Spring uses to move data through messaging, integration, and streaming code. It wraps two things: getPayload() returns the body of generic type T (your domain object, a String, bytes, etc.), and getHeaders() returns a MessageHeaders instance — a read-only map of metadata such as the auto-assigned id (a UUID) and timestamp, plus anything you attach (correlation ids, content type, reply channel). The interface deliberately separates 'what you're sending' (payload) from 'information about the send' (headers), so the same envelope works across Spring Messaging, Spring Integration, spring-messaging over WebSocket/STOMP, and Spring Cloud Stream. The most common concrete implementation is GenericMessage<T>.

code

java · 8 lines
java
import org.springframework.messaging.Message;
import org.springframework.messaging.support.GenericMessage;

Message<String> msg = new GenericMessage<>("order-123");

String body = msg.getPayload();        // "order-123"
Object id = msg.getHeaders().getId(); // auto-assigned UUID
Object ts = msg.getHeaders().getTimestamp(); // epoch millis Long

go deeper

for a junior

Know it is payload + headers and where the package lives.

for a middle

Know GenericMessage and the auto-assigned id/timestamp headers.

for a senior

Explain the transport-agnostic role across Integration/Stream/STOMP and header-based routing.

for a principal

Frame it as the EIP Message pattern enabling infrastructure to act without touching the payload.

## The abstraction `org.springframework.messaging.Message<T>` is the foundational envelope in Spring's messaging stack. It models the classic Enterprise Integration Pattern of a **Message = payload + headers**. The interface is tiny: ```java public interface Message<T> { T getPayload(); MessageHeaders getHeaders(); } ``` - **Payload** — the actual content you care about, typed by the generic parameter `T`. It can be a domain object, a `String`, a `byte[]`, a JSON node, anything. - **Headers** — a `MessageHeaders` object, which is an **immutable `Map<String, Object>`** of metadata *about* the message (not part of the business body). ## Why separate them? Separating body from metadata lets infrastructure (routers, filters, transformers, channel adapters) inspect and act on a message **without parsing the payload**. Routing on a `type` header, correlating request/reply via a `reply-channel` header, or tracing via a `correlationId` all happen at the header level. ## Where it shows up The same `Message<T>` type flows through **Spring Messaging** (the `spring-messaging` module), **Spring Integration**, **Spring Cloud Stream**, STOMP/WebSocket messaging, and `@KafkaListener`/`@RabbitListener` when you accept a `Message<?>` parameter. Learning it once pays off across all of them. ## Standard headers Every `MessageHeaders` automatically carries: - `id` (`MessageHeaders.ID`) — a unique `java.util.UUID` generated per message. - `timestamp` (`MessageHeaders.TIMESTAMP`) — a `Long` epoch-millis creation time. Optional well-known headers include `MessageHeaders.REPLY_CHANNEL`, `MessageHeaders.ERROR_CHANNEL`, and `MessageHeaders.CONTENT_TYPE`. ## Common implementation `GenericMessage<T>` is the default concrete class. You rarely construct `Message` by hand for anything non-trivial — you use `MessageBuilder` (covered separately), which validates and copies headers for you. ## Gotcha A `Message` is meant to be **immutable** — you don't mutate a received message's headers in place; you build a new message when you need changes.

  • Which concrete class typically implements Message<T>?
    GenericMessage<T> in org.springframework.messaging.support — the default immutable implementation carrying a payload plus copied-in headers.
  • Name two headers Spring assigns automatically.
    id (a per-message UUID under MessageHeaders.ID) and timestamp (epoch-millis Long under MessageHeaders.TIMESTAMP).

saying these in an interview costs you the question

  • Thinking Message is JMS/Kafka-specific — it is Spring's transport-agnostic abstraction
  • Confusing payload with headers
  • Believing you must set id/timestamp yourself

context

open as a page

How do you build a Message with custom headers, and why can't you just mutate headers on an existing message?

level: middleimportance: must knowfreq 65%

basics

~10 s

Use MessageBuilder: MessageBuilder.withPayload(body).setHeader("key", value).build(). You can't mutate an existing message's headers because MessageHeaders is immutable — instead you build a new message, optionally copying the old headers.

open as a page

What standard headers does Spring assign to every message, and what are the consequences of their auto-generation?

level: middleimportance: should knowfreq 40%

basics

~10 s

Spring auto-assigns id (a unique UUID) and timestamp (creation epoch millis) to every MessageHeaders. You read them via getId()/getTimestamp() but never set them yourself — the framework generates them when the message is built.

open as a page

What is MessageHeaderAccessor and how does it relate to MessageBuilder and the standard headers?

level: seniorimportance: should knowfreq 45%

basics

~20 s

MessageHeaderAccessor is a mutable, typed wrapper for building/reading headers. You mutate it freely, then call toMessage() (or hand it to MessageBuilder) to produce an immutable message. It also exposes typed getters for standard headers like id, timestamp, replyChannel, and contentType.

open as a page

Why did Spring make MessageHeaders immutable, and what design and correctness trade-offs does that impose on a messaging pipeline?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

Immutable headers make a message safe to share across threads and channels without defensive copying, and keep identity (id/timestamp) stable. The cost is that every change means allocating a new message, and mutable payloads still aren't protected — immutability only covers the header map.

open as a page