What is Spring's Message<T> abstraction, and what are its two parts?
answer
- payload + headers
- org.springframework.messaging
- getPayload / getHeaders
- id + timestamp auto
- GenericMessage default impl
basics
~10 sMessage<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 sMessage<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 linesimport 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 Longgo deeper
Know it is payload + headers and where the package lives.
Know GenericMessage and the auto-assigned id/timestamp headers.
Explain the transport-agnostic role across Integration/Stream/STOMP and header-based routing.
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