Class MessageHeaderAccessor

java.lang.Object
org.springframework.messaging.support.MessageHeaderAccessor
Direct Known Subclasses:
NativeMessageHeaderAccessor

public class MessageHeaderAccessor extends Object
Wrapper around MessageHeaders that provides extra features such as strongly typed accessors for specific headers, the ability to leave headers in a Message mutable, and the option to suppress automatic generation of id and timestamp headers. Subclasses such as NativeMessageHeaderAccessor and others provide support for managing processing vs external source headers as well as protocol specific headers.

Below is a workflow to initialize headers via MessageHeaderAccessor, or one of its subclasses, then create a Message, and then re-obtain the accessor possibly from a different component:

 // Create a message with headers
 MessageHeaderAccessor accessor = new MessageHeaderAccessor();
 accessor.setHeader("foo", "bar");
 MessageHeaders headers = accessor.getMessageHeaders();
 Message message = MessageBuilder.createMessage("payload", headers);

 // Later on
 MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message);
 Assert.notNull(accessor, "No MessageHeaderAccessor");
 

In order for the above to work, all participating components must use MessageHeaders to create, access, or modify headers, or otherwise getAccessor(Message, Class) will return null. Below is a workflow that shows how headers are created and left mutable, then modified possibly by a different component, and finally made immutable perhaps before the possibility of being accessed on a different thread:

 // Create a message with mutable headers
 MessageHeaderAccessor accessor = new MessageHeaderAccessor();
 accessor.setHeader("foo", "bar");
 accessor.setLeaveMutable(true);
 MessageHeaders headers = accessor.getMessageHeaders();
 Message message = MessageBuilder.createMessage("payload", headers);

 // Later on
 MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message);
 if (accessor.isMutable()) {
     // It's mutable, just change the headers
     accessor.setHeader("bar", "baz");
 }
 else {
     // It's not, so get a mutable copy, change and re-create
     accessor = MessageHeaderAccessor.getMutableAccessor(message);
     accessor.setHeader("bar", "baz");
     accessor.setLeaveMutable(true); // leave mutable again or not?
     message = MessageBuilder.createMessage(message.getPayload(), accessor);
 }

 // Make the accessor immutable
 MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message);
 accessor.setImmutable();
 
Since:
4.0
Author:
Rossen Stoyanchev, Juergen Hoeller
  • Field Details

    • DEFAULT_CHARSET

      public static final Charset DEFAULT_CHARSET
      The default charset used for headers.
  • Constructor Details

    • MessageHeaderAccessor

      public MessageHeaderAccessor()
      A constructor to create new headers.
    • MessageHeaderAccessor

      public MessageHeaderAccessor(@Nullable Message<?> message)
      A constructor accepting the headers of an existing message to copy.
      Parameters:
      message - a message to copy the headers from, or null if none
  • Method Details

    • createAccessor

      protected MessageHeaderAccessor createAccessor(Message<?> message)
      Build a 'nested' accessor for the given message.
      Parameters:
      message - the message to build a new accessor for
      Returns:
      the nested accessor (typically a specific subclass)
    • setLeaveMutable

      public void setLeaveMutable(boolean leaveMutable)
      By default, when getMessageHeaders() is called, "this" MessageHeaderAccessor instance can no longer be used to modify the underlying message headers and the returned MessageHeaders is immutable.

      However when this is set to true, the returned (underlying) MessageHeaders instance remains mutable. To make further modifications continue to use the same accessor instance or re-obtain it via:
      MessageHeaderAccessor.getAccessor(Message, Class)

      When modifications are complete use setImmutable() to prevent further changes. The intended use case for this mechanism is initialization of a Message within a single thread.

      By default this is set to false.

      Since:
      4.1
    • setImmutable

      public void setImmutable()
      By default, when getMessageHeaders() is called, "this" MessageHeaderAccessor instance can no longer be used to modify the underlying message headers. However if setLeaveMutable(boolean) is used, this method is necessary to indicate explicitly when the MessageHeaders instance should no longer be modified.
      Since:
      4.1
    • isMutable

      public boolean isMutable()
      Whether the underlying headers can still be modified.
      Since:
      4.1
    • setModified

      protected void setModified(boolean modified)
      Mark the underlying message headers as modified.
      Parameters:
      modified - typically true, or false to reset the flag
      Since:
      4.1
    • isModified

      public boolean isModified()
      Check whether the underlying message headers have been marked as modified.
      Returns:
      true if the flag has been set, false otherwise
    • getMessageHeaders

      public MessageHeaders getMessageHeaders()
      Return the underlying MessageHeaders instance.

      Unless setLeaveMutable(boolean) was set to true, after this call, the headers are immutable and this accessor can no longer modify them.

      This method always returns the same MessageHeaders instance if invoked multiples times. To obtain a copy of the underlying headers, use toMessageHeaders() or toMap() instead.

      Since:
      4.1
    • toMessageHeaders

      public MessageHeaders toMessageHeaders()
      Return a copy of the underlying header values as a MessageHeaders object.

      This method can be invoked many times, with modifications in between where each new call returns a fresh copy of the current header values.

      Since:
      4.1
    • toMap

      public Map<String,Object> toMap()
      Return a copy of the underlying header values as a plain Map object.

      This method can be invoked many times, with modifications in between where each new call returns a fresh copy of the current header values.

    • getHeader

      @Nullable public Object getHeader(String headerName)
      Retrieve the value for the header with the given name.
      Parameters:
      headerName - the name of the header
      Returns:
      the associated value, or null if none found
    • setHeader

      public void setHeader(String name, @Nullable Object value)
      Set the value for the given header name.

      If the provided value is null, the header will be removed.

    • verifyType

      protected void verifyType(@Nullable String headerName, @Nullable Object headerValue)
    • setHeaderIfAbsent

      public void setHeaderIfAbsent(String name, Object value)
      Set the value for the given header name only if the header name is not already associated with a value.
    • removeHeader

      public void removeHeader(String headerName)
      Remove the value for the given header name.
    • removeHeaders

      public void removeHeaders(String... headerPatterns)
      Removes all headers provided via array of 'headerPatterns'.

      As the name suggests, array may contain simple matching patterns for header names. Supported pattern styles are: "xxx*", "*xxx", "*xxx*" and "xxx*yyy".

    • copyHeaders

      public void copyHeaders(@Nullable Map<String,?> headersToCopy)
      Copy the name-value pairs from the provided Map.

      This operation will overwrite any existing values. Use copyHeadersIfAbsent(Map) to avoid overwriting values.

    • copyHeadersIfAbsent

      public void copyHeadersIfAbsent(@Nullable Map<String,?> headersToCopy)
      Copy the name-value pairs from the provided Map.

      This operation will not overwrite any existing values.

    • isReadOnly

      protected boolean isReadOnly(String headerName)
    • getId

      @Nullable public UUID getId()
    • getTimestamp

      @Nullable public Long getTimestamp()
    • setContentType

      public void setContentType(MimeType contentType)
    • getContentType

      @Nullable public MimeType getContentType()
    • setReplyChannelName

      public void setReplyChannelName(String replyChannelName)
    • setReplyChannel

      public void setReplyChannel(MessageChannel replyChannel)
    • getReplyChannel

      @Nullable public Object getReplyChannel()
    • setErrorChannelName

      public void setErrorChannelName(String errorChannelName)
    • setErrorChannel

      public void setErrorChannel(MessageChannel errorChannel)
    • getErrorChannel

      @Nullable public Object getErrorChannel()
    • getShortLogMessage

      public String getShortLogMessage(Object payload)
      Return a concise message for logging purposes.
      Parameters:
      payload - the payload that corresponds to the headers.
      Returns:
      the message
    • getDetailedLogMessage

      public String getDetailedLogMessage(@Nullable Object payload)
      Return a more detailed message for logging purposes.
      Parameters:
      payload - the payload that corresponds to the headers.
      Returns:
      the message
    • getShortPayloadLogMessage

      protected String getShortPayloadLogMessage(Object payload)
    • getDetailedPayloadLogMessage

      protected String getDetailedPayloadLogMessage(@Nullable Object payload)
    • isReadableContentType

      protected boolean isReadableContentType()
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • getAccessor

      @Nullable public static MessageHeaderAccessor getAccessor(Message<?> message)
      Return the original MessageHeaderAccessor used to create the headers of the given Message, or null if that's not available or if its type does not match the required type.

      This is for cases where the existence of an accessor is strongly expected (followed up with an assertion) or where an accessor will be created otherwise.

      Parameters:
      message - the message to get an accessor for
      Returns:
      an accessor instance of the specified type, or null if none
      Since:
      5.1.19
    • getAccessor

      @Nullable public static <T extends MessageHeaderAccessor> T getAccessor(Message<?> message, @Nullable Class<T> requiredType)
      Return the original MessageHeaderAccessor used to create the headers of the given Message, or null if that's not available or if its type does not match the required type.

      This is for cases where the existence of an accessor is strongly expected (followed up with an assertion) or where an accessor will be created otherwise.

      Parameters:
      message - the message to get an accessor for
      requiredType - the required accessor type (or null for any)
      Returns:
      an accessor instance of the specified type, or null if none
      Since:
      4.1
    • getAccessor

      @Nullable public static <T extends MessageHeaderAccessor> T getAccessor(MessageHeaders messageHeaders, @Nullable Class<T> requiredType)
      A variation of getAccessor(org.springframework.messaging.Message, Class) with a MessageHeaders instance instead of a Message.

      This is for cases when a full message may not have been created yet.

      Parameters:
      messageHeaders - the message headers to get an accessor for
      requiredType - the required accessor type (or null for any)
      Returns:
      an accessor instance of the specified type, or null if none
      Since:
      4.1
    • getMutableAccessor

      public static MessageHeaderAccessor getMutableAccessor(Message<?> message)
      Return a mutable MessageHeaderAccessor for the given message attempting to match the type of accessor used to create the message headers, or otherwise wrapping the message with a MessageHeaderAccessor instance.

      This is for cases where a header needs to be updated in generic code while preserving the accessor type for downstream processing.

      Returns:
      an accessor of the required type (never null)
      Since:
      4.1