INT-3500: Consider to add "error-channel" to the <enricher>
JIRA: https://jira.spring.io/browse/INT-3500 * add 'error-channel' to the <enricher> component * delegate errorChannel to the internal gateway in ContentEnricher * added tests for xml based and java based enrichers with error channels INT-3500: Consider to add "error-channel" to the <enricher> * Fixed typos and comments * Reworked xml integration test to use the outputChannel and increased timeout * Added overview in whats-new doc INT-3500: Consider to add "error-channel" to the <enricher> * Ensure requestChannel is set if an errorChannel is set * Increased timeout to fix unit test * Added details to content-enricher ref doc Polishing
This commit is contained in:
@@ -41,6 +41,7 @@ import org.springframework.util.xml.DomUtils;
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
* @author Liujiong
|
||||
* @author Kris Jacyna
|
||||
* @since 2.1
|
||||
*/
|
||||
public class EnricherParser extends AbstractConsumerEndpointParser {
|
||||
@@ -51,6 +52,7 @@ public class EnricherParser extends AbstractConsumerEndpointParser {
|
||||
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "request-channel");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "error-channel");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-timeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
|
||||
@@ -69,19 +71,21 @@ public class EnricherParser extends AbstractConsumerEndpointParser {
|
||||
boolean hasAttributeExpression = StringUtils.hasText(expression);
|
||||
boolean hasAttributeNullResultExpression = StringUtils.hasText(nullResultExpression);
|
||||
|
||||
if (hasAttributeValue && hasAttributeExpression){
|
||||
if (hasAttributeValue && hasAttributeExpression) {
|
||||
parserContext.getReaderContext().error("Only one of 'value' or 'expression' is allowed", element);
|
||||
}
|
||||
|
||||
if (!hasAttributeValue && !hasAttributeExpression && !hasAttributeNullResultExpression){
|
||||
parserContext.getReaderContext().error("One of 'value' or 'expression' or 'null-result-expression' is required", element);
|
||||
if (!hasAttributeValue && !hasAttributeExpression && !hasAttributeNullResultExpression) {
|
||||
parserContext.getReaderContext()
|
||||
.error("One of 'value' or 'expression' or 'null-result-expression' is required", element);
|
||||
}
|
||||
|
||||
BeanDefinition expressionDef = null;
|
||||
BeanDefinition nullResultExpressionExpressionDef;
|
||||
|
||||
if (hasAttributeValue) {
|
||||
BeanDefinitionBuilder expressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(ValueExpression.class);
|
||||
BeanDefinitionBuilder expressionBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ValueExpression.class);
|
||||
if (StringUtils.hasText(type)) {
|
||||
expressionBuilder.addConstructorArgValue(new TypedStringValue(value, type));
|
||||
}
|
||||
@@ -93,19 +97,20 @@ public class EnricherParser extends AbstractConsumerEndpointParser {
|
||||
else if (hasAttributeExpression) {
|
||||
if (StringUtils.hasText(type)) {
|
||||
parserContext.getReaderContext().error("The 'type' attribute for '<property>' of '<enricher>' " +
|
||||
"is not allowed with an 'expression' attribute.", element);
|
||||
"is not allowed with an 'expression' attribute.", element);
|
||||
}
|
||||
expressionDef = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(ExpressionFactoryBean.class)
|
||||
.addConstructorArgValue(expression)
|
||||
.getBeanDefinition();
|
||||
}
|
||||
if (expressionDef != null){
|
||||
if (expressionDef != null) {
|
||||
expressions.put(name, expressionDef);
|
||||
}
|
||||
if (hasAttributeNullResultExpression) {
|
||||
nullResultExpressionExpressionDef = BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class)
|
||||
.addConstructorArgValue(nullResultExpression).getBeanDefinition();
|
||||
nullResultExpressionExpressionDef =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class)
|
||||
.addConstructorArgValue(nullResultExpression).getBeanDefinition();
|
||||
nullResultExpressions.put(name, nullResultExpressionExpressionDef);
|
||||
}
|
||||
}
|
||||
@@ -129,13 +134,14 @@ public class EnricherParser extends AbstractConsumerEndpointParser {
|
||||
boolean hasAttributeValue = StringUtils.hasText(valueElementValue);
|
||||
boolean hasAttributeExpression = StringUtils.hasText(expressionElementValue);
|
||||
boolean hasAttributeNullResultExpression = StringUtils.hasText(nullResultHeaderExpression);
|
||||
if (hasAttributeValue && hasAttributeExpression){
|
||||
if (hasAttributeValue && hasAttributeExpression) {
|
||||
parserContext.getReaderContext().error("Only one of '" + "value" + "' or '"
|
||||
+ "expression" + "' is allowed", subElement);
|
||||
+ "expression" + "' is allowed", subElement);
|
||||
}
|
||||
|
||||
if (!hasAttributeValue && !hasAttributeExpression && !hasAttributeNullResultExpression){
|
||||
parserContext.getReaderContext().error("One of 'value' or 'expression' or 'null-result-expression' is required", subElement);
|
||||
if (!hasAttributeValue && !hasAttributeExpression && !hasAttributeNullResultExpression) {
|
||||
parserContext.getReaderContext()
|
||||
.error("One of 'value' or 'expression' or 'null-result-expression' is required", subElement);
|
||||
}
|
||||
BeanDefinition expressionDef = null;
|
||||
if (hasAttributeValue) {
|
||||
@@ -143,7 +149,8 @@ public class EnricherParser extends AbstractConsumerEndpointParser {
|
||||
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(valueElementValue);
|
||||
}
|
||||
else if (hasAttributeExpression) {
|
||||
expressionDef = IntegrationNamespaceUtils.createExpressionDefIfAttributeDefined("expression", subElement);
|
||||
expressionDef =
|
||||
IntegrationNamespaceUtils.createExpressionDefIfAttributeDefined("expression", subElement);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(subElement.getAttribute("expression"))
|
||||
@@ -167,7 +174,8 @@ public class EnricherParser extends AbstractConsumerEndpointParser {
|
||||
.genericBeanDefinition(ExpressionEvaluatingHeaderValueMessageProcessor.class)
|
||||
.addConstructorArgValue(nullResultExpressionDefinition)
|
||||
.addConstructorArgValue(subElement.getAttribute("type"));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(nullResultValueProcessorBuilder, subElement, "overwrite");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(nullResultValueProcessorBuilder, subElement,
|
||||
"overwrite");
|
||||
nullResultHeaderExpressions.put(name, nullResultValueProcessorBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
@@ -184,8 +192,9 @@ public class EnricherParser extends AbstractConsumerEndpointParser {
|
||||
String requestPayloadExpression = element.getAttribute("request-payload-expression");
|
||||
|
||||
if (StringUtils.hasText(requestPayloadExpression)) {
|
||||
BeanDefinitionBuilder expressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class);
|
||||
expressionBuilder.addConstructorArgValue(requestPayloadExpression);
|
||||
BeanDefinitionBuilder expressionBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class)
|
||||
.addConstructorArgValue(requestPayloadExpression);
|
||||
builder.addPropertyValue("requestPayloadExpression", expressionBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @author Liujiong
|
||||
* @author Kris Jacyna
|
||||
* @since 2.1
|
||||
*/
|
||||
public class ContentEnricher extends AbstractReplyProducingMessageHandler
|
||||
@@ -82,6 +83,10 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler
|
||||
|
||||
private volatile String replyChannelName;
|
||||
|
||||
private volatile MessageChannel errorChannel;
|
||||
|
||||
private volatile String errorChannelName;
|
||||
|
||||
private volatile Gateway gateway = null;
|
||||
|
||||
private volatile Long requestTimeout;
|
||||
@@ -167,6 +172,22 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler
|
||||
this.replyChannelName = replyChannelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content enricher's error channel to allow the error handling flow to return
|
||||
* of an alternative object to use for enrichment if exceptions occur in the
|
||||
* downstream flow.
|
||||
* @param errorChannel The error channel.
|
||||
* @since 4.1
|
||||
*/
|
||||
public void setErrorChannel(MessageChannel errorChannel) {
|
||||
this.errorChannel = errorChannel;
|
||||
}
|
||||
|
||||
public void setErrorChannelName(String errorChannelName) {
|
||||
Assert.hasText(errorChannelName, "'errorChannelName' must not be empty");
|
||||
this.errorChannelName = errorChannelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timeout value for sending request messages. If not explicitly configured,
|
||||
* the default is one second.
|
||||
@@ -246,10 +267,17 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler
|
||||
Assert.state(!(this.replyChannelName != null && this.replyChannel != null),
|
||||
"'replyChannelName' and 'replyChannel' are mutually exclusive.");
|
||||
|
||||
Assert.state(!(this.errorChannelName != null && this.errorChannel != null),
|
||||
"'errorChannelName' and 'errorChannel' are mutually exclusive.");
|
||||
|
||||
if (this.replyChannel != null || this.replyChannelName != null) {
|
||||
Assert.state(this.requestChannel != null || this.requestChannelName != null,
|
||||
"If the replyChannel is set, then the requestChannel must not be null");
|
||||
}
|
||||
if (this.errorChannel != null || this.errorChannelName != null) {
|
||||
Assert.state(this.requestChannel != null || this.requestChannelName != null,
|
||||
"If the errorChannel is set, then the requestChannel must not be null");
|
||||
}
|
||||
if (this.requestChannel != null || this.requestChannelName != null) {
|
||||
this.gateway = new Gateway();
|
||||
this.gateway.setRequestChannel(this.requestChannel);
|
||||
@@ -269,6 +297,11 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler
|
||||
this.gateway.setReplyChannelName(this.replyChannelName);
|
||||
}
|
||||
|
||||
this.gateway.setErrorChannel(errorChannel);
|
||||
if (this.errorChannelName != null) {
|
||||
this.gateway.setErrorChannelName(this.errorChannelName);
|
||||
}
|
||||
|
||||
if (this.getBeanFactory() != null) {
|
||||
this.gateway.setBeanFactory(this.getBeanFactory());
|
||||
}
|
||||
|
||||
@@ -1387,6 +1387,21 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="error-channel" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Used when exceptions occur in a downstream flow and allows the error
|
||||
handling flow to return an alternative object to use for enrichment.
|
||||
If no "error-channel" reference is provided,
|
||||
this enricher will propagate Exceptions to the caller.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.messaging.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<channel id="inputChannel"/>
|
||||
|
||||
<channel id="requestChannel"/>
|
||||
|
||||
<channel id="errChannel"/>
|
||||
|
||||
<channel id="outputChannel">
|
||||
<queue />
|
||||
</channel>
|
||||
|
||||
<enricher id="enricher"
|
||||
input-channel="inputChannel" request-channel="requestChannel"
|
||||
output-channel="outputChannel" error-channel="errChannel">
|
||||
<property name="name" expression="'Mr. ' + payload.name"/>
|
||||
</enricher>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Tests the error-channel in an enricher to produce
|
||||
* a default object in case of downstream failure.
|
||||
*
|
||||
* @author Kris Jacyna
|
||||
* @since 4.1
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class EnricherParserTests5 {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
|
||||
@Test
|
||||
public void errorChannelTest() {
|
||||
|
||||
class ErrorThrower extends AbstractReplyProducingMessageHandler {
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultTargetProducer extends AbstractReplyProducingMessageHandler {
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
final Target defaultTarget = new Target();
|
||||
defaultTarget.setName("Default");
|
||||
return defaultTarget;
|
||||
}
|
||||
}
|
||||
|
||||
context.getBean("requestChannel", DirectChannel.class).subscribe(new ErrorThrower());
|
||||
context.getBean("errChannel", DirectChannel.class).subscribe(new DefaultTargetProducer());
|
||||
|
||||
Target original = new Target();
|
||||
original.setName("John");
|
||||
Message<?> request = MessageBuilder.withPayload(original).build();
|
||||
|
||||
context.getBean("inputChannel", DirectChannel.class).send(request);
|
||||
|
||||
Message<?> reply = context.getBean("outputChannel", PollableChannel.class).receive(10000);
|
||||
Target enriched = (Target) reply.getPayload();
|
||||
assertEquals("Mr. Default", enriched.getName());
|
||||
}
|
||||
|
||||
|
||||
public static class Target {
|
||||
|
||||
private volatile String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -57,6 +57,7 @@ import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
* @author Gunnar Hillert
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
* @author Kris Jacyna
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
@@ -85,9 +86,9 @@ public class ContentEnricherTests {
|
||||
public void replyChannelReplyTimingOut() throws Exception {
|
||||
|
||||
final long requestTimeout = 500L;
|
||||
final long replyTimeout = 700L;
|
||||
final long replyTimeout = 700L;
|
||||
|
||||
final DirectChannel replyChannel = new DirectChannel();
|
||||
final DirectChannel replyChannel = new DirectChannel();
|
||||
final QueueChannel requestChannel = new QueueChannel(1);
|
||||
|
||||
final ContentEnricher enricher = new ContentEnricher();
|
||||
@@ -144,10 +145,11 @@ public class ContentEnricherTests {
|
||||
Message<?> requestMessage = MessageBuilder.withPayload(target).setReplyChannel(replyChannel).build();
|
||||
|
||||
try {
|
||||
enricher.handleMessage(requestMessage);
|
||||
enricher.handleMessage(requestMessage);
|
||||
}
|
||||
catch (ReplyRequiredException e) {
|
||||
assertEquals("No reply produced by handler 'Enricher', and its 'requiresReply' property is set to true.", e.getMessage());
|
||||
assertEquals("No reply produced by handler 'Enricher', and its 'requiresReply' property is set to true.",
|
||||
e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -161,7 +163,7 @@ public class ContentEnricherTests {
|
||||
final String requestChannelName = "Request_Channel";
|
||||
final long requestTimeout = 200L;
|
||||
|
||||
QueueChannel replyChannel = new QueueChannel();
|
||||
QueueChannel replyChannel = new QueueChannel();
|
||||
QueueChannel requestChannel = new RendezvousChannel();
|
||||
requestChannel.setBeanName(requestChannelName);
|
||||
|
||||
@@ -179,8 +181,7 @@ public class ContentEnricherTests {
|
||||
}
|
||||
catch (MessageDeliveryException e) {
|
||||
assertEquals("failed to send message to channel '" + requestChannelName
|
||||
+ "' within timeout: " + requestTimeout, e.getMessage());
|
||||
return;
|
||||
+ "' within timeout: " + requestTimeout, e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -216,7 +217,7 @@ public class ContentEnricherTests {
|
||||
@Test
|
||||
public void setReplyChannelWithoutRequestChannel() {
|
||||
|
||||
QueueChannel replyChannel = new QueueChannel();
|
||||
QueueChannel replyChannel = new QueueChannel();
|
||||
|
||||
ContentEnricher enricher = new ContentEnricher();
|
||||
enricher.setReplyChannel(replyChannel);
|
||||
@@ -287,8 +288,8 @@ public class ContentEnricherTests {
|
||||
@Test
|
||||
public void testContentEnricherWithNullRequestChannel() {
|
||||
|
||||
ContentEnricher enricher = new ContentEnricher();
|
||||
enricher.setReplyChannel(new QueueChannel());
|
||||
ContentEnricher enricher = new ContentEnricher();
|
||||
enricher.setReplyChannel(new QueueChannel());
|
||||
enricher.setBeanFactory(mock(BeanFactory.class));
|
||||
|
||||
try {
|
||||
@@ -383,7 +384,7 @@ public class ContentEnricherTests {
|
||||
enricher.afterPropertiesSet();
|
||||
|
||||
TargetUser target = new TargetUser();
|
||||
target.setName("replace me");
|
||||
target.setName("replace me");
|
||||
|
||||
Message<?> requestMessage = MessageBuilder.withPayload(target).setReplyChannel(replyChannel).build();
|
||||
enricher.handleMessage(requestMessage);
|
||||
@@ -416,12 +417,12 @@ public class ContentEnricherTests {
|
||||
enricher.afterPropertiesSet();
|
||||
|
||||
UncloneableTargetUser target = new UncloneableTargetUser();
|
||||
target.setName("replace me");
|
||||
target.setName("replace me");
|
||||
|
||||
Message<?> requestMessage = MessageBuilder.withPayload(target).setReplyChannel(replyChannel).build();
|
||||
|
||||
try {
|
||||
enricher.handleMessage(requestMessage);
|
||||
enricher.handleMessage(requestMessage);
|
||||
}
|
||||
catch (MessageHandlingException e) {
|
||||
assertThat(e.getMessage(), containsString("Failed to clone payload object"));
|
||||
@@ -469,6 +470,56 @@ public class ContentEnricherTests {
|
||||
assertTrue(enricher.isRunning());
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test a {@link Target} message is passed into a {@link ContentEnricher}.
|
||||
* The Enricher passes the message to a "request-channel" to a handler which throws
|
||||
* an exception. The {@link ContentEnricher} then uses the error flow and consults
|
||||
* the "error-channel" which returns a alternative {@link Target}.
|
||||
*/
|
||||
@Test
|
||||
public void testErrorChannel() throws Exception {
|
||||
|
||||
final DirectChannel requestChannel = new DirectChannel();
|
||||
requestChannel.subscribe(new AbstractReplyProducingMessageHandler() {
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
final DirectChannel errorChannel = new DirectChannel();
|
||||
errorChannel.subscribe(new AbstractReplyProducingMessageHandler() {
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
return new Target("failed");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
final QueueChannel replyChannel = new QueueChannel();
|
||||
|
||||
final ContentEnricher enricher = new ContentEnricher();
|
||||
enricher.setRequestChannel(requestChannel);
|
||||
enricher.setErrorChannel(errorChannel);
|
||||
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
Map<String, Expression> propertyExpressions = new HashMap<String, Expression>();
|
||||
propertyExpressions.put("name", parser.parseExpression("payload.name + ' target'"));
|
||||
|
||||
enricher.setPropertyExpressions(propertyExpressions);
|
||||
enricher.setBeanFactory(mock(BeanFactory.class));
|
||||
enricher.afterPropertiesSet();
|
||||
|
||||
final Target target = new Target("replace me");
|
||||
Message<?> requestMessage = MessageBuilder.withPayload(target).setReplyChannel(replyChannel).build();
|
||||
|
||||
enricher.handleMessage(requestMessage);
|
||||
Message<?> reply = replyChannel.receive(10000);
|
||||
Target result = (Target) reply.getPayload();
|
||||
assertEquals("failed target", result.getName());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final class Source {
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
with id <code>integrationHeaderChannelRegistry</code> and configure the required default delay using
|
||||
a constructor argument (milliseconds).
|
||||
</para>
|
||||
|
||||
|
||||
<para>
|
||||
Since <emphasis>version 4.1</emphasis>, you can set a property <code>removeOnGet</code>
|
||||
to <code>true</code> on the <code><bean/></code> definition, and the mapping entry will be removed
|
||||
@@ -212,7 +212,7 @@
|
||||
</int:header-enricher>
|
||||
|
||||
<int:header-enricher input-channel="inputCustomTtl" output-channel="next">
|
||||
<int:header-channels-to-string
|
||||
<int:header-channels-to-string
|
||||
time-to-live-expression="headers['channelTTL'] ?: 120000" />
|
||||
</int:header-enricher>]]></programlisting>
|
||||
|
||||
@@ -295,12 +295,13 @@
|
||||
output-channel="" ]]><co id="payload-enricher05-co" linkends="payload-enricher05" /><![CDATA[
|
||||
request-payload-expression="" ]]><co id="payload-enricher06-co" linkends="payload-enricher06" /><![CDATA[
|
||||
reply-channel="" ]]><co id="payload-enricher07-co" linkends="payload-enricher07" /><![CDATA[
|
||||
send-timeout="" ]]><co id="payload-enricher08-co" linkends="payload-enricher08" /><![CDATA[
|
||||
should-clone-payload="false"> ]]><co id="payload-enricher09-co" linkends="payload-enricher09" /><![CDATA[
|
||||
<int:poller></int:poller> ]]><co id="payload-enricher10-co" linkends="payload-enricher10" /><![CDATA[
|
||||
<int:property name="" expression="" null-result-expression="'Could not determine the name'"/> ]]><co id="payload-enricher11-co" linkends="payload-enricher11" /><![CDATA[
|
||||
error-channel="" ]]><co id="payload-enricher08-co" linkends="payload-enricher08" /><![CDATA[
|
||||
send-timeout="" ]]><co id="payload-enricher09-co" linkends="payload-enricher09" /><![CDATA[
|
||||
should-clone-payload="false"> ]]><co id="payload-enricher10-co" linkends="payload-enricher10" /><![CDATA[
|
||||
<int:poller></int:poller> ]]><co id="payload-enricher11-co" linkends="payload-enricher11" /><![CDATA[
|
||||
<int:property name="" expression="" null-result-expression="'Could not determine the name'"/> ]]><co id="payload-enricher12-co" linkends="payload-enricher12" /><![CDATA[
|
||||
<int:property name="" value="23" type="java.lang.Integer" null-result-expression="'0'"/>
|
||||
<int:header name="" expression="" null-result-expression=""/> ]]><co id="payload-enricher12-co" linkends="payload-enricher12" /><![CDATA[
|
||||
<int:header name="" expression="" null-result-expression=""/> ]]><co id="payload-enricher13-co" linkends="payload-enricher13" /><![CDATA[
|
||||
<int:header name="" value="" overwrite="" type="" null-result-expression=""/>
|
||||
</int:enricher>]]></programlisting>
|
||||
|
||||
@@ -381,7 +382,17 @@
|
||||
<emphasis>Optional</emphasis>.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="payload-enricher08-co" id="payload-enricher08">
|
||||
<callout arearefs="payload-enricher08-co" id="payload-enricher08">
|
||||
<para>
|
||||
Channel to which an <classname>ErrorMessage</classname> will be sent if an
|
||||
<classname>Exception</classname> occurs downstream of the
|
||||
<code>request-channel</code>. This enables you to return an alternative object to use
|
||||
for enrichment. This is optional; if it is not set then <classname>Exception</classname>
|
||||
is thrown to the caller.
|
||||
<emphasis>Optional</emphasis>.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="payload-enricher09-co" id="payload-enricher09">
|
||||
<para>
|
||||
Maximum amount of time in milliseconds to wait when
|
||||
sending a message to the channel, if such channel may block.
|
||||
@@ -400,7 +411,7 @@
|
||||
<emphasis>Optional</emphasis>.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="payload-enricher09-co" id="payload-enricher09">
|
||||
<callout arearefs="payload-enricher10-co" id="payload-enricher10">
|
||||
<para>
|
||||
Boolean value indicating whether any payload that implements
|
||||
<interfacename>Cloneable</interfacename> should be cloned
|
||||
@@ -411,14 +422,14 @@
|
||||
<emphasis>Optional</emphasis>.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="payload-enricher10-co" id="payload-enricher10">
|
||||
<callout arearefs="payload-enricher11-co" id="payload-enricher11">
|
||||
<para>
|
||||
Allows you to configure a Message Poller if this endpoint
|
||||
is a Polling Consumer.
|
||||
<emphasis>Optional</emphasis>.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="payload-enricher11-co" id="payload-enricher11">
|
||||
<callout arearefs="payload-enricher12-co" id="payload-enricher12">
|
||||
<para>
|
||||
Each <code>property</code> sub-element provides the
|
||||
name of a property (via the mandatory <code>name</code>
|
||||
@@ -452,7 +463,7 @@
|
||||
returns null, it will be evaluated and the output of the evaluation will be returned instead.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="payload-enricher12-co" id="payload-enricher12">
|
||||
<callout arearefs="payload-enricher13-co" id="payload-enricher13">
|
||||
<para>
|
||||
Each <code>header</code> sub-element provides the
|
||||
name of a Message header (via the mandatory <code>name</code>
|
||||
|
||||
@@ -131,10 +131,17 @@
|
||||
<section id="4.1-content-enricher-improvement">
|
||||
<title>Content Enricher Improvements</title>
|
||||
<para>
|
||||
Add null-result-expression attribute, which will be evaluated and returned if <code><enricher></code> returns null.
|
||||
An <code>null-result-expression</code> attribute has been added, which is evaluated and returned if
|
||||
<code><enricher></code> returns <code>null</code>.
|
||||
It can be added in <code><header></code> and <code><property></code>.
|
||||
See <xref linkend="content-enricher"/> for more information.
|
||||
</para>
|
||||
<para>
|
||||
An <code>error-channel</code> attribute has been added, which is used to handle an error flow
|
||||
if <classname>Exception</classname> occurs downstream of the <code>request-channel</code>. This enable
|
||||
you to return an alternative object to use for enrichment.
|
||||
See <xref linkend="content-enricher"/> for more information.
|
||||
</para>
|
||||
</section>
|
||||
<section id="4.1-header-channel-registry">
|
||||
<title>Header Channel Registry</title>
|
||||
|
||||
Reference in New Issue
Block a user