Merge branch 'pr/23417'

Closes gh-23417
This commit is contained in:
Rossen Stoyanchev 2019-11-08 15:04:15 +00:00
commit fd453a0753
2 changed files with 41 additions and 17 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2019 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.
@ -41,23 +41,23 @@ public final class MessageBuilder<T> {
private final T payload; private final T payload;
@Nullable @Nullable
private final Message<T> originalMessage; private final Message<T> providedMessage;
private MessageHeaderAccessor headerAccessor; private MessageHeaderAccessor headerAccessor;
private MessageBuilder(Message<T> originalMessage) { private MessageBuilder(Message<T> providedMessage) {
Assert.notNull(originalMessage, "Message must not be null"); Assert.notNull(providedMessage, "Message must not be null");
this.payload = originalMessage.getPayload(); this.payload = providedMessage.getPayload();
this.originalMessage = originalMessage; this.providedMessage = providedMessage;
this.headerAccessor = new MessageHeaderAccessor(originalMessage); this.headerAccessor = new MessageHeaderAccessor(providedMessage);
} }
private MessageBuilder(T payload, MessageHeaderAccessor accessor) { private MessageBuilder(T payload, MessageHeaderAccessor accessor) {
Assert.notNull(payload, "Payload must not be null"); Assert.notNull(payload, "Payload must not be null");
Assert.notNull(accessor, "MessageHeaderAccessor must not be null"); Assert.notNull(accessor, "MessageHeaderAccessor must not be null");
this.payload = payload; this.payload = payload;
this.originalMessage = null; this.providedMessage = null;
this.headerAccessor = accessor; this.headerAccessor = accessor;
} }
@ -99,6 +99,7 @@ public final class MessageBuilder<T> {
this.headerAccessor.removeHeaders(headerPatterns); this.headerAccessor.removeHeaders(headerPatterns);
return this; return this;
} }
/** /**
* Remove the value for the given header name. * Remove the value for the given header name.
*/ */
@ -148,11 +149,17 @@ public final class MessageBuilder<T> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Message<T> build() { public Message<T> build() {
if (this.originalMessage != null && !this.headerAccessor.isModified()) { if (this.providedMessage != null && !this.headerAccessor.isModified()) {
return this.originalMessage; return this.providedMessage;
} }
MessageHeaders headersToUse = this.headerAccessor.toMessageHeaders(); MessageHeaders headersToUse = this.headerAccessor.toMessageHeaders();
if (this.payload instanceof Throwable) { if (this.payload instanceof Throwable) {
if (this.providedMessage != null && this.providedMessage instanceof ErrorMessage) {
Message<?> message = ((ErrorMessage) this.providedMessage).getOriginalMessage();
if (message != null) {
return (Message<T>) new ErrorMessage((Throwable) this.payload, headersToUse, message);
}
}
return (Message<T>) new ErrorMessage((Throwable) this.payload, headersToUse); return (Message<T>) new ErrorMessage((Throwable) this.payload, headersToUse);
} }
else { else {
@ -165,6 +172,9 @@ public final class MessageBuilder<T> {
* Create a builder for a new {@link Message} instance pre-populated with all of the * 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 * headers copied from the provided message. The payload of the provided Message will
* also be used as the payload for the new message. * also be used as the payload for the new message.
* <p>If the provided message is an {@link ErrorMessage}, the
* {@link ErrorMessage#getOriginalMessage() originalMessage} it contains, will be
* passed on to new instance.
* @param message the Message from which the payload and all headers will be copied * @param message the Message from which the payload and all headers will be copied
*/ */
public static <T> MessageBuilder<T> fromMessage(Message<T> message) { public static <T> MessageBuilder<T> fromMessage(Message<T> message) {

View File

@ -16,6 +16,7 @@
package org.springframework.messaging.support; package org.springframework.messaging.support;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -107,6 +108,19 @@ public class MessageBuilderTests {
assertThat(message2.getHeaders().get("foo")).isEqualTo("bar"); assertThat(message2.getHeaders().get("foo")).isEqualTo("bar");
} }
@Test // gh-23417
public void createErrorMessageFromErrorMessage() {
Message<String> source = MessageBuilder.withPayload("test").setHeader("foo", "bar").build();
RuntimeException ex = new RuntimeException();
ErrorMessage errorMessage1 = new ErrorMessage(ex, Collections.singletonMap("baz", "42"), source);
Message<Throwable> errorMessage2 = MessageBuilder.fromMessage(errorMessage1).build();
assertThat(errorMessage2).isExactlyInstanceOf(ErrorMessage.class);
ErrorMessage actual = (ErrorMessage) errorMessage2;
assertThat(actual.getPayload()).isSameAs(ex);
assertThat(actual.getHeaders().get("baz")).isEqualTo("42");
assertThat(actual.getOriginalMessage()).isSameAs(source);
}
@Test @Test
public void createIdRegenerated() { public void createIdRegenerated() {
Message<String> message1 = MessageBuilder.withPayload("test") Message<String> message1 = MessageBuilder.withPayload("test")