From 008a740fb0bf1dc3f83646368f3fe689af6c6202 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Fri, 15 Sep 2017 15:24:54 -0400 Subject: [PATCH] Add option for MutableMB to not generate headers Since `MutableMessage` can be mutated, the `ID` and `TIMESTAMP` headers can be added lately. Or there might be some scenarios which don't care about those headers at all. Plus we get a performance gain when we skip their generation Coerce the `null` cast to the proper target ctor --- .../integration/support/MutableMessage.java | 14 +++--- .../support/MutableMessageBuilder.java | 44 ++++++++++++++----- .../support/MutableMessageHeaders.java | 9 +++- .../message/MessageBuilderTests.java | 35 ++++++++++++--- 4 files changed, 78 insertions(+), 24 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessage.java b/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessage.java index 27a90b8a7e..f86b7ee545 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessage.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessage.java @@ -37,6 +37,7 @@ import org.springframework.util.ObjectUtils; * @author Artem Bilan * @author Stuart Williams * @author David Turanski + * * @since 4.0 * */ @@ -49,16 +50,19 @@ public class MutableMessage implements Message, Serializable { private final MutableMessageHeaders headers; public MutableMessage(T payload) { - this(payload, null); + this(payload, (Map) null); } public MutableMessage(T payload, Map headers) { - Assert.notNull(payload, "payload must not be null"); - this.payload = payload; - - this.headers = new MutableMessageHeaders(headers); + this(payload, new MutableMessageHeaders(headers)); } + protected MutableMessage(T payload, MutableMessageHeaders headers) { + Assert.notNull(payload, "payload must not be null"); + Assert.notNull(headers, "headers must not be null"); + this.payload = payload; + this.headers = headers; + } @Override public MutableMessageHeaders getHeaders() { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageBuilder.java b/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageBuilder.java index 77dde69ff4..e8197b5fce 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageBuilder.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageBuilder.java @@ -23,6 +23,7 @@ import java.util.Map.Entry; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; import org.springframework.util.Assert; import org.springframework.util.PatternMatchUtils; import org.springframework.util.StringUtils; @@ -64,6 +65,39 @@ public final class MutableMessageBuilder extends AbstractIntegrationMessageBu return this.headers; } + /** + * Create a builder for a new {@link Message} instance with the provided payload. + * @param payload the payload for the new message + * @param The type of the payload. + * @return A MutableMessageBuilder. + */ + public static MutableMessageBuilder withPayload(T payload) { + return withPayload(payload, true); + } + + /** + * Create a builder for a new {@link Message} instance with the provided payload. + * The {@code generateHeaders} flag allows to disable {@link MessageHeaders#ID} + * and {@link MessageHeaders#TIMESTAMP} headers generation. + * @param payload the payload for the new message + * @param generateHeaders whether generate {@link MessageHeaders#ID} + * and {@link MessageHeaders#TIMESTAMP} headers + * @param The type of the payload. + * @return A MutableMessageBuilder. + * @since 5.0 + */ + public static MutableMessageBuilder withPayload(T payload, boolean generateHeaders) { + MutableMessage message; + if (generateHeaders) { + message = new MutableMessage<>(payload); + } + else { + message = new MutableMessage<>(payload, new MutableMessageHeaders(null, MessageHeaders.ID_VALUE_NONE, -1L)); + } + + return fromMessage(message); + } + /** * Create a builder for a new {@link Message} instance pre-populated with all of the headers copied from the * provided message. The payload of the provided Message will also be used as the payload for the new message. @@ -76,16 +110,6 @@ public final class MutableMessageBuilder extends AbstractIntegrationMessageBu return new MutableMessageBuilder(message); } - /** - * Create a builder for a new {@link Message} instance with the provided payload. - * @param payload the payload for the new message - * @param The type of the payload. - * @return A MessageBuilder. - */ - public static MutableMessageBuilder withPayload(T payload) { - return new MutableMessageBuilder(new MutableMessage(payload)); - } - @Override public AbstractIntegrationMessageBuilder setHeader(String headerName, Object headerValue) { Assert.notNull(headerName, "'headerName' must not be null"); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageHeaders.java b/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageHeaders.java index 08691735e1..c6b58ad9ea 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageHeaders.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/MutableMessageHeaders.java @@ -19,6 +19,7 @@ package org.springframework.integration.support; import java.util.Map; import java.util.UUID; +import org.springframework.lang.Nullable; import org.springframework.messaging.MessageHeaders; @@ -36,8 +37,8 @@ public class MutableMessageHeaders extends MessageHeaders { private static final long serialVersionUID = 3084692953798643018L; - public MutableMessageHeaders(Map headers) { - super(headers, + public MutableMessageHeaders(@Nullable Map headers) { + this(headers, (headers != null ? (UUID) headers.get(MessageHeaders.ID) : null), @@ -46,6 +47,10 @@ public class MutableMessageHeaders extends MessageHeaders { : null)); } + protected MutableMessageHeaders(@Nullable Map headers, @Nullable UUID id, @Nullable Long timestamp) { + super(headers, id, timestamp); + } + @Override protected Map getRawHeaders() { return super.getRawHeaders(); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/message/MessageBuilderTests.java b/spring-integration-core/src/test/java/org/springframework/integration/message/MessageBuilderTests.java index 3937809b44..44e8cd08f9 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/message/MessageBuilderTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/message/MessageBuilderTests.java @@ -16,11 +16,15 @@ package org.springframework.integration.message; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.springframework.integration.test.matcher.HeaderMatcher.hasHeaderKey; import java.util.Date; import java.util.HashMap; @@ -34,6 +38,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.support.MessageBuilderFactory; +import org.springframework.integration.support.MutableMessage; import org.springframework.integration.support.MutableMessageBuilder; import org.springframework.integration.support.MutableMessageBuilderFactory; import org.springframework.messaging.Message; @@ -77,7 +82,7 @@ public class MessageBuilderTests { public void testHeaderValues() { Message message = MessageBuilder.withPayload("test") .setHeader("foo", "bar") - .setHeader("count", new Integer(123)) + .setHeader("count", 123) .build(); assertEquals("bar", message.getHeaders().get("foo", String.class)); assertEquals(new Integer(123), message.getHeaders().get("count", Integer.class)); @@ -146,11 +151,11 @@ public class MessageBuilderTests { @Test public void mutate() { - assertTrue(messageBuilderFactory instanceof MutableMessageBuilderFactory); - in.send(new GenericMessage("foo")); + assertTrue(this.messageBuilderFactory instanceof MutableMessageBuilderFactory); + in.send(new GenericMessage<>("foo")); Message m1 = out.receive(0); Message m2 = out.receive(0); - assertEquals("org.springframework.integration.support.MutableMessage", m1.getClass().getName()); + assertThat(m1, instanceOf(MutableMessage.class)); assertTrue(m1 == m2); } @@ -190,7 +195,7 @@ public class MessageBuilderTests { @Test public void testPriority() { Message importantMessage = MessageBuilder.withPayload(1) - .setPriority(123).build(); + .setPriority(123).build(); assertEquals(new Integer(123), new IntegrationMessageHeaderAccessor(importantMessage).getPriority()); } @@ -199,8 +204,8 @@ public class MessageBuilderTests { Message message1 = MessageBuilder.withPayload(1) .setPriority(42).build(); Message message2 = MessageBuilder.fromMessage(message1) - .setHeaderIfAbsent(IntegrationMessageHeaderAccessor.PRIORITY, 13) - .build(); + .setHeaderIfAbsent(IntegrationMessageHeaderAccessor.PRIORITY, 13) + .build(); assertEquals(new Integer(42), new IntegrationMessageHeaderAccessor(message2).getPriority()); } @@ -358,7 +363,23 @@ public class MessageBuilderTests { .setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER, Long.MAX_VALUE) .build(); + @SuppressWarnings("unused") Integer sequenceNumber = new IntegrationMessageHeaderAccessor(message).getSequenceNumber(); } + @Test + public void testNoIdAndTimestampHeaders() { + Message message = + MutableMessageBuilder.withPayload("foo", false) + .pushSequenceDetails("bar", 1, 1) + .build(); + + assertThat(message, hasHeaderKey(IntegrationMessageHeaderAccessor.CORRELATION_ID)); + assertThat(message, hasHeaderKey(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER)); + assertThat(message, hasHeaderKey(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE)); + assertThat(message, not(hasHeaderKey(IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS))); + assertThat(message, not(hasHeaderKey(MessageHeaders.ID))); + assertThat(message, not(hasHeaderKey(MessageHeaders.TIMESTAMP))); + } + }