|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2002-2018 the original author or authors. |
|
|
|
* Copyright 2002-2020 the original author or authors. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -39,76 +39,62 @@ import org.springframework.util.PatternMatchUtils; |
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* A base for classes providing strongly typed getters and setters as well as |
|
|
|
* Wrapper around {@link MessageHeaders} that provides extra features such as |
|
|
|
* behavior around specific categories of headers (e.g. STOMP headers). |
|
|
|
* strongly typed accessors for specific headers, the ability to leave headers |
|
|
|
* Supports creating new headers, modifying existing headers (when still mutable), |
|
|
|
* in a {@link Message} mutable, and the option to suppress automatic generation |
|
|
|
* or copying and modifying existing headers. |
|
|
|
* of {@link MessageHeaders#ID id} and {@link MessageHeaders#TIMESTAMP |
|
|
|
* |
|
|
|
* timesteamp} headers. Sub-classes such as {@link NativeMessageHeaderAccessor} |
|
|
|
* <p>The method {@link #getMessageHeaders()} provides access to the underlying, |
|
|
|
* and others provide support for managing processing vs external source headers |
|
|
|
* fully-prepared {@link MessageHeaders} that can then be used as-is (i.e. |
|
|
|
* as well as protocol specific headers. |
|
|
|
* without copying) to create a single message as follows: |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
|
|
|
|
* <p>Below is a workflow to initialize headers via {@code MessageHeaderAccessor}, |
|
|
|
|
|
|
|
* or one of its sub-classes, then create a {@link Message}, and then re-obtain |
|
|
|
|
|
|
|
* the accessor possibly from a different component: |
|
|
|
* <pre class="code"> |
|
|
|
* <pre class="code"> |
|
|
|
|
|
|
|
* // Create a message with headers
|
|
|
|
* MessageHeaderAccessor accessor = new MessageHeaderAccessor(); |
|
|
|
* MessageHeaderAccessor accessor = new MessageHeaderAccessor(); |
|
|
|
* accessor.setHeader("foo", "bar"); |
|
|
|
* accessor.setHeader("foo", "bar"); |
|
|
|
* Message message = MessageBuilder.createMessage("payload", accessor.getMessageHeaders()); |
|
|
|
* MessageHeaders headers = accessor.getMessageHeaders(); |
|
|
|
* </pre> |
|
|
|
* Message message = MessageBuilder.createMessage("payload", headers); |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>After the above, by default the {@code MessageHeaderAccessor} becomes |
|
|
|
* // Later on
|
|
|
|
* immutable. However it is possible to leave it mutable for further initialization |
|
|
|
* MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message); |
|
|
|
* in the same thread, for example: |
|
|
|
* Assert.notNull(accessor, "No MessageHeaderAccessor"); |
|
|
|
|
|
|
|
* </pre> |
|
|
|
* |
|
|
|
* |
|
|
|
|
|
|
|
* <p>In order for the above to work, all participating components must use |
|
|
|
|
|
|
|
* {@code MessageHeaders} to create, access, or modify headers, or otherwise |
|
|
|
|
|
|
|
* {@link MessageHeaderAccessor#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: |
|
|
|
* <pre class="code"> |
|
|
|
* <pre class="code"> |
|
|
|
|
|
|
|
* // Create a message with mutable headers
|
|
|
|
* MessageHeaderAccessor accessor = new MessageHeaderAccessor(); |
|
|
|
* MessageHeaderAccessor accessor = new MessageHeaderAccessor(); |
|
|
|
* accessor.setHeader("foo", "bar"); |
|
|
|
* accessor.setHeader("foo", "bar"); |
|
|
|
* accessor.setLeaveMutable(true); |
|
|
|
* accessor.setLeaveMutable(true); |
|
|
|
* Message message = MessageBuilder.createMessage("payload", accessor.getMessageHeaders()); |
|
|
|
* MessageHeaders headers = accessor.getMessageHeaders(); |
|
|
|
* |
|
|
|
* Message message = MessageBuilder.createMessage("payload", headers); |
|
|
|
* // later on in the same thread...
|
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
|
|
|
|
* // Later on
|
|
|
|
* MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message); |
|
|
|
* MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message); |
|
|
|
|
|
|
|
* if (accessor.isMutable()) { |
|
|
|
|
|
|
|
* // It's mutable, just change the headers
|
|
|
|
* accessor.setHeader("bar", "baz"); |
|
|
|
* accessor.setHeader("bar", "baz"); |
|
|
|
* accessor.setImmutable(); |
|
|
|
* } |
|
|
|
* </pre> |
|
|
|
* else { |
|
|
|
* |
|
|
|
* // It's not, so get a mutable copy, change and re-create
|
|
|
|
* <p>The method {@link #toMap()} returns a copy of the underlying headers. It can |
|
|
|
* accessor = MessageHeaderAccessor.getMutableAccessor(message); |
|
|
|
* be used to prepare multiple messages from the same {@code MessageHeaderAccessor} |
|
|
|
* accessor.setHeader("bar", "baz"); |
|
|
|
* instance: |
|
|
|
* accessor.setLeaveMutable(true); // leave mutable again or not?
|
|
|
|
* <pre class="code"> |
|
|
|
* message = MessageBuilder.createMessage(message.getPayload(), accessor); |
|
|
|
* MessageHeaderAccessor accessor = new MessageHeaderAccessor(); |
|
|
|
* } |
|
|
|
* MessageBuilder builder = MessageBuilder.withPayload("payload").setHeaders(accessor); |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* accessor.setHeader("foo", "bar1"); |
|
|
|
|
|
|
|
* Message message1 = builder.build(); |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* accessor.setHeader("foo", "bar2"); |
|
|
|
|
|
|
|
* Message message2 = builder.build(); |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* accessor.setHeader("foo", "bar3"); |
|
|
|
|
|
|
|
* Message message3 = builder.build(); |
|
|
|
|
|
|
|
* </pre> |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* <p>However note that with the above style, the header accessor is shared and |
|
|
|
|
|
|
|
* cannot be re-obtained later on. Alternatively it is also possible to create |
|
|
|
|
|
|
|
* one {@code MessageHeaderAccessor} per message: |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* <pre class="code"> |
|
|
|
|
|
|
|
* MessageHeaderAccessor accessor1 = new MessageHeaderAccessor(); |
|
|
|
|
|
|
|
* accessor.set("foo", "bar1"); |
|
|
|
|
|
|
|
* Message message1 = MessageBuilder.createMessage("payload", accessor1.getMessageHeaders()); |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* MessageHeaderAccessor accessor2 = new MessageHeaderAccessor(); |
|
|
|
|
|
|
|
* accessor.set("foo", "bar2"); |
|
|
|
|
|
|
|
* Message message2 = MessageBuilder.createMessage("payload", accessor2.getMessageHeaders()); |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* MessageHeaderAccessor accessor3 = new MessageHeaderAccessor(); |
|
|
|
* // Make the accessor immutable
|
|
|
|
* accessor.set("foo", "bar3"); |
|
|
|
* MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message); |
|
|
|
* Message message3 = MessageBuilder.createMessage("payload", accessor3.getMessageHeaders()); |
|
|
|
* accessor.setImmutable(); |
|
|
|
* </pre> |
|
|
|
* </pre> |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>Note that the above examples aim to demonstrate the general idea of using |
|
|
|
|
|
|
|
* header accessors. The most likely usage however is through subclasses. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @author Rossen Stoyanchev |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
* @author Juergen Hoeller |
|
|
|
* @author Juergen Hoeller |
|
|
|
* @since 4.0 |
|
|
|
* @since 4.0 |
|
|
|
@ -568,6 +554,21 @@ public class MessageHeaderAccessor { |
|
|
|
|
|
|
|
|
|
|
|
// Static factory methods
|
|
|
|
// Static factory methods
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Return the original {@code MessageHeaderAccessor} used to create the headers |
|
|
|
|
|
|
|
* of the given {@code Message}, or {@code null} if that's not available or if |
|
|
|
|
|
|
|
* its type does not match the required type. |
|
|
|
|
|
|
|
* <p>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. |
|
|
|
|
|
|
|
* @param message the message to get an accessor for |
|
|
|
|
|
|
|
* @return an accessor instance of the specified type, or {@code null} if none |
|
|
|
|
|
|
|
* @since 5.1.19 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
|
|
|
public static MessageHeaderAccessor getAccessor(Message<?> message) { |
|
|
|
|
|
|
|
return getAccessor(message.getHeaders(), null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Return the original {@code MessageHeaderAccessor} used to create the headers |
|
|
|
* Return the original {@code MessageHeaderAccessor} used to create the headers |
|
|
|
* of the given {@code Message}, or {@code null} if that's not available or if |
|
|
|
* of the given {@code Message}, or {@code null} if that's not available or if |
|
|
|
@ -627,6 +628,11 @@ public class MessageHeaderAccessor { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Extension of {@link MessageHeaders} that helps to preserve the link to |
|
|
|
|
|
|
|
* the outer {@link MessageHeaderAccessor} instance that created it as well |
|
|
|
|
|
|
|
* as keeps track of whether headers are still mutable. |
|
|
|
|
|
|
|
*/ |
|
|
|
@SuppressWarnings("serial") |
|
|
|
@SuppressWarnings("serial") |
|
|
|
private class MutableMessageHeaders extends MessageHeaders { |
|
|
|
private class MutableMessageHeaders extends MessageHeaders { |
|
|
|
|
|
|
|
|
|
|
|
|