INT-3312: Add Support for outputChannelName
JIRA: https://jira.springsource.org/browse/INT-3312 * Add `setOutputChannelName` to `AbstractReplyProducingMessageHandler` and `SourcePollingChannelAdapterFactoryBean` to allow to have 'late binding' and resolve the real channel from `AC` on component initialization, instead of creation phase * Add `setRequestChannelName` and `setReplyChannelName` to `ContentEnricher` for the same purpose * Make `HeaderValueMessageProcessor` implementation `public`. It is useful for JavaConfig and DSL * Polishing parsers to use classes, not their names as strings INT-3312: PR comments INT-3312: Polishing
This commit is contained in:
committed by
Gary Russell
parent
5c68029a72
commit
f0a1f81931
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
@@ -24,11 +25,13 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.scheduling.PollerMetadata;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.core.DestinationResolutionException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* FactoryBean for creating a SourcePollingChannelAdapter instance.
|
||||
@@ -44,6 +47,8 @@ public class SourcePollingChannelAdapterFactoryBean implements FactoryBean<Sourc
|
||||
|
||||
private volatile MessageChannel outputChannel;
|
||||
|
||||
private volatile String outputChannelName;
|
||||
|
||||
private volatile PollerMetadata pollerMetadata;
|
||||
|
||||
private volatile boolean autoStartup = true;
|
||||
@@ -76,6 +81,10 @@ public class SourcePollingChannelAdapterFactoryBean implements FactoryBean<Sourc
|
||||
this.outputChannel = outputChannel;
|
||||
}
|
||||
|
||||
public void setOutputChannelName(String outputChannelName) {
|
||||
this.outputChannelName = outputChannelName;
|
||||
}
|
||||
|
||||
public void setPollerMetadata(PollerMetadata pollerMetadata) {
|
||||
this.pollerMetadata = pollerMetadata;
|
||||
}
|
||||
@@ -127,6 +136,18 @@ public class SourcePollingChannelAdapterFactoryBean implements FactoryBean<Sourc
|
||||
return;
|
||||
}
|
||||
Assert.notNull(this.source, "source is required");
|
||||
|
||||
if (StringUtils.hasText(this.outputChannelName)) {
|
||||
Assert.isNull(this.outputChannel, "'outputChannelName' and 'outputChannel' are mutually exclusive.");
|
||||
try {
|
||||
this.outputChannel = this.beanFactory.getBean(this.outputChannelName, MessageChannel.class);
|
||||
}
|
||||
catch (BeansException e) {
|
||||
throw new DestinationResolutionException("Failed to look up MessageChannel with name '"
|
||||
+ this.outputChannelName + "' in the BeanFactory.");
|
||||
}
|
||||
}
|
||||
|
||||
Assert.notNull(this.outputChannel, "outputChannel is required");
|
||||
SourcePollingChannelAdapter spca = new SourcePollingChannelAdapter();
|
||||
spca.setSource(this.source);
|
||||
|
||||
@@ -25,8 +25,8 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.ExpressionFactoryBean;
|
||||
import org.springframework.integration.config.IntegrationConfigUtils;
|
||||
import org.springframework.integration.transformer.ContentEnricher;
|
||||
import org.springframework.integration.transformer.support.ExpressionEvaluatingHeaderValueMessageProcessor;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -69,8 +69,7 @@ public class EnricherParser extends AbstractConsumerEndpointParser {
|
||||
String name = subElement.getAttribute("name");
|
||||
BeanDefinition expressionDefinition = IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression("value",
|
||||
"expression", parserContext, subElement, true);
|
||||
BeanDefinitionBuilder valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".transformer.support.ExpressionEvaluatingHeaderValueMessageProcessor");
|
||||
BeanDefinitionBuilder valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionEvaluatingHeaderValueMessageProcessor.class);
|
||||
valueProcessorBuilder.addConstructorArgValue(expressionDefinition)
|
||||
.addConstructorArgValue(subElement.getAttribute("type"));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(valueProcessorBuilder, subElement, "overwrite");
|
||||
|
||||
@@ -29,10 +29,12 @@ import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.IntegrationConfigUtils;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.expression.DynamicExpression;
|
||||
import org.springframework.integration.transformer.HeaderEnricher;
|
||||
import org.springframework.integration.transformer.support.ExpressionEvaluatingHeaderValueMessageProcessor;
|
||||
import org.springframework.integration.transformer.support.MessageProcessingHeaderValueMessageProcessor;
|
||||
import org.springframework.integration.transformer.support.StaticHeaderValueMessageProcessor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -216,8 +218,7 @@ public abstract class HeaderEnricherParserSupport extends AbstractTransformerPar
|
||||
}
|
||||
Object headerValue = (headerType != null) ?
|
||||
new TypedStringValue(value, headerType) : value;
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".transformer.support.StaticHeaderValueMessageProcessor");
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(StaticHeaderValueMessageProcessor.class);
|
||||
valueProcessorBuilder.addConstructorArgValue(headerValue);
|
||||
}
|
||||
else if (isExpression) {
|
||||
@@ -225,8 +226,7 @@ public abstract class HeaderEnricherParserSupport extends AbstractTransformerPar
|
||||
parserContext.getReaderContext().error(
|
||||
"The 'method' attribute cannot be used with the 'expression' attribute.", element);
|
||||
}
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".transformer.support.ExpressionEvaluatingHeaderValueMessageProcessor");
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionEvaluatingHeaderValueMessageProcessor.class);
|
||||
if (expressionElement != null) {
|
||||
BeanDefinitionBuilder dynamicExpressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DynamicExpression.class);
|
||||
dynamicExpressionBuilder.addConstructorArgValue(expressionElement.getAttribute("key"));
|
||||
@@ -244,16 +244,14 @@ public abstract class HeaderEnricherParserSupport extends AbstractTransformerPar
|
||||
"The 'type' attribute cannot be used with an inner bean.", element);
|
||||
}
|
||||
if (hasMethod || isScript) {
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".transformer.support.MessageProcessingHeaderValueMessageProcessor");
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(MessageProcessingHeaderValueMessageProcessor.class);
|
||||
valueProcessorBuilder.addConstructorArgValue(innerComponentDefinition);
|
||||
if (hasMethod) {
|
||||
valueProcessorBuilder.addConstructorArgValue(method);
|
||||
}
|
||||
}
|
||||
else {
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".transformer.support.StaticHeaderValueMessageProcessor");
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(StaticHeaderValueMessageProcessor.class);
|
||||
valueProcessorBuilder.addConstructorArgValue(innerComponentDefinition);
|
||||
}
|
||||
}
|
||||
@@ -263,14 +261,12 @@ public abstract class HeaderEnricherParserSupport extends AbstractTransformerPar
|
||||
"The 'type' attribute cannot be used with the 'ref' attribute.", element);
|
||||
}
|
||||
if (hasMethod) {
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".transformer.support.MessageProcessingHeaderValueMessageProcessor");
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(MessageProcessingHeaderValueMessageProcessor.class);
|
||||
valueProcessorBuilder.addConstructorArgReference(ref);
|
||||
valueProcessorBuilder.addConstructorArgValue(method);
|
||||
}
|
||||
else {
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".transformer.support.StaticHeaderValueMessageProcessor");
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(StaticHeaderValueMessageProcessor.class);
|
||||
valueProcessorBuilder.addConstructorArgReference(ref);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.integration.core.MessageProducer;
|
||||
import org.springframework.integration.core.MessagingTemplate;
|
||||
@@ -34,6 +35,7 @@ import org.springframework.messaging.core.DestinationResolver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for MessageHandlers that are capable of producing replies.
|
||||
@@ -48,6 +50,8 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
|
||||
|
||||
private MessageChannel outputChannel;
|
||||
|
||||
private String outputChannelName;
|
||||
|
||||
private volatile boolean requiresReply = false;
|
||||
|
||||
private final MessagingTemplate messagingTemplate;
|
||||
@@ -70,6 +74,10 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
|
||||
this.outputChannel = outputChannel;
|
||||
}
|
||||
|
||||
public void setOutputChannelName(String outputChannelName) {
|
||||
this.outputChannelName = outputChannelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timeout for sending reply Messages.
|
||||
*
|
||||
@@ -128,6 +136,16 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
|
||||
protected final void onInit() {
|
||||
if (this.getBeanFactory() != null) {
|
||||
this.messagingTemplate.setBeanFactory(getBeanFactory());
|
||||
if (StringUtils.hasText(this.outputChannelName)) {
|
||||
Assert.isNull(this.outputChannel, "'outputChannelName' and 'outputChannel' are mutually exclusive.");
|
||||
try {
|
||||
this.outputChannel = this.getBeanFactory().getBean(this.outputChannelName, MessageChannel.class);
|
||||
}
|
||||
catch (BeansException e) {
|
||||
throw new DestinationResolutionException("Failed to look up MessageChannel with name '"
|
||||
+ this.outputChannelName + "' in the BeanFactory.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(this.adviceChain)) {
|
||||
ProxyFactory proxyFactory = new ProxyFactory(new AdvisedRequestHandler());
|
||||
@@ -215,7 +233,7 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
|
||||
* @param replyMessage the reply Message to send
|
||||
* @param replyChannelHeaderValue the 'replyChannel' header value from the original request
|
||||
*/
|
||||
private final void sendReplyMessage(Message<?> replyMessage, final Object replyChannelHeaderValue) {
|
||||
private void sendReplyMessage(Message<?> replyMessage, final Object replyChannelHeaderValue) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("handler '" + this + "' sending reply Message: " + replyMessage);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandlingException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Content Enricher is a Message Transformer that can augment a message's payload
|
||||
@@ -68,8 +69,12 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler implem
|
||||
|
||||
private volatile MessageChannel requestChannel;
|
||||
|
||||
private volatile String requestChannelName;
|
||||
|
||||
private volatile MessageChannel replyChannel;
|
||||
|
||||
private volatile String replyChannelName;
|
||||
|
||||
private volatile Gateway gateway = null;
|
||||
|
||||
private volatile Long requestTimeout;
|
||||
@@ -123,6 +128,10 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler implem
|
||||
this.requestChannel = requestChannel;
|
||||
}
|
||||
|
||||
public void setRequestChannelName(String requestChannelName) {
|
||||
this.requestChannelName = requestChannelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content enricher's reply channel. If not specified, yet the request
|
||||
* channel is set, an anonymous reply channel will automatically created
|
||||
@@ -134,6 +143,10 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler implem
|
||||
this.replyChannel = replyChannel;
|
||||
}
|
||||
|
||||
public void setReplyChannelName(String replyChannelName) {
|
||||
this.replyChannelName = replyChannelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timeout value for sending request messages. If not explicitly
|
||||
* configured, the default is one second.
|
||||
@@ -207,6 +220,16 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler implem
|
||||
*/
|
||||
@Override
|
||||
protected void doInit() {
|
||||
if (StringUtils.hasText(this.requestChannelName)) {
|
||||
Assert.isNull(this.requestChannel, "'requestChannelName' and 'requestChannel' are mutually exclusive.");
|
||||
this.requestChannel = this.getBeanFactory().getBean(this.requestChannelName, MessageChannel.class);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(this.replyChannelName)) {
|
||||
Assert.isNull(this.replyChannel, "'replyChannelName' and 'replyChannel' are mutually exclusive.");
|
||||
this.replyChannel = this.getBeanFactory().getBean(this.replyChannelName, MessageChannel.class);
|
||||
}
|
||||
|
||||
if (this.replyChannel != null) {
|
||||
Assert.notNull(this.requestChannel, "If the replyChannel is set, then the requestChannel must not be null");
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ package org.springframework.integration.transformer.support;
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
abstract class AbstractHeaderValueMessageProcessor<T> implements HeaderValueMessageProcessor<T> {
|
||||
public abstract class AbstractHeaderValueMessageProcessor<T> implements HeaderValueMessageProcessor<T> {
|
||||
|
||||
// null indicates no explicit setting
|
||||
private volatile Boolean overwrite = null;
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.messaging.Message;
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
class ExpressionEvaluatingHeaderValueMessageProcessor<T> extends AbstractHeaderValueMessageProcessor<T>
|
||||
public class ExpressionEvaluatingHeaderValueMessageProcessor<T> extends AbstractHeaderValueMessageProcessor<T>
|
||||
implements BeanFactoryAware {
|
||||
|
||||
private static final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.springframework.messaging.Message;
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
class MessageProcessingHeaderValueMessageProcessor extends AbstractHeaderValueMessageProcessor<Object> {
|
||||
public class MessageProcessingHeaderValueMessageProcessor extends AbstractHeaderValueMessageProcessor<Object> {
|
||||
|
||||
private final MessageProcessor<?> targetProcessor;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.springframework.messaging.Message;
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
class StaticHeaderValueMessageProcessor<T> extends AbstractHeaderValueMessageProcessor<T> {
|
||||
public class StaticHeaderValueMessageProcessor<T> extends AbstractHeaderValueMessageProcessor<T> {
|
||||
|
||||
private final T value;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user