Merge pull request #753 from srt/INT-2755
* INT-2755: INT-2755: Support 'id' For <chain> Child Elements
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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
|
||||
@@ -23,6 +23,8 @@ import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.context.IntegrationObjectSupport;
|
||||
import org.springframework.integration.context.NamedComponent;
|
||||
import org.springframework.integration.context.Orderable;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.core.MessageProducer;
|
||||
@@ -34,8 +36,10 @@ import org.springframework.util.CollectionUtils;
|
||||
* @author Dave Syer
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public abstract class AbstractSimpleMessageHandlerFactoryBean<H extends MessageHandler> implements FactoryBean<MessageHandler>, BeanFactoryAware {
|
||||
public abstract class AbstractSimpleMessageHandlerFactoryBean<H extends MessageHandler>
|
||||
implements FactoryBean<MessageHandler>, BeanFactoryAware {
|
||||
|
||||
private volatile H handler;
|
||||
|
||||
@@ -51,6 +55,7 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean<H extends MessageH
|
||||
|
||||
private volatile List<Advice> adviceChain;
|
||||
|
||||
private volatile String componentName;
|
||||
|
||||
public AbstractSimpleMessageHandlerFactoryBean() {
|
||||
super();
|
||||
@@ -76,16 +81,19 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean<H extends MessageH
|
||||
this.adviceChain = adviceChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the handler component.
|
||||
*
|
||||
* @param componentName
|
||||
*/
|
||||
public void setComponentName(String componentName) {
|
||||
this.componentName = componentName;
|
||||
}
|
||||
|
||||
public H getObject() throws Exception {
|
||||
if (this.handler == null) {
|
||||
this.handler = this.createHandlerInternal();
|
||||
Assert.notNull(this.handler, "failed to create MessageHandler");
|
||||
if (this.handler instanceof MessageProducer && this.outputChannel != null) {
|
||||
((MessageProducer) this.handler).setOutputChannel(this.outputChannel);
|
||||
}
|
||||
if (this.handler instanceof Orderable && this.order != null) {
|
||||
((Orderable) this.handler).setOrder(this.order.intValue());
|
||||
}
|
||||
}
|
||||
return this.handler;
|
||||
}
|
||||
@@ -100,10 +108,19 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean<H extends MessageH
|
||||
if (handler instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) handler).setBeanFactory(getBeanFactory());
|
||||
}
|
||||
if (this.handler instanceof MessageProducer && this.outputChannel != null) {
|
||||
((MessageProducer) this.handler).setOutputChannel(this.outputChannel);
|
||||
}
|
||||
if (this.handler instanceof IntegrationObjectSupport && this.componentName != null) {
|
||||
((IntegrationObjectSupport) this.handler).setComponentName(this.componentName);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(this.adviceChain) &&
|
||||
this.handler instanceof AbstractReplyProducingMessageHandler) {
|
||||
((AbstractReplyProducingMessageHandler) this.handler).setAdviceChain(this.adviceChain);
|
||||
}
|
||||
if (this.handler instanceof Orderable && this.order != null) {
|
||||
((Orderable) this.handler).setOrder(this.order);
|
||||
}
|
||||
this.initialized = true;
|
||||
}
|
||||
if (handler instanceof InitializingBean) {
|
||||
@@ -130,4 +147,4 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean<H extends MessageH
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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
|
||||
@@ -13,15 +13,22 @@
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
@@ -41,23 +48,52 @@ import org.springframework.util.xml.DomUtils;
|
||||
*/
|
||||
public class ChainParser extends AbstractConsumerEndpointParser {
|
||||
|
||||
/**
|
||||
* {@link BeanDefinition} attribute used to pass down the current bean id for nested chains, allowing full
|
||||
* qualification of 'named' handlers within nested chains.
|
||||
*
|
||||
*/
|
||||
private static final String SI_CHAIN_NESTED_ID_ATTRIBUTE = "SI.ChainParser.NestedId.Prefix";
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
@Override
|
||||
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MessageHandlerChain.class);
|
||||
ManagedList<BeanMetadataElement> handlerList = new ManagedList<BeanMetadataElement>();
|
||||
|
||||
if (!StringUtils.hasText(element.getAttribute(ID_ATTRIBUTE))) {
|
||||
logger.info("It is useful to provide an explicit 'id' attribute on 'chain' elements " +
|
||||
"to simplify the identification of child elements in logs etc.");
|
||||
}
|
||||
|
||||
String chainHandlerId = this.resolveId(element, builder.getRawBeanDefinition(), parserContext);
|
||||
List<BeanMetadataElement> handlerList = new ManagedList<BeanMetadataElement>();
|
||||
Set<String> handlerBeanNameSet = new HashSet<String>();
|
||||
NodeList children = element.getChildNodes();
|
||||
|
||||
int childOrder = 0;
|
||||
for (int i = 0; i < children.getLength(); i++) {
|
||||
Node child = children.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE && !"poller".equals(child.getLocalName())) {
|
||||
BeanDefinitionHolder holder = this.parseChild((Element) child, parserContext, builder.getBeanDefinition());
|
||||
if ("gateway".equals(child.getLocalName())){
|
||||
BeanMetadataElement childBeanMetadata = this.parseChild(chainHandlerId, (Element) child, childOrder++,
|
||||
parserContext, builder.getBeanDefinition());
|
||||
if (childBeanMetadata instanceof RuntimeBeanReference) {
|
||||
String handlerBeanName = ((RuntimeBeanReference) childBeanMetadata).getBeanName();
|
||||
if (!handlerBeanNameSet.add(handlerBeanName)) {
|
||||
parserContext.getReaderContext().error("A bean definition is already registered for " +
|
||||
"beanName: '" + handlerBeanName + "' within the current <chain>.",
|
||||
element);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if ("gateway".equals(child.getLocalName())) {
|
||||
BeanDefinitionBuilder gwBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationNamespaceUtils.BASE_PACKAGE + ".gateway.RequestReplyMessageHandlerAdapter");
|
||||
gwBuilder.addConstructorArgValue(holder);
|
||||
gwBuilder.addConstructorArgValue(childBeanMetadata);
|
||||
handlerList.add(gwBuilder.getBeanDefinition());
|
||||
}
|
||||
else {
|
||||
handlerList.add(holder);
|
||||
handlerList.add(childBeanMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,31 +104,30 @@ public class ChainParser extends AbstractConsumerEndpointParser {
|
||||
return builder;
|
||||
}
|
||||
|
||||
private void validateChild(Element element, ParserContext parserContext) {
|
||||
|
||||
final Object source = parserContext.extractSource(element);
|
||||
|
||||
final String order = element.getAttribute(IntegrationNamespaceUtils.ORDER);
|
||||
|
||||
if (StringUtils.hasText(order)) {
|
||||
parserContext.getReaderContext().error(IntegrationNamespaceUtils.createElementDescription(element) + " must not define " +
|
||||
"an 'order' attribute when used within a chain.", source);
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException {
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
BeanDefinition containingBeanDefinition = parserContext.getContainingBeanDefinition();
|
||||
if (containingBeanDefinition != null) {
|
||||
String nestedChainIdPrefix = (String) containingBeanDefinition.getAttribute(SI_CHAIN_NESTED_ID_ATTRIBUTE);
|
||||
if (StringUtils.hasText(nestedChainIdPrefix)) {
|
||||
id = nestedChainIdPrefix + "$child." + id;
|
||||
}
|
||||
}
|
||||
|
||||
final List<Element> pollerChildElements = DomUtils
|
||||
.getChildElementsByTagName(element, "poller");
|
||||
|
||||
if (!pollerChildElements.isEmpty()) {
|
||||
parserContext.getReaderContext().error(IntegrationNamespaceUtils.createElementDescription(element) + " must not define " +
|
||||
"a 'poller' sub-element when used within a chain.", source);
|
||||
}
|
||||
|
||||
definition.setAttribute(SI_CHAIN_NESTED_ID_ATTRIBUTE, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
private BeanDefinitionHolder parseChild(Element element, ParserContext parserContext, BeanDefinition parentDefinition) {
|
||||
private BeanMetadataElement parseChild(String chainHandlerId, Element element, int order, ParserContext parserContext,
|
||||
BeanDefinition parentDefinition) {
|
||||
|
||||
BeanDefinitionHolder holder = null;
|
||||
|
||||
String id = element.getAttribute(ID_ATTRIBUTE);
|
||||
boolean hasId = StringUtils.hasText(id);
|
||||
String handlerComponentName = chainHandlerId + "$child" + (hasId ? "." + id : "#" + order);
|
||||
|
||||
|
||||
if ("bean".equals(element.getLocalName())) {
|
||||
holder = parserContext.getDelegate().parseBeanDefinitionElement(element, parentDefinition);
|
||||
}
|
||||
@@ -103,13 +138,40 @@ public class ChainParser extends AbstractConsumerEndpointParser {
|
||||
BeanDefinition beanDefinition = parserContext.getDelegate().parseCustomElement(element, parentDefinition);
|
||||
if (beanDefinition == null) {
|
||||
parserContext.getReaderContext().error("child BeanDefinition must not be null", element);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
String beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, parserContext.getRegistry(), true);
|
||||
holder = new BeanDefinitionHolder(beanDefinition, beanName);
|
||||
holder = new BeanDefinitionHolder(beanDefinition, handlerComponentName + IntegrationNamespaceUtils.HANDLER_ALIAS_SUFFIX);
|
||||
}
|
||||
}
|
||||
|
||||
holder.getBeanDefinition().getPropertyValues().add("componentName", handlerComponentName);
|
||||
|
||||
if (hasId) {
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry());
|
||||
return new RuntimeBeanReference(holder.getBeanName());
|
||||
}
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
private void validateChild(Element element, ParserContext parserContext) {
|
||||
|
||||
final Object source = parserContext.extractSource(element);
|
||||
|
||||
final String order = element.getAttribute(IntegrationNamespaceUtils.ORDER);
|
||||
|
||||
if (StringUtils.hasText(order)) {
|
||||
parserContext.getReaderContext().error(IntegrationNamespaceUtils.createElementDescription(element) + " must not define " +
|
||||
"an 'order' attribute when used within a chain.", source);
|
||||
}
|
||||
|
||||
final List<Element> pollerChildElements = DomUtils.getChildElementsByTagName(element, "poller");
|
||||
|
||||
if (!pollerChildElements.isEmpty()) {
|
||||
parserContext.getReaderContext().error(IntegrationNamespaceUtils.createElementDescription(element) + " must not define " +
|
||||
"a 'poller' sub-element when used within a chain.", source);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -175,34 +175,6 @@ public class MessageHandlerChain extends AbstractMessageHandler implements Messa
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComponentName(String componentName) {
|
||||
super.setComponentName(componentName);
|
||||
int i = 0;
|
||||
if (this.handlers != null) {
|
||||
for (MessageHandler messageHandler : this.handlers) {
|
||||
try {
|
||||
MessageHandler targetHandler = messageHandler;
|
||||
if (AopUtils.isAopProxy(targetHandler)) {
|
||||
Object target = ((Advised) targetHandler).getTargetSource().getTarget();
|
||||
if (target instanceof MessageHandler) {
|
||||
targetHandler = (MessageHandler) target;
|
||||
}
|
||||
}
|
||||
if (targetHandler instanceof IntegrationObjectSupport) {
|
||||
((IntegrationObjectSupport) targetHandler).setComponentName(componentName + ".handler#" + i);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not set component name for handler "
|
||||
+ messageHandler + " for " + componentName + " :" + e.getMessage());
|
||||
}
|
||||
}
|
||||
i++; // increment, regardless of whether we assigned a component name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SmartLifecycle implementation (delegates to the {@link #handlers})
|
||||
*/
|
||||
|
||||
@@ -727,6 +727,7 @@
|
||||
Defines a Messaging Gateway to be used within a chain.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="id" type="xsd:string" use="optional" />
|
||||
<xsd:attribute name="request-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -1048,6 +1049,7 @@
|
||||
<xsd:all>
|
||||
<xsd:element ref="beans:bean" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:all>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="service-activator">
|
||||
@@ -1067,7 +1069,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="expressionOrInnerEndpointDefinitionAware">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
<xsd:attribute name="requires-reply" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -1090,6 +1092,15 @@
|
||||
Base type for Message-handling endpoints.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="id" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
'id' value:
|
||||
- Identifies the underlying Spring bean definition (AbstractEndpoint)
|
||||
- as MessageHandler bean alias together with suffix '.handler'
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="ref" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
@@ -1166,7 +1177,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="enricher-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -1301,6 +1312,7 @@
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="propertySubElementType">
|
||||
@@ -1370,17 +1382,6 @@
|
||||
<xsd:element name="transactional" type="transactionalType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="advice-chain" type="adviceChainType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="id" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
'id' value is used:
|
||||
- as the 'AbstractEndpoint' bean 'id' if this tag is defined as root element.
|
||||
- as the DelayHandler bean alias together with suffix '.handler'
|
||||
- as the 'messageGroupId' property of DelayHandler together with suffix '.messageGroupId'
|
||||
in the operations of the MessageGroupStore for scheduling delayed messages.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="default-delay" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -1437,6 +1438,7 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="bridge">
|
||||
@@ -1452,7 +1454,8 @@
|
||||
<xsd:any processContents="strict" namespace="##other" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element ref="poller" />
|
||||
</xsd:choice>
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -1468,7 +1471,7 @@
|
||||
<xsd:element name="poller" type="basePollerType" minOccurs="0"/>
|
||||
<xsd:group ref="chain-elements-group" maxOccurs="unbounded"/>
|
||||
</xsd:choice>
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
<xsd:attribute name="phase" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
@@ -1479,6 +1482,7 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -1519,6 +1523,7 @@
|
||||
<xsd:sequence>
|
||||
<xsd:group ref="chain-elements-group"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -1710,7 +1715,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="header-enricher-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -1855,6 +1860,7 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="userDefinedHeaderType">
|
||||
@@ -1970,7 +1976,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="header-filter-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -1998,6 +2004,7 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="transformer">
|
||||
@@ -2009,7 +2016,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="expressionOrInnerEndpointDefinitionAware">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2026,7 +2033,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="specialized-transformer-charset-aware-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2040,7 +2047,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="specialized-transformer-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2054,7 +2061,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="map-to-object-transformer-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2085,6 +2092,7 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="object-to-json-transformer">
|
||||
@@ -2096,7 +2104,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="object-to-json-transformer-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2139,6 +2147,7 @@
|
||||
</xsd:appinfo>-->
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="json-to-object-transformer">
|
||||
@@ -2150,7 +2159,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="json-to-object-transformer-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2185,6 +2194,7 @@
|
||||
</xsd:appinfo>-->
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="payload-serializing-transformer">
|
||||
@@ -2196,7 +2206,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="payload-serializing-transformer-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2220,6 +2230,7 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="payload-deserializing-transformer">
|
||||
@@ -2231,7 +2242,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="payload-deserializing-transformer-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2255,6 +2266,7 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="syslog-to-map-transformer">
|
||||
@@ -2264,7 +2276,8 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -2285,7 +2298,7 @@
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
<xsd:element ref="poller" />
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2313,7 +2326,7 @@
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
<xsd:element ref="poller" />
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2346,6 +2359,7 @@
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="commonClaimCheckType">
|
||||
<xsd:attribute name="id" type="xsd:string"/>
|
||||
<xsd:attribute name="message-store" default="messageStore">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -2367,6 +2381,7 @@
|
||||
<xsd:any processContents="strict" namespace="##other" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element ref="poller" />
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="specialized-transformer-charset-aware-type">
|
||||
@@ -2394,7 +2409,7 @@
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="filter-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -2946,16 +2961,6 @@
|
||||
-->
|
||||
|
||||
<xsd:attributeGroup name="topLevelRouterAttributeGroup">
|
||||
<xsd:attribute name="id" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[Identifies the underlying Spring bean
|
||||
definition which in case of Routers is an instance of
|
||||
EventDrivenConsumer or PollingConsumer depending on whether
|
||||
the Router's "input-channel" is a "SubscribableChannel" or
|
||||
"PollableChannel", respectively. This is an "optional" attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="auto-startup" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -2998,6 +3003,16 @@
|
||||
-->
|
||||
|
||||
<xsd:complexType name="abstractRouterType" abstract="true">
|
||||
<xsd:attribute name="id" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[Identifies the underlying Spring bean
|
||||
definition which in case of Routers is an instance of
|
||||
EventDrivenConsumer or PollingConsumer depending on whether
|
||||
the Router's "input-channel" is a "SubscribableChannel" or
|
||||
"PollableChannel", respectively. This is an "optional" attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="default-output-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -3099,7 +3114,7 @@ is provided, the return value is expected to match a channel name exactly.
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="splitter-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -3149,7 +3164,7 @@ is provided, the return value is expected to match a channel name exactly.
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="aggregator-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -3318,7 +3333,7 @@ is provided, the return value is expected to match a channel name exactly.
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="resequencer-type">
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -3787,7 +3802,7 @@ The list of component name patterns you want to track (e.g., tracked-components
|
||||
<xsd:all minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="poller" type="basePollerType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:all>
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -3805,6 +3820,7 @@ The list of component name patterns you want to track (e.g., tracked-components
|
||||
3) get/set or shutdown methods on configurable TaskExecutors or TaskSchedulers
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:attributeGroup name="inputOutputChannelGroup">
|
||||
@@ -3864,19 +3880,6 @@ endpoint itself is a Polling Consumer for a channel with a queue.
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:attributeGroup name="inputOutputChannelGroupWithId">
|
||||
<xsd:attribute name="id" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
'id' value:
|
||||
- Identifies the underlying Spring bean definition (AbstractEndpoint)
|
||||
- as MessageHandler bean alias together with suffix '.handler'
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup"/>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:attributeGroup name="subscribersAttributeGroup">
|
||||
<xsd:attribute name="max-subscribers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
|
||||
@@ -1,78 +1,89 @@
|
||||
<?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
|
||||
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="pollableInput1">
|
||||
<queue />
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<channel id="pollableInput2">
|
||||
<queue />
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<channel id="output">
|
||||
<queue />
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<channel id="replyOutput">
|
||||
<queue />
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<chain input-channel="filterInput" output-channel="output">
|
||||
<filter ref="typeSelector" />
|
||||
<service-activator ref="testHandler" />
|
||||
<chain id="filterChain" input-channel="filterInput" output-channel="output">
|
||||
<filter id="filterWithinChain" ref="typeSelector"/>
|
||||
<service-activator id="serviceActivatorWithinChain" ref="testHandler"/>
|
||||
</chain>
|
||||
|
||||
<chain input-channel="headerEnricherInput">
|
||||
<header-enricher>
|
||||
<chain id="headerEnricherChain" input-channel="headerEnricherInput">
|
||||
<header-enricher id="headerEnricherWithinChain">
|
||||
<reply-channel ref="replyOutput"/>
|
||||
<correlation-id value="ABC"/>
|
||||
<header name="testValue" value="XYZ" />
|
||||
<header name="testRef" ref="testHeaderValue" />
|
||||
<header name="testValue" value="XYZ"/>
|
||||
<header name="testRef" ref="testHeaderValue"/>
|
||||
</header-enricher>
|
||||
<service-activator ref="testHandler" />
|
||||
<service-activator ref="testHandler"/>
|
||||
</chain>
|
||||
|
||||
<chain input-channel="pollableInput1" output-channel="output">
|
||||
<filter ref="typeSelector" />
|
||||
<poller fixed-delay="10000" />
|
||||
<service-activator ref="testHandler" />
|
||||
<filter ref="typeSelector"/>
|
||||
<poller fixed-delay="10000"/>
|
||||
<service-activator ref="testHandler"/>
|
||||
</chain>
|
||||
|
||||
<chain input-channel="pollableInput2" output-channel="output">
|
||||
<service-activator ref="testHandler" />
|
||||
<service-activator ref="testHandler"/>
|
||||
<poller ref="topLevelPoller"/>
|
||||
</chain>
|
||||
|
||||
<poller id="topLevelPoller" fixed-delay="5000" />
|
||||
<poller id="topLevelPoller" fixed-delay="5000"/>
|
||||
|
||||
<chain input-channel="beanInput" output-channel="output">
|
||||
<beans:bean
|
||||
class="org.springframework.integration.config.ChainParserTests$StubHandler" />
|
||||
class="org.springframework.integration.config.ChainParserTests$StubHandler"/>
|
||||
</chain>
|
||||
|
||||
<chain input-channel="aggregatorInput" output-channel="output">
|
||||
<aggregator ref="aggregatorBean" method="aggregate" />
|
||||
<chain>
|
||||
<filter ref="typeSelector" />
|
||||
<service-activator ref="testHandler" />
|
||||
<chain id="aggregatorChain" input-channel="aggregatorInput" output-channel="output">
|
||||
<aggregator id="aggregatorWithinChain" ref="aggregatorBean" method="aggregate"/>
|
||||
<chain id="nestedChain">
|
||||
<filter id="filterWithinNestedChain" ref="typeSelector"/>
|
||||
<service-activator ref="testHandler"/>
|
||||
<chain id="doubleNestedChain">
|
||||
<filter id="filterWithinDoubleNestedChain" ref="typeSelector"/>
|
||||
</chain>
|
||||
</chain>
|
||||
</chain>
|
||||
|
||||
<chain input-channel="payloadTypeRouterInput">
|
||||
<payload-type-router>
|
||||
<chain id="aggregatorChain2" input-channel="aggregatorInput" output-channel="output">
|
||||
<aggregator id="aggregatorWithinChain" ref="aggregatorBean" method="aggregate"/>
|
||||
<chain id="nestedChain">
|
||||
<filter id="filterWithinNestedChain" ref="typeSelector"/>
|
||||
<service-activator ref="testHandler"/>
|
||||
</chain>
|
||||
</chain>
|
||||
|
||||
<chain id="payloadTypeRouterChain" input-channel="payloadTypeRouterInput">
|
||||
<payload-type-router id="payloadTypeRouterWithinChain">
|
||||
<mapping type="java.lang.String" channel="strings"/>
|
||||
<mapping type="java.lang.Number" channel="numbers"/>
|
||||
</payload-type-router>
|
||||
</chain>
|
||||
|
||||
<chain input-channel="headerValueRouterInput">
|
||||
<header-value-router header-name="routingHeader"/>
|
||||
<chain id="headerValueRouterChain" input-channel="headerValueRouterInput">
|
||||
<header-value-router id="headerValueRouterWithinChain" header-name="routingHeader"/>
|
||||
</chain>
|
||||
|
||||
<chain input-channel="headerValueRouterWithMappingInput">
|
||||
@@ -82,31 +93,74 @@
|
||||
</header-value-router>
|
||||
</chain>
|
||||
|
||||
<chain id="chainWithClaimChecks" input-channel="claimCheckInput" output-channel="claimCheckOutput">
|
||||
<claim-check-in/>
|
||||
<claim-check-out/>
|
||||
</chain>
|
||||
|
||||
<channel id="claimCheckOutput">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<chain id="chainWithSendTimeout" input-channel="chainWithSendTimeoutInput" output-channel="output" send-timeout="9876">
|
||||
<filter ref="typeSelector" />
|
||||
<service-activator ref="testHandler" />
|
||||
<chain id="chainWithClaimChecks" input-channel="claimCheckInput" output-channel="claimCheckOutput">
|
||||
<claim-check-in id="claimCheckInWithinChain"/>
|
||||
<claim-check-out id="claimCheckOutWithinChain"/>
|
||||
</chain>
|
||||
|
||||
<chain input-channel="outboundChannelAdapterChannel">
|
||||
<outbound-channel-adapter ref="testConsumer"/>
|
||||
<channel id="claimCheckOutput">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<chain id="chainWithSendTimeout" input-channel="chainWithSendTimeoutInput" output-channel="output"
|
||||
send-timeout="9876">
|
||||
<filter ref="typeSelector"/>
|
||||
<service-activator ref="testHandler"/>
|
||||
</chain>
|
||||
|
||||
<chain id="outboundChain" input-channel="outboundChannelAdapterChannel">
|
||||
<outbound-channel-adapter id="outboundChannelAdapterWithinChain" ref="testConsumer"/>
|
||||
</chain>
|
||||
|
||||
<chain id="logChain" input-channel="loggingChannelAdapterChannel">
|
||||
<object-to-string-transformer charset="cp1251"/>
|
||||
<transformer expression="payload.toUpperCase()"/>
|
||||
<logging-channel-adapter level="WARN"/>
|
||||
<transformer id="transformerWithinChain" expression="payload.toUpperCase()"/>
|
||||
<logging-channel-adapter id="loggingChannelAdapterWithinChain" level="WARN"/>
|
||||
</chain>
|
||||
|
||||
<beans:bean id="testConsumer" class="org.springframework.integration.config.TestConsumer" />
|
||||
<chain id="subComponentsIdSupport1" input-channel="subComponentsIdSupport1Channel">
|
||||
<splitter id="splitterWithinChain"/>
|
||||
<resequencer id="resequencerWithinChain"/>
|
||||
<enricher id="enricherWithinChain" requires-reply="false">
|
||||
<property name="foo" value="bar"/>
|
||||
</enricher>
|
||||
<header-filter id="headerFilterWithinChain" header-names="foo"/>
|
||||
<payload-serializing-transformer id="payloadSerializingTransformerWithinChain"/>
|
||||
<payload-deserializing-transformer id="payloadDeserializingTransformerWithinChain"/>
|
||||
<gateway id="gatewayWithinChain" request-channel="strings"/>
|
||||
<object-to-string-transformer id="objectToStringTransformerWithinChain"/>
|
||||
<object-to-map-transformer id="objectToMapTransformerWithinChain"/>
|
||||
<map-to-object-transformer id="mapToObjectTransformerWithinChain"
|
||||
type="org.springframework.integration.config.ChainParserTests$FooPojo"/>
|
||||
<object-to-json-transformer id="objectToJsonTransformerWithinChain"/>
|
||||
<json-to-object-transformer id="jsonToObjectTransformerWithinChain"
|
||||
type="org.springframework.integration.config.ChainParserTests$FooPojo"/>
|
||||
<control-bus id="controlBusWithinChain"/>
|
||||
<router id="routerWithinChain" expression="foo"/>
|
||||
</chain>
|
||||
|
||||
<chain id="exceptionTypeRouterChain" input-channel="subComponentsIdSupport2Channel">
|
||||
<exception-type-router id="exceptionTypeRouterWithinChain">
|
||||
<mapping channel="numbers" exception-type="org.springframework.integration.MessageRejectedException"/>
|
||||
</exception-type-router>
|
||||
</chain>
|
||||
|
||||
<chain id="recipientListRouterChain" input-channel="subComponentsIdSupport3Channel">
|
||||
<recipient-list-router id="recipientListRouterWithinChain">
|
||||
<recipient channel="strings"/>
|
||||
<recipient channel="numbers"/>
|
||||
</recipient-list-router>
|
||||
</chain>
|
||||
|
||||
<chain id="chainReplayRequired" input-channel="chainReplayRequiredChannel">
|
||||
<transformer id="transformerReplayRequired" expression="null"/>
|
||||
</chain>
|
||||
|
||||
<chain id="chainMessageRejectedException" input-channel="chainMessageRejectedExceptionChannel">
|
||||
<filter id="filterMessageRejectedException" expression="false" throw-exception-on-rejection="true"/>
|
||||
</chain>
|
||||
|
||||
<beans:bean id="testConsumer" class="org.springframework.integration.config.TestConsumer"/>
|
||||
|
||||
<channel id="strings">
|
||||
<queue/>
|
||||
@@ -117,21 +171,21 @@
|
||||
</channel>
|
||||
|
||||
<beans:bean id="aggregatorBean"
|
||||
class="org.springframework.integration.config.ChainParserTests$StubAggregator" />
|
||||
class="org.springframework.integration.config.ChainParserTests$StubAggregator"/>
|
||||
|
||||
<beans:bean id="testHeaderValue" class="java.lang.Integer">
|
||||
<beans:constructor-arg value="123" />
|
||||
<beans:constructor-arg value="123"/>
|
||||
</beans:bean>
|
||||
|
||||
<beans:bean id="typeSelector"
|
||||
class="org.springframework.integration.selector.PayloadTypeSelector">
|
||||
<beans:constructor-arg value="java.lang.String" />
|
||||
class="org.springframework.integration.selector.PayloadTypeSelector">
|
||||
<beans:constructor-arg value="java.lang.String"/>
|
||||
</beans:bean>
|
||||
|
||||
<beans:bean id="testHandler"
|
||||
class="org.springframework.integration.config.TestHandler">
|
||||
<beans:constructor-arg value="1" />
|
||||
<beans:property name="replyMessageText" value="foo" />
|
||||
class="org.springframework.integration.config.TestHandler">
|
||||
<beans:constructor-arg value="1"/>
|
||||
<beans:property name="replyMessageText" value="foo"/>
|
||||
</beans:bean>
|
||||
|
||||
<beans:bean id="messageStore" class="org.springframework.integration.store.SimpleMessageStore"/>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
@@ -38,23 +39,30 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageRejectedException;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.handler.LoggingHandler;
|
||||
import org.springframework.integration.handler.MessageHandlerChain;
|
||||
import org.springframework.integration.handler.ReplyRequiredException;
|
||||
import org.springframework.integration.handler.ServiceActivatingHandler;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.message.MessageMatcher;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.transformer.MessageTransformingHandler;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -70,6 +78,9 @@ import org.springframework.util.StringUtils;
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class ChainParserTests {
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("filterInput")
|
||||
private MessageChannel filterInput;
|
||||
@@ -141,6 +152,12 @@ public class ChainParserTests {
|
||||
@Autowired
|
||||
private PollableChannel numbers;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel chainReplayRequiredChannel;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel chainMessageRejectedExceptionChannel;
|
||||
|
||||
public static Message<?> successMessage = MessageBuilder.withPayload("success").build();
|
||||
|
||||
@Factory
|
||||
@@ -324,6 +341,81 @@ public class ChainParserTests {
|
||||
assertEquals(false, TestUtils.getPropertyValue(handlerChain, "running"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt2755SubComponentsIdSupport() {
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("filterChain$child.filterWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("filterChain$child.serviceActivatorWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain$child.aggregatorWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain$child.nestedChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain$child.nestedChain$child.filterWithinNestedChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain$child.nestedChain$child.doubleNestedChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain$child.nestedChain$child.doubleNestedChain$child.filterWithinDoubleNestedChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain2.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain2$child.aggregatorWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain2$child.nestedChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("aggregatorChain2$child.nestedChain$child.filterWithinNestedChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("payloadTypeRouterChain$child.payloadTypeRouterWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("headerValueRouterChain$child.headerValueRouterWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("chainWithClaimChecks$child.claimCheckInWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("chainWithClaimChecks$child.claimCheckOutWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("outboundChain$child.outboundChannelAdapterWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("logChain$child.transformerWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("logChain$child.loggingChannelAdapterWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.splitterWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.resequencerWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.enricherWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.headerFilterWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.payloadSerializingTransformerWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.payloadDeserializingTransformerWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.gatewayWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.objectToStringTransformerWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.objectToMapTransformerWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.mapToObjectTransformerWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.controlBusWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.routerWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("exceptionTypeRouterChain$child.exceptionTypeRouterWithinChain.handler"));
|
||||
assertTrue(this.beanFactory.containsBean("recipientListRouterChain$child.recipientListRouterWithinChain.handler"));
|
||||
|
||||
MessageHandlerChain chain = this.beanFactory.getBean("headerEnricherChain.handler", MessageHandlerChain.class);
|
||||
List handlers = TestUtils.getPropertyValue(chain, "handlers", List.class);
|
||||
|
||||
assertTrue(handlers.get(0) instanceof MessageTransformingHandler);
|
||||
assertEquals("headerEnricherChain$child.headerEnricherWithinChain", TestUtils.getPropertyValue(handlers.get(0), "componentName"));
|
||||
assertEquals("headerEnricherChain$child.headerEnricherWithinChain.handler", TestUtils.getPropertyValue(handlers.get(0), "beanName"));
|
||||
assertTrue(this.beanFactory.containsBean("headerEnricherChain$child.headerEnricherWithinChain.handler"));
|
||||
|
||||
assertTrue(handlers.get(1) instanceof ServiceActivatingHandler);
|
||||
assertEquals("headerEnricherChain$child#1", TestUtils.getPropertyValue(handlers.get(1), "componentName"));
|
||||
assertNull(TestUtils.getPropertyValue(handlers.get(1), "beanName"));
|
||||
assertFalse(this.beanFactory.containsBean("headerEnricherChain$child#1.handler"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt2755SubComponentException() {
|
||||
GenericMessage<String> testMessage = new GenericMessage<String>("test");
|
||||
try {
|
||||
this.chainReplayRequiredChannel.send(testMessage);
|
||||
fail("Expected ReplyRequiredException");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue(e instanceof ReplyRequiredException);
|
||||
assertTrue(e.getMessage().contains("'chainReplayRequired$child.transformerReplayRequired'"));
|
||||
}
|
||||
|
||||
try {
|
||||
this.chainMessageRejectedExceptionChannel.send(testMessage);
|
||||
fail("Expected MessageRejectedException");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue(e instanceof MessageRejectedException);
|
||||
assertTrue(e.getMessage().contains("chainMessageRejectedException$child.filterMessageRejectedException"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class StubHandler extends AbstractReplyProducingMessageHandler {
|
||||
|
||||
@Override
|
||||
@@ -339,4 +431,20 @@ public class ChainParserTests {
|
||||
return StringUtils.collectionToCommaDelimitedString(strings);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FooPojo {
|
||||
|
||||
|
||||
private String bar;
|
||||
|
||||
public String getBar() {
|
||||
return bar;
|
||||
}
|
||||
|
||||
public void setBar(String bar) {
|
||||
this.bar = bar;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.springframework.integration.config.xml;
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -14,14 +13,17 @@ package org.springframework.integration.config.xml;
|
||||
* 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 static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
@@ -35,6 +37,7 @@ import org.springframework.core.io.InputStreamResource;
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gunnar Hillert
|
||||
* @author Artem Bilan
|
||||
*
|
||||
*/
|
||||
public class ChainElementsFailureTests {
|
||||
@@ -227,12 +230,25 @@ public class ChainElementsFailureTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt2755DetectDuplicateHandlerId() throws Exception {
|
||||
|
||||
try {
|
||||
this.bootStrap("duplicate-handler-id");
|
||||
fail("Expected a BeanDefinitionParsingException to be thrown.");
|
||||
}
|
||||
catch (BeanDefinitionParsingException e) {
|
||||
assertTrue(e.getMessage().contains("A bean definition is already registered for " +
|
||||
"beanName: 'foo$child.bar.handler' within the current <chain>."));
|
||||
}
|
||||
}
|
||||
|
||||
private ApplicationContext bootStrap(String configProperty) throws Exception {
|
||||
PropertiesFactoryBean pfb = new PropertiesFactoryBean();
|
||||
pfb.setLocation(new ClassPathResource("org/springframework/integration/config/xml/chain-elements-config.properties"));
|
||||
pfb.afterPropertiesSet();
|
||||
Properties prop = pfb.getObject();
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(prop.getProperty("xmlheaders")).append(prop.getProperty(configProperty)).append(prop.getProperty("xmlfooter"));
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(buffer.toString().getBytes());
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
@@ -243,7 +259,7 @@ public class ChainElementsFailureTests {
|
||||
return ac;
|
||||
}
|
||||
|
||||
public static class Sampleservice {
|
||||
public static class SampleService {
|
||||
public String echo(String value){
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertNotSame;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -36,6 +37,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@Ignore
|
||||
public class NestedChainParserTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -10,7 +10,7 @@ xmlfooter= </beans>
|
||||
service-activator=\
|
||||
<int:chain input-channel="input"> \
|
||||
<int:service-activator input-channel="fail"> \
|
||||
<bean class="org.springframework.integration.config.xml.ChainElementsFailureTests$Sampleservice"/> \
|
||||
<bean class="org.springframework.integration.config.xml.ChainElementsFailureTests$SampleService"/> \
|
||||
</int:service-activator> \
|
||||
</int:chain>
|
||||
|
||||
@@ -81,4 +81,9 @@ resequencer-poller=\
|
||||
<int:resequencer> \
|
||||
<int:poller fixed-rate="5000" max-messages-per-poll="10" />\
|
||||
</int:resequencer> \
|
||||
</int:chain>
|
||||
</int:chain>
|
||||
duplicate-handler-id=\
|
||||
<int:chain id="foo" input-channel="input"> \
|
||||
<int:splitter id="bar"/> \
|
||||
<int:aggregator id="bar"/> \
|
||||
</int:chain>
|
||||
|
||||
@@ -172,21 +172,6 @@ public class MessageHandlerChainTests {
|
||||
chain.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentNaming() {
|
||||
List<MessageHandler> handlers = new ArrayList<MessageHandler>();
|
||||
handlers.add(producer1);
|
||||
handlers.add(handler1); // this one won't be named
|
||||
handlers.add(producer2);
|
||||
handlers.add(producer3);
|
||||
MessageHandlerChain chain = new MessageHandlerChain();
|
||||
chain.setHandlers(handlers);
|
||||
chain.setComponentName("testChain");
|
||||
assertEquals("testChain.handler#0", producer1.getComponentName());
|
||||
assertEquals("testChain.handler#2", producer2.getComponentName());
|
||||
assertEquals("testChain.handler#3", producer3.getComponentName());
|
||||
}
|
||||
|
||||
private static class ProducingHandlerStub extends IntegrationObjectSupport implements MessageHandler, MessageProducer {
|
||||
|
||||
private volatile MessageChannel output;
|
||||
@@ -199,7 +184,7 @@ public class MessageHandlerChainTests {
|
||||
|
||||
public void setOutputChannel(MessageChannel channel) {
|
||||
this.output = channel;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void handleMessage(Message<?> message) {
|
||||
|
||||
@@ -46,6 +46,7 @@ import static org.junit.Assert.assertNull;
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gunnar Hillert
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public class MessageHistoryIntegrationTests {
|
||||
|
||||
@@ -69,61 +70,65 @@ public class MessageHistoryIntegrationTests {
|
||||
public void handleMessage(Message<?> message) {
|
||||
Iterator<Properties> historyIterator = message.getHeaders().get(MessageHistory.HEADER_NAME, MessageHistory.class).iterator();
|
||||
|
||||
Properties event1 = historyIterator.next();
|
||||
assertEquals("sampleGateway", event1.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("gateway", event1.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
Properties event = historyIterator.next();
|
||||
assertEquals("sampleGateway", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("gateway", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event2 = historyIterator.next();
|
||||
assertEquals("bridgeInChannel", event2.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event2.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("bridgeInChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event3 = historyIterator.next();
|
||||
assertEquals("testBridge", event3.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("bridge", event3.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("testBridge", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("bridge", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event4 = historyIterator.next();
|
||||
assertEquals("headerEnricherChannel", event4.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event4.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("headerEnricherChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event5 = historyIterator.next();
|
||||
assertEquals("testHeaderEnricher", event5.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("transformer", event5.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("testHeaderEnricher", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("transformer", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event6 = historyIterator.next();
|
||||
assertEquals("chainChannel", event6.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event6.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("chainChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event7 = historyIterator.next();
|
||||
assertEquals("sampleChain", event7.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("chain", event7.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("sampleChain", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("chain", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event8 = historyIterator.next();
|
||||
assertEquals("filterChannel", event8.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event8.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("sampleChain$child.service-activator-within-chain", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("service-activator", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event9 = historyIterator.next();
|
||||
assertEquals("testFilter", event9.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("filter", event9.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("filterChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event10 = historyIterator.next();
|
||||
assertEquals("splitterChannel", event10.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event10.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("testFilter", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("filter", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event11 = historyIterator.next();
|
||||
assertEquals("testSplitter", event11.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("splitter", event11.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("splitterChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event12 = historyIterator.next();
|
||||
assertEquals("aggregatorChannel", event12.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event12.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("testSplitter", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("splitter", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event13 = historyIterator.next();
|
||||
assertEquals("testAggregator", event13.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("aggregator", event13.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("aggregatorChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
Properties event14 = historyIterator.next();
|
||||
assertEquals("endOfThePipeChannel", event14.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event14.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
event = historyIterator.next();
|
||||
assertEquals("testAggregator", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("aggregator", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
event = historyIterator.next();
|
||||
assertEquals("endOfThePipeChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
|
||||
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
|
||||
|
||||
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
|
||||
replyChannel.send(message);
|
||||
|
||||
@@ -5,34 +5,35 @@
|
||||
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">
|
||||
|
||||
<int:gateway id="sampleGateway"
|
||||
<int:gateway id="sampleGateway"
|
||||
service-interface="org.springframework.integration.history.MessageHistoryIntegrationTests.SampleGateway"
|
||||
default-request-channel="bridgeInChannel"/>
|
||||
|
||||
|
||||
<int:channel id="bridgeInChannel"/>
|
||||
|
||||
|
||||
<int:bridge id="testBridge" input-channel="bridgeInChannel" output-channel="headerEnricherChannel"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<int:header-enricher id="testHeaderEnricher" input-channel="headerEnricherChannel" output-channel="chainChannel">
|
||||
<int:header name="foo" value="foo"/>
|
||||
</int:header-enricher>
|
||||
|
||||
|
||||
<int:chain id="sampleChain" input-channel="chainChannel" output-channel="filterChannel">
|
||||
<int:header-enricher>
|
||||
<int:header name="baz" value="baz"/>
|
||||
</int:header-enricher>
|
||||
<int:service-activator id="service-activator-within-chain" expression="payload"/>
|
||||
</int:chain>
|
||||
|
||||
<int:filter id="testFilter" input-channel="filterChannel"
|
||||
|
||||
<int:filter id="testFilter" input-channel="filterChannel"
|
||||
output-channel="splitterChannel" expression="payload.equals('hello')"/>
|
||||
|
||||
|
||||
<int:splitter id="testSplitter" input-channel="splitterChannel" output-channel="aggregatorChannel"/>
|
||||
|
||||
|
||||
<int:aggregator id="testAggregator" input-channel="aggregatorChannel" output-channel="endOfThePipeChannel"/>
|
||||
|
||||
|
||||
<int:channel id="endOfThePipeChannel"/>
|
||||
|
||||
|
||||
<bean class="org.springframework.integration.history.MessageHistoryConfigurer"/>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -17,4 +17,8 @@
|
||||
|
||||
<beans:bean id="testBean" class="org.springframework.integration.transformer.SpelTransformerIntegrationTests$TestBean"/>
|
||||
|
||||
<chain id="transformerChain" input-channel="transformerChainInput">
|
||||
<transformer expression="null"/>
|
||||
</chain>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -17,7 +17,9 @@
|
||||
package org.springframework.integration.transformer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -26,12 +28,15 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.handler.ReplyRequiredException;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@@ -46,6 +51,9 @@ public class SpelTransformerIntegrationTests {
|
||||
@Autowired @Qualifier("output")
|
||||
private PollableChannel output;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel transformerChainInput;
|
||||
|
||||
|
||||
@Test
|
||||
public void simple() {
|
||||
@@ -63,6 +71,16 @@ public class SpelTransformerIntegrationTests {
|
||||
assertEquals("testFOO", result.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt2755ChainChildIdWithinExceptionMessage() {
|
||||
try {
|
||||
this.transformerChainInput.send(new GenericMessage<String>("foo"));
|
||||
}
|
||||
catch (ReplyRequiredException e) {
|
||||
assertThat(e.getMessage(), Matchers.containsString("No reply produced by handler 'transformerChain$child#0'"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class TestBean {
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<si:header-enricher>
|
||||
<si:header name="#{T(org.springframework.integration.file.FileHeaders).FILENAME}" value="${test.file}"/>
|
||||
</si:header-enricher>
|
||||
<file:outbound-channel-adapter directory="${work.dir}"/>
|
||||
<file:outbound-channel-adapter id="file-outbound-channel-adapter-within-chain" directory="${work.dir}"/>
|
||||
</si:chain>
|
||||
|
||||
<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
@@ -61,6 +62,9 @@ public class FileOutboundChannelAdapterInsideChainTests {
|
||||
@Autowired
|
||||
private MessageChannel outboundChainChannel;
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private static File workDir;
|
||||
|
||||
@BeforeClass
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
delete-source-files="true"/>
|
||||
|
||||
<si:chain input-channel="fileOutboundGatewayInsideChain" output-channel="output">
|
||||
<outbound-gateway directory="${java.io.tmpdir}/anyDir" delete-source-files="true"/>
|
||||
<outbound-gateway id="file-outbound-gateway-within-chain" directory="${java.io.tmpdir}/anyDir" delete-source-files="true"/>
|
||||
</si:chain>
|
||||
|
||||
<!--suppress SpringModelInspection -->
|
||||
|
||||
@@ -19,7 +19,9 @@ package org.springframework.integration.file;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -150,6 +152,10 @@ public class FileOutboundGatewayIntegrationTests {
|
||||
|
||||
@Test //INT-1029
|
||||
public void moveInsideTheChain() throws Exception {
|
||||
// INT-2755
|
||||
Object bean = this.beanFactory.getBean("org.springframework.integration.handler.MessageHandlerChain#0$child.file-outbound-gateway-within-chain.handler");
|
||||
assertTrue(bean instanceof FileWritingMessageHandler);
|
||||
|
||||
fileOutboundGatewayInsideChain.send(message);
|
||||
List<Message<?>> result = outputChannel.clear();
|
||||
assertThat(result.size(), is(1));
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
maxOccurs="1" />
|
||||
<xsd:element name="request-handler-advice-chain" type="integration:adviceChainType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:choice>
|
||||
<xsd:attributeGroup ref="integration:inputOutputChannelGroupWithId" />
|
||||
<xsd:attributeGroup ref="integration:inputOutputChannelGroup" />
|
||||
<xsd:attribute name="customizer" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
|
||||
<int:chain input-channel="tcpOutboundGatewayInsideChain" output-channel="replyChannel">
|
||||
<ip:tcp-outbound-gateway connection-factory="crLfClient2"/>
|
||||
<ip:tcp-outbound-gateway id="tcp-outbound-gateway-within-chain" connection-factory="crLfClient2"/>
|
||||
</int:chain>
|
||||
|
||||
<int:channel id="replyChannel" >
|
||||
|
||||
@@ -173,6 +173,7 @@ public class TcpConfigOutboundGatewayTests {
|
||||
|
||||
@Test //INT-1029
|
||||
public void testOutboundInsideChain() throws Exception {
|
||||
// this.ctx.getBean("tcp-outbound-gateway-within-chain.handler", TcpOutboundGateway.class);
|
||||
tcpOutboundGatewayInsideChain.send(MessageBuilder.withPayload("test").build());
|
||||
byte[] bytes = (byte[]) replyChannel.receive().getPayload();
|
||||
assertEquals("echo:test", new String(bytes).trim());
|
||||
|
||||
@@ -73,7 +73,7 @@ public class JdbcOutboundGatewayParserTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, ?> payload = (Map<String, ?>) reply.getPayload();
|
||||
assertEquals("bar", payload.get("name"));
|
||||
JdbcOutboundGateway gateway = context.getBean(JdbcOutboundGateway.class);
|
||||
JdbcOutboundGateway gateway = context.getBean("jdbcGateway.handler", JdbcOutboundGateway.class);
|
||||
assertEquals(23, TestUtils.getPropertyValue(gateway, "order"));
|
||||
Object gw = context.getBean("jdbcGateway");
|
||||
assertEquals(1, adviceCalled);
|
||||
@@ -204,6 +204,10 @@ public class JdbcOutboundGatewayParserTests {
|
||||
@Test //INT-1029
|
||||
public void testOutboundGatewayInsideChain() {
|
||||
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("handlingMapPayloadJdbcOutboundGatewayTest.xml", getClass());
|
||||
//INT-2755
|
||||
assertNotNull(context.getBean("org.springframework.integration.handler.MessageHandlerChain#0$child.jdbc-outbound-gateway-within-chain.handler",
|
||||
JdbcOutboundGateway.class));
|
||||
|
||||
MessageChannel channel = context.getBean("jdbcOutboundGatewayInsideChain", MessageChannel.class);
|
||||
channel.send(MessageBuilder.withPayload(Collections.singletonMap("foo", "bar")).build());
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</outbound-gateway>
|
||||
|
||||
<si:chain input-channel="jdbcOutboundGatewayInsideChain" output-channel="replyChannel">
|
||||
<outbound-gateway query="select * from foos where id=:headers[id]"
|
||||
<outbound-gateway id="jdbc-outbound-gateway-within-chain" query="select * from foos where id=:headers[id]"
|
||||
update="insert into foos (id, status, name) values (:headers[id], 0, :payload[foo])"
|
||||
data-source="dataSource"/>
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:jmx="http://www.springframework.org/schema/integration/jmx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:jmx="http://www.springframework.org/schema/integration/jmx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
@@ -24,15 +24,16 @@
|
||||
object-name="test.publisher:name=publisher"
|
||||
default-notification-type="default.type">
|
||||
<jmx:request-handler-advice-chain>
|
||||
<bean class="org.springframework.integration.jmx.config.NotificationPublishingChannelAdapterParserTests$FooADvice" />
|
||||
<bean class="org.springframework.integration.jmx.config.NotificationPublishingChannelAdapterParserTests$FooADvice"/>
|
||||
</jmx:request-handler-advice-chain>
|
||||
</jmx:notification-publishing-channel-adapter>
|
||||
|
||||
|
||||
<si:chain input-channel="publishingWithinChainChannel">
|
||||
<si:chain id="chainWithJmxNotificationPublishing" input-channel="publishingWithinChainChannel">
|
||||
<jmx:notification-publishing-channel-adapter
|
||||
object-name="test.publisher:name=publisher-chain"
|
||||
default-notification-type="default.type"/>
|
||||
id="jmx-notification-publishing-channel-adapter-within-chain"
|
||||
object-name="test.publisher:name=publisher-chain"
|
||||
default-notification-type="default.type"/>
|
||||
</si:chain>
|
||||
|
||||
<bean id="testListener" class="org.springframework.integration.jmx.config.TestListener"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -20,16 +20,22 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.Notification;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
|
||||
import org.springframework.integration.jmx.JmxHeaders;
|
||||
import org.springframework.integration.jmx.NotificationPublishingMessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -53,6 +59,12 @@ public class NotificationPublishingChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private MessageChannel publishingWithinChainChannel;
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Autowired
|
||||
private MBeanServer server;
|
||||
|
||||
private static volatile int adviceCalled;
|
||||
|
||||
@After
|
||||
@@ -60,7 +72,6 @@ public class NotificationPublishingChannelAdapterParserTests {
|
||||
listener.lastNotification = null;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void publishStringMessage() throws Exception {
|
||||
adviceCalled = 0;
|
||||
@@ -102,6 +113,8 @@ public class NotificationPublishingChannelAdapterParserTests {
|
||||
|
||||
@Test //INT-2275
|
||||
public void publishStringMessageWithinChain() throws Exception {
|
||||
assertNotNull(this.beanFactory.getBean("chainWithJmxNotificationPublishing$child.jmx-notification-publishing-channel-adapter-within-chain.handler",
|
||||
MessageHandler.class));
|
||||
assertNull(listener.lastNotification);
|
||||
Message<?> message = MessageBuilder.withPayload("XYZ")
|
||||
.setHeader(JmxHeaders.NOTIFICATION_TYPE, "test.type").build();
|
||||
@@ -111,9 +124,15 @@ public class NotificationPublishingChannelAdapterParserTests {
|
||||
assertEquals("XYZ", notification.getMessage());
|
||||
assertEquals("test.type", notification.getType());
|
||||
assertNull(notification.getUserData());
|
||||
Set<ObjectName> names = server.queryNames(
|
||||
new ObjectName("org.springframework.integration:type=MessageHandler," +
|
||||
"name=chainWithJmxNotificationPublishing$child.jmx-notification-publishing-channel-adapter-within-chain.handler,*")
|
||||
, null);
|
||||
assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
private static class TestData {
|
||||
|
||||
}
|
||||
|
||||
public static class FooADvice extends AbstractRequestHandlerAdvice {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -40,6 +40,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@@ -69,6 +70,8 @@ public class JpaOutboundGatewayFactoryBean extends AbstractFactoryBean<MessageHa
|
||||
|
||||
private long replyTimeout;
|
||||
|
||||
private volatile String componentName;
|
||||
|
||||
/**
|
||||
* Constructor taking an {@link JpaExecutor} that wraps all JPA Operations.
|
||||
*
|
||||
@@ -114,6 +117,16 @@ public class JpaOutboundGatewayFactoryBean extends AbstractFactoryBean<MessageHa
|
||||
public void setReplyTimeout(long replyTimeout) {
|
||||
this.replyTimeout = replyTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the handler component.
|
||||
*
|
||||
* @param componentName
|
||||
*/
|
||||
public void setComponentName(String componentName) {
|
||||
this.componentName = componentName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return MessageHandler.class;
|
||||
@@ -128,6 +141,7 @@ public class JpaOutboundGatewayFactoryBean extends AbstractFactoryBean<MessageHa
|
||||
jpaOutboundGateway.setOutputChannel(this.outputChannel);
|
||||
jpaOutboundGateway.setOrder(this.order);
|
||||
jpaOutboundGateway.setSendTimeout(replyTimeout);
|
||||
jpaOutboundGateway.setComponentName(this.componentName);
|
||||
if (this.adviceChain != null) {
|
||||
jpaOutboundGateway.setAdviceChain(this.adviceChain);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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.mail;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
@@ -30,7 +31,9 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.mapping.MessageMappingException;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
@@ -48,6 +51,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
public class MailSendingMessageHandlerContextTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mailSendingMessageConsumer")
|
||||
private MailSendingMessageHandler handler;
|
||||
|
||||
@Autowired
|
||||
@@ -56,6 +60,9 @@ public class MailSendingMessageHandlerContextTests {
|
||||
@Autowired
|
||||
private MessageChannel sendMailOutboundChainChannel;
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
|
||||
@Before
|
||||
public void reset() {
|
||||
@@ -106,6 +113,7 @@ public class MailSendingMessageHandlerContextTests {
|
||||
|
||||
@Test //INT-2275
|
||||
public void mailOutboundChannelAdapterWithinChain() {
|
||||
assertNotNull(this.beanFactory.getBean("org.springframework.integration.handler.MessageHandlerChain#0$child.mail-outbound-channel-adapter-within-chain.handler"));
|
||||
this.sendMailOutboundChainChannel.send(MailTestsHelper.createIntegrationMessage());
|
||||
SimpleMailMessage mailMessage = MailTestsHelper.createSimpleMailMessage();
|
||||
assertEquals("no mime message should have been sent", 0, this.mailSender.getSentMimeMessages().size());
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</bean>
|
||||
|
||||
<int:chain input-channel="sendMailOutboundChainChannel">
|
||||
<int-mail:outbound-channel-adapter mail-sender="javaMailSender"/>
|
||||
<int-mail:outbound-channel-adapter id="mail-outbound-channel-adapter-within-chain" mail-sender="javaMailSender"/>
|
||||
</int:chain>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
</section>
|
||||
|
||||
<section id="chain-namespace">
|
||||
<title>Configuring Chain</title>
|
||||
<title>Configuring a Chain</title>
|
||||
<para>
|
||||
The <chain> element provides an <code>input-channel</code> attribute, and if the last element in the chain is capable
|
||||
of producing reply messages (optional), it also supports an <code>output-channel</code> attribute. The sub-elements are then
|
||||
@@ -106,22 +106,62 @@
|
||||
attributes and elements.
|
||||
</para>
|
||||
</important>
|
||||
<para><emphasis>'id' Attribute</emphasis></para>
|
||||
<para>
|
||||
The <emphasis>id</emphasis> attribute, however, is allowed to be specified.
|
||||
In fact, the <link linkend='delayer'><emphasis>Delayer</emphasis></link>
|
||||
component actually requires the <emphasis>id</emphasis> attribute to be present.
|
||||
Beginning with Spring Integration 3.0, if a chain element is given an <emphasis>id</emphasis>, the
|
||||
bean name for the element is a combination of the chain's <emphasis>id</emphasis> and the <emphasis>id</emphasis>
|
||||
of the element itself. Elements without an <emphasis>id</emphasis> are not registered
|
||||
as beans, but they are given <code>componentName</code>s that include the chain id. For example:
|
||||
<programlisting language="xml"><![CDATA[<int:chain id="fooChain" input-channel="input">
|
||||
<int:service-activator id="fooService" ref="someService" method="someMethod"/>
|
||||
<int:object-to-json-transformer/>
|
||||
</int:chain>]]></programlisting>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
The <code><chain></code> root element has an <emphasis>id</emphasis> 'fooChain'. So, the
|
||||
<classname>AbstractEndpoint</classname> implementation (<classname>PollingConsumer</classname> or
|
||||
<classname>EventDrivenConsumer</classname>, depending on the <emphasis>input-channel</emphasis> type)
|
||||
bean takes this value as it's bean name.
|
||||
</listitem>
|
||||
<listitem>
|
||||
The <classname>MessageHandlerChain</classname> bean acquires a bean alias 'fooChain.handler', which allows
|
||||
direct access to this bean from the <interfacename>BeanFactory</interfacename>.
|
||||
</listitem>
|
||||
<listitem>
|
||||
The <code><service-activator></code> is not a fully-fledged Messaging Endpoint (<classname>PollingConsumer</classname>
|
||||
or <classname>EventDrivenConsumer</classname>) - it is simply a
|
||||
<interfacename>MessageHandler</interfacename> within the <code><chain></code>. In this case,
|
||||
the bean name registered with the <interfacename>BeanFactory</interfacename>
|
||||
is 'fooChain$child.fooService.handler'.
|
||||
</listitem>
|
||||
<listitem>
|
||||
The <emphasis>componentName</emphasis> of this <classname>ServiceActivatingHandler</classname> takes the
|
||||
same value, but without the '.handler' suffix - 'fooChain$child.fooService'.
|
||||
</listitem>
|
||||
<listitem>
|
||||
The last <code><chain></code> sub-component, <code><object-to-json-transformer></code>, doesn't have
|
||||
an <emphasis>id</emphasis> attribute. Its <emphasis>componentName</emphasis> is based on its
|
||||
position in the <code><chain></code>. In this case, it is 'fooChain$child#1'.
|
||||
(The final element of the name is the order within the chain, beginning with '#0').
|
||||
Note, this transformer isn't registered as a bean within the application context,
|
||||
so, it doesn't get a <emphasis>beanName</emphasis>, however its <emphasis>componentName</emphasis> has
|
||||
a value which is useful for logging etc.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
In most other cases, the <emphasis>id</emphasis> will generally be
|
||||
ignored but may still add value for documentation purposes, and may also
|
||||
be used for providing more meaningful log messages.
|
||||
The <emphasis>id</emphasis> attribute for <code><chain></code> elements allows them to be eligible for
|
||||
<link linkend='jmx-mbean-exporter'>JMX export</link> and they are trackable via <link linkend='message-history'>Message History</link>.
|
||||
They can also be accessed from the <interfacename>BeanFactory</interfacename> using the appropriate bean name
|
||||
as discussed above.
|
||||
</para>
|
||||
<note>
|
||||
Currently, the XML Schema of the <emphasis>Spring Integration</emphasis> Core module
|
||||
prevents you from setting the <emphasis>id</emphasis> attribute for
|
||||
Core components within a Message Handler Chain. This may be relaxed in future,
|
||||
to provide the benefits described above.
|
||||
</note>
|
||||
<tip>
|
||||
<para>
|
||||
It is useful to provide an explicit <emphasis>id</emphasis> attribute on <code><chain></code>s
|
||||
to simplify the identification of sub-components in logs, and to provide
|
||||
access to them from the <interfacename>BeanFactory</interfacename> etc.
|
||||
</para>
|
||||
</tip>
|
||||
<para><emphasis>Calling a Chain from within a Chain</emphasis></para>
|
||||
|
||||
<para>
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
please see <xref linkend="jdbc-message-store-generic"/>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<section id="3.0-json-transformers">
|
||||
<title>Jackson Support (JSON)</title>
|
||||
<para>
|
||||
A new abstraction for JSON conversion has been introduced. Implementations for Jackson 1.x
|
||||
@@ -170,6 +170,17 @@
|
||||
may set other headers.
|
||||
</para>
|
||||
</section>
|
||||
<section id="3.0-id-for-chain-sub-components">
|
||||
<title>Chain Elements 'id' Attribute</title>
|
||||
<para>
|
||||
Previously, the <emphasis>id</emphasis> attribute for elements within a <code><chain></code> was
|
||||
ignored and, in some cases, disallowed. Now, the <emphasis>id</emphasis> attribute is allowed
|
||||
for all elements within a <code><chain></code>. The bean names of chain elements is a combination
|
||||
of the surrounding chain's <emphasis>id</emphasis> and the <emphasis>id</emphasis> of the element
|
||||
itself. For example: 'fooChain$child.fooTransformer.handler'.
|
||||
For more information see <xref linkend="chain"/>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user