|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2018 the original author or authors. |
| 2 | + * Copyright 2002-2020 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
38 | 38 | import org.springframework.util.StringUtils;
|
39 | 39 |
|
40 | 40 | /**
|
41 |
| - * A base for classes providing strongly typed getters and setters as well as |
42 |
| - * behavior around specific categories of headers (e.g. STOMP headers). |
43 |
| - * Supports creating new headers, modifying existing headers (when still mutable), |
44 |
| - * or copying and modifying existing headers. |
45 |
| - * |
46 |
| - * <p>The method {@link #getMessageHeaders()} provides access to the underlying, |
47 |
| - * fully-prepared {@link MessageHeaders} that can then be used as-is (i.e. |
48 |
| - * without copying) to create a single message as follows: |
| 41 | + * Wrapper around {@link MessageHeaders} that provides extra features such as |
| 42 | + * strongly typed accessors for specific headers, the ability to leave headers |
| 43 | + * in a {@link Message} mutable, and the option to suppress automatic generation |
| 44 | + * of {@link MessageHeaders#ID id} and {@link MessageHeaders#TIMESTAMP |
| 45 | + * timesteamp} headers. Sub-classes such as {@link NativeMessageHeaderAccessor} |
| 46 | + * and others provide support for managing processing vs external source headers |
| 47 | + * as well as protocol specific headers. |
49 | 48 | *
|
| 49 | + * <p>Below is a workflow to initialize headers via {@code MessageHeaderAccessor}, |
| 50 | + * or one of its sub-classes, then create a {@link Message}, and then re-obtain |
| 51 | + * the accessor possibly from a different component: |
50 | 52 | * <pre class="code">
|
| 53 | + * // Create a message with headers |
51 | 54 | * MessageHeaderAccessor accessor = new MessageHeaderAccessor();
|
52 | 55 | * accessor.setHeader("foo", "bar");
|
53 |
| - * Message message = MessageBuilder.createMessage("payload", accessor.getMessageHeaders()); |
54 |
| - * </pre> |
| 56 | + * MessageHeaders headers = accessor.getMessageHeaders(); |
| 57 | + * Message message = MessageBuilder.createMessage("payload", headers); |
55 | 58 | *
|
56 |
| - * <p>After the above, by default the {@code MessageHeaderAccessor} becomes |
57 |
| - * immutable. However it is possible to leave it mutable for further initialization |
58 |
| - * in the same thread, for example: |
| 59 | + * // Later on |
| 60 | + * MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message); |
| 61 | + * Assert.notNull(accessor, "No MessageHeaderAccessor"); |
| 62 | + * </pre> |
59 | 63 | *
|
| 64 | + * <p>In order for the above to work, all participating components must use |
| 65 | + * {@code MessageHeaders} to create, access, or modify headers, or otherwise |
| 66 | + * {@link MessageHeaderAccessor#getAccessor(Message, Class)} will return null. |
| 67 | + * Below is a workflow that shows how headers are created and left mutable, |
| 68 | + * then modified possibly by a different component, and finally made immutable |
| 69 | + * perhaps before the possibility of being accessed on a different thread: |
60 | 70 | * <pre class="code">
|
| 71 | + * // Create a message with mutable headers |
61 | 72 | * MessageHeaderAccessor accessor = new MessageHeaderAccessor();
|
62 | 73 | * accessor.setHeader("foo", "bar");
|
63 | 74 | * accessor.setLeaveMutable(true);
|
64 |
| - * Message message = MessageBuilder.createMessage("payload", accessor.getMessageHeaders()); |
| 75 | + * MessageHeaders headers = accessor.getMessageHeaders(); |
| 76 | + * Message message = MessageBuilder.createMessage("payload", headers); |
65 | 77 | *
|
66 |
| - * // later on in the same thread... |
| 78 | + * // Later on |
| 79 | + * MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message); |
| 80 | + * if (accessor.isMutable()) { |
| 81 | + * // It's mutable, just change the headers |
| 82 | + * accessor.setHeader("bar", "baz"); |
| 83 | + * } |
| 84 | + * else { |
| 85 | + * // It's not, so get a mutable copy, change and re-create |
| 86 | + * accessor = MessageHeaderAccessor.getMutableAccessor(message); |
| 87 | + * accessor.setHeader("bar", "baz"); |
| 88 | + * accessor.setLeaveMutable(true); // leave mutable again or not? |
| 89 | + * message = MessageBuilder.createMessage(message.getPayload(), accessor); |
| 90 | + * } |
67 | 91 | *
|
| 92 | + * // Make the accessor immutable |
68 | 93 | * MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message);
|
69 |
| - * accessor.setHeader("bar", "baz"); |
70 | 94 | * accessor.setImmutable();
|
71 | 95 | * </pre>
|
72 | 96 | *
|
73 |
| - * <p>The method {@link #toMap()} returns a copy of the underlying headers. It can |
74 |
| - * be used to prepare multiple messages from the same {@code MessageHeaderAccessor} |
75 |
| - * instance: |
76 |
| - * <pre class="code"> |
77 |
| - * MessageHeaderAccessor accessor = new MessageHeaderAccessor(); |
78 |
| - * MessageBuilder builder = MessageBuilder.withPayload("payload").setHeaders(accessor); |
79 |
| - * |
80 |
| - * accessor.setHeader("foo", "bar1"); |
81 |
| - * Message message1 = builder.build(); |
82 |
| - * |
83 |
| - * accessor.setHeader("foo", "bar2"); |
84 |
| - * Message message2 = builder.build(); |
85 |
| - * |
86 |
| - * accessor.setHeader("foo", "bar3"); |
87 |
| - * Message message3 = builder.build(); |
88 |
| - * </pre> |
89 |
| - * |
90 |
| - * <p>However note that with the above style, the header accessor is shared and |
91 |
| - * cannot be re-obtained later on. Alternatively it is also possible to create |
92 |
| - * one {@code MessageHeaderAccessor} per message: |
93 |
| - * |
94 |
| - * <pre class="code"> |
95 |
| - * MessageHeaderAccessor accessor1 = new MessageHeaderAccessor(); |
96 |
| - * accessor.set("foo", "bar1"); |
97 |
| - * Message message1 = MessageBuilder.createMessage("payload", accessor1.getMessageHeaders()); |
98 |
| - * |
99 |
| - * MessageHeaderAccessor accessor2 = new MessageHeaderAccessor(); |
100 |
| - * accessor.set("foo", "bar2"); |
101 |
| - * Message message2 = MessageBuilder.createMessage("payload", accessor2.getMessageHeaders()); |
102 |
| - * |
103 |
| - * MessageHeaderAccessor accessor3 = new MessageHeaderAccessor(); |
104 |
| - * accessor.set("foo", "bar3"); |
105 |
| - * Message message3 = MessageBuilder.createMessage("payload", accessor3.getMessageHeaders()); |
106 |
| - * </pre> |
107 |
| - * |
108 |
| - * <p>Note that the above examples aim to demonstrate the general idea of using |
109 |
| - * header accessors. The most likely usage however is through subclasses. |
110 |
| - * |
111 | 97 | * @author Rossen Stoyanchev
|
112 | 98 | * @author Juergen Hoeller
|
113 | 99 | * @since 4.0
|
@@ -566,6 +552,21 @@ public String toString() {
|
566 | 552 |
|
567 | 553 | // Static factory methods
|
568 | 554 |
|
| 555 | + /** |
| 556 | + * Return the original {@code MessageHeaderAccessor} used to create the headers |
| 557 | + * of the given {@code Message}, or {@code null} if that's not available or if |
| 558 | + * its type does not match the required type. |
| 559 | + * <p>This is for cases where the existence of an accessor is strongly expected |
| 560 | + * (followed up with an assertion) or where an accessor will be created otherwise. |
| 561 | + * @param message the message to get an accessor for |
| 562 | + * @return an accessor instance of the specified type, or {@code null} if none |
| 563 | + * @since 5.1.19 |
| 564 | + */ |
| 565 | + @Nullable |
| 566 | + public static MessageHeaderAccessor getAccessor(Message<?> message) { |
| 567 | + return getAccessor(message.getHeaders(), null); |
| 568 | + } |
| 569 | + |
569 | 570 | /**
|
570 | 571 | * Return the original {@code MessageHeaderAccessor} used to create the headers
|
571 | 572 | * of the given {@code Message}, or {@code null} if that's not available or if
|
@@ -625,6 +626,11 @@ public static MessageHeaderAccessor getMutableAccessor(Message<?> message) {
|
625 | 626 | }
|
626 | 627 |
|
627 | 628 |
|
| 629 | + /** |
| 630 | + * Extension of {@link MessageHeaders} that helps to preserve the link to |
| 631 | + * the outer {@link MessageHeaderAccessor} instance that created it as well |
| 632 | + * as keeps track of whether headers are still mutable. |
| 633 | + */ |
628 | 634 | @SuppressWarnings("serial")
|
629 | 635 | private class MutableMessageHeaders extends MessageHeaders {
|
630 | 636 |
|
|
0 commit comments