INT-3555: Fix Header Channel Mapping

JIRA: https://jira.spring.io/browse/INT-3555

Previously, `replyChannel` and `errorChannel` headers were
unconditionally dropped in `AbstractHeaderMapper`. This was
changed in 4.1.0.M1 to allow these headers to be transmitted
in the case that they were translated to a String by a
`HeaderChannelRegistry`.

However, we should still drop these headers if they reference live
`MessageChannel` instances.
This commit is contained in:
Gary Russell
2014-11-07 10:20:20 -05:00
committed by Artem Bilan
parent 1c9cea162d
commit 90c6f2fa3e
2 changed files with 24 additions and 8 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.integration.amqp.outbound;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
@@ -34,8 +35,10 @@ import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.messaging.MessageHeaders;
import org.springframework.integration.amqp.support.DefaultAmqpHeaderMapper;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageHeaders;
/**
* @author Gary Russell
@@ -73,6 +76,9 @@ public class OutboundEndpointTests {
TestRabbitTemplate amqpTemplate = spy(new TestRabbitTemplate(connectionFactory));
AmqpOutboundEndpoint endpoint = new AmqpOutboundEndpoint(amqpTemplate);
endpoint.setExpectReply(true);
DefaultAmqpHeaderMapper mapper = new DefaultAmqpHeaderMapper();
mapper.setRequestHeaderNames("*");
endpoint.setHeaderMapper(mapper);
final AtomicReference<Message> amqpMessage =
new AtomicReference<Message>();
doAnswer(new Answer<Object>() {
@@ -85,10 +91,12 @@ public class OutboundEndpointTests {
}).when(amqpTemplate).doSendAndReceiveWithTemporary(anyString(), anyString(), any(Message.class));
org.springframework.messaging.Message<?> message = MessageBuilder.withPayload("foo")
.setHeader(MessageHeaders.CONTENT_TYPE, "bar")
.setReplyChannel(new QueueChannel())
.build();
endpoint.handleMessage(message);
assertNotNull(amqpMessage.get());
assertEquals("bar", amqpMessage.get().getMessageProperties().getContentType());
assertNull(amqpMessage.get().getMessageProperties().getHeaders().get(MessageHeaders.REPLY_CHANNEL));
}
/**

View File

@@ -27,6 +27,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHeaders;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@@ -196,7 +197,7 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
private void populateUserDefinedHeaders(Map<String, Object> headers, T target) {
for (String headerName : headers.keySet()) {
Object value = headers.get(headerName);
if (value != null) {
if (value != null && !isMessageChannel(headerName, value)) {
try {
if (!headerName.startsWith(this.standardHeaderPrefix)) {
String key = this.createTargetPropertyName(headerName, true);
@@ -212,6 +213,16 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
}
}
private boolean isMessageChannel(String headerName, Object headerValue) {
if (headerValue instanceof MessageChannel) {
if (logger.isDebugEnabled()) {
logger.debug("Cannot map a MessageChannel instance in header " + headerName);
}
return true;
}
return false;
}
/**
* Map headers from a source instance to the {@link MessageHeaders} of
* a {@link org.springframework.messaging.Message}.
@@ -245,11 +256,8 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
}
private boolean shouldMapHeader(String headerName, HeaderMatcher headerMatcher) {
if (!StringUtils.hasText(headerName)
|| getTransientHeaderNames().contains(headerName)) {
return false;
}
return headerMatcher.matchHeader(headerName);
return !(!StringUtils.hasText(headerName) || getTransientHeaderNames().contains(headerName))
&& headerMatcher.matchHeader(headerName);
}
@SuppressWarnings("unchecked")