INT-4365: Improve notPropagatedHeaders function

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

It is much useful to configure the `notPropagatedHeaders` as a set of
patterns to match.
In this case we can filter a group of headers with the common prefix or
suffix

* Allow to configure `AbstractMessageProducingHandler.setNotPropagatedHeaders`
as simple patterns; the `*` means filter all - not copy request headers
at all - similar to `transformer` behavior
* Add `ConsumerEndpointSpec.notPropagatedHeaders()` for Java DSL
* Add `not-propagated-headers` to the `<service-activator>`

Address PR comments; some other improvements

* Fix `ConsumerEndpointSpec#notPropagatedHeaders()` log message
* Improve `AbstractMessageProducingHandler.notPropagatedHeaders() logic
so any `*` in the set of patterns eliminates all others since it has
a highest priority
* Expose `requires-reply` for the `<transformer>` as a `true` by default
* Refactor a bit `AbstractStandardMessageHandlerFactoryBean` hierarchy to
avoid duplicated code

* Fix `message.adoc`
* Add `noHeadersPropagation` flag to the `AbstractMessageProducingHandler`
* Rework logic in the `updateNotPropagatedHeaders()` to store the array
of patterns instead of `Set` to avoid extra operation on each message
* Combine `noHeadersPropagation` with the `shouldCopyRequestHeaders()`
in the `createOutputMessage()` for logic to determine if we should start
the copy-headers procedure at all

* Revert `AbstractMessageProducingHandler.selectiveHeaderPropagation`
* Optimize `AmqpOutboundGatewayParserTests` performance from 3 secs to 0.5

Fix more NPEs in the `AbstractMessageProducingHandler`
This commit is contained in:
Artem Bilan
2017-11-17 16:53:19 -05:00
committed by Gary Russell
parent 7c701ca5e6
commit 90c46f5a79
17 changed files with 230 additions and 199 deletions

View File

@@ -46,6 +46,7 @@ import org.springframework.messaging.support.GenericMessage;
* @author Gunnar Hillert
* @author Gary Russell
* @author Marius Bogoevici
* @author Artem Bilan
*/
@RunWith(MockitoJUnitRunner.class)
public class AbstractReplyProducingMessageHandlerTests {
@@ -80,19 +81,20 @@ public class AbstractReplyProducingMessageHandlerTests {
}
@Test
@SuppressWarnings("unchecked")
public void testNotPropagate() {
AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
return new GenericMessage<String>("world", Collections.singletonMap("bar", "RAB"));
return new GenericMessage<>("world", Collections.singletonMap("bar", "RAB"));
}
};
assertThat(handler.getNotPropagatedHeaders(), emptyCollectionOf(String.class));
handler.setNotPropagatedHeaders("foo", "bar");
handler.setNotPropagatedHeaders("f*", "*r");
handler.setOutputChannel(this.channel);
assertThat(handler.getNotPropagatedHeaders(), containsInAnyOrder("foo", "bar"));
assertThat(handler.getNotPropagatedHeaders(), containsInAnyOrder("f*", "*r"));
ArgumentCaptor<Message<?>> captor = ArgumentCaptor.forClass(Message.class);
willReturn(true).given(this.channel).send(captor.capture());
handler.handleMessage(MessageBuilder.withPayload("hello")
@@ -120,9 +122,9 @@ public class AbstractReplyProducingMessageHandlerTests {
};
assertThat(handler.getNotPropagatedHeaders(), emptyCollectionOf(String.class));
handler.setNotPropagatedHeaders("foo");
handler.addNotPropagatedHeaders("bar");
handler.addNotPropagatedHeaders("b*r");
handler.setOutputChannel(this.channel);
assertThat(handler.getNotPropagatedHeaders(), containsInAnyOrder("foo", "bar"));
assertThat(handler.getNotPropagatedHeaders(), containsInAnyOrder("foo", "b*r"));
ArgumentCaptor<Message<?>> captor =
(ArgumentCaptor<Message<?>>) (ArgumentCaptor<?>) ArgumentCaptor.forClass(Message.class);
willReturn(true).given(this.channel).send(captor.capture());

View File

@@ -38,7 +38,10 @@
class="org.springframework.integration.handler.ServiceActivatorDefaultFrameworkMethodTests$TestMessageHandler"/>
</service-activator>
<service-activator id="processorTestService" input-channel="processorTestInputChannel" ref="testMessageProcessor"/>
<service-activator id="processorTestService"
input-channel="processorTestInputChannel"
ref="testMessageProcessor"
not-propagated-headers="*"/>
<gateway id="gateway" default-request-channel="requestChannel" default-reply-channel="replyChannel"/>

View File

@@ -19,6 +19,7 @@ package org.springframework.integration.handler;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
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.assertNotNull;
@@ -27,6 +28,7 @@ import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.springframework.integration.test.matcher.HeaderMatcher.hasHeaderKey;
import java.util.concurrent.atomic.AtomicReference;
@@ -189,18 +191,20 @@ public class ServiceActivatorDefaultFrameworkMethodTests {
this.handlerTestInputChannel.send(message);
}
// INT-2399
@Test
public void testMessageProcessor() {
Object processor = TestUtils.getPropertyValue(processorTestService, "handler.processor");
assertSame(testMessageProcessor, processor);
QueueChannel replyChannel = new QueueChannel();
Message<?> message = MessageBuilder.withPayload("bar").setReplyChannel(replyChannel).build();
Message<?> message = MessageBuilder.withPayload("bar")
.setReplyChannel(replyChannel)
.setHeader("foo", "foo")
.build();
this.processorTestInputChannel.send(message);
Message<?> reply = replyChannel.receive(0);
assertEquals("foo:bar", reply.getPayload());
assertEquals("processorTestInputChannel,processorTestService", reply.getHeaders().get("history").toString());
assertThat(reply, not(hasHeaderKey("foo")));
}
@Test

View File

@@ -25,7 +25,8 @@
<beans:bean class="org.springframework.integration.transformer.TransformerContextTests$Bar"/>
</transformer>
<transformer input-channel="directRef" output-channel="output" ref="trans" method="handleMessage"/>
<transformer input-channel="directRef" output-channel="output" ref="trans" method="handleMessage"
requires-reply="false"/>
<beans:bean id="trans" class="org.springframework.integration.transformer.TransformerContextTests$Bar"/>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.transformer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -90,6 +91,9 @@ public class TransformerContextTests {
assertFalse(this.testBean.isRunning());
this.pojoTransformer.start();
assertTrue(this.testBean.isRunning());
this.directRef.send(new GenericMessage<String>("bar"));
assertNull(this.output.receive(0));
}
public static class FooAdvice extends AbstractRequestHandlerAdvice {
@@ -106,6 +110,9 @@ public class TransformerContextTests {
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
if ("bar".equals(requestMessage.getPayload())) {
return null;
}
Exception e = new RuntimeException();
StackTraceElement[] st = e.getStackTrace();
return MessageBuilder.withPayload(requestMessage.getPayload().toString().toUpperCase())