INT-2998: Channel Adapters' Lifecycle Refactoring
* Add XSD attributeGroup `smartLifeCycleAttributeGroup`
* Use it for all adapters tags
* Refactoring `AbstractChannelAdapterParser` hierarchy
* Refactoring some `MessageHandler`'s that should not have `autoStartup` & `phase`.
It is the responsibility of `AbstrctEndpoint`
* Polishing some tests according new logic
JIRA: https://jira.springsource.org/browse/INT-2998
INT-2998: Polishing
Polishing
- Reformat schemas where indentation changed
- Add SLC to the UDP inbound adapter
This commit is contained in:
committed by
Gary Russell
parent
e8ecbac7fd
commit
f3d3f4ee4b
@@ -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,8 +18,10 @@ package org.springframework.integration.config.xml;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
@@ -30,7 +32,7 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base parser for Channel Adapters.
|
||||
*
|
||||
* <p/>
|
||||
* Includes logic to determine {@link org.springframework.integration.MessageChannel}:
|
||||
* if 'channel' attribute is defined - uses its value as 'channelName';
|
||||
* if 'id' attribute is defined - creates {@link DirectChannel} at runtime and uses id's value as 'channelName';
|
||||
@@ -63,7 +65,17 @@ public abstract class AbstractChannelAdapterParser extends AbstractBeanDefinitio
|
||||
if (!StringUtils.hasText(channelName)) {
|
||||
channelName = this.createDirectChannel(element, parserContext);
|
||||
}
|
||||
return doParse(element, parserContext, channelName);
|
||||
AbstractBeanDefinition beanDefinition = doParse(element, parserContext, channelName);
|
||||
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
|
||||
String autoStartup = element.getAttribute(IntegrationNamespaceUtils.AUTO_STARTUP);
|
||||
if (StringUtils.hasText(autoStartup)) {
|
||||
propertyValues.add("autoStartup", new TypedStringValue(autoStartup));
|
||||
}
|
||||
String phase = element.getAttribute(IntegrationNamespaceUtils.PHASE);
|
||||
if (StringUtils.hasText(phase)) {
|
||||
propertyValues.add("phase", new TypedStringValue(phase));
|
||||
}
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
private String createDirectChannel(Element element, ParserContext parserContext) {
|
||||
|
||||
@@ -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.
|
||||
@@ -19,6 +19,8 @@ package org.springframework.integration.config.xml;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
@@ -34,7 +36,6 @@ import org.springframework.integration.config.ConsumerEndpointFactoryBean;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Base class parser for elements that create Message Endpoints.
|
||||
@@ -96,7 +97,8 @@ public abstract class AbstractConsumerEndpointParser extends AbstractBeanDefinit
|
||||
+ elementDescription + ".", element);
|
||||
}
|
||||
return handlerBeanDefinition;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!hasInputChannelAttribute) {
|
||||
String elementDescription = IntegrationNamespaceUtils.createElementDescription(element);
|
||||
parserContext.getReaderContext().error("The '" + inputChannelAttributeName
|
||||
@@ -115,18 +117,18 @@ public abstract class AbstractConsumerEndpointParser extends AbstractBeanDefinit
|
||||
|
||||
String inputChannelName = element.getAttribute(inputChannelAttributeName);
|
||||
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(inputChannelName)){
|
||||
if (parserContext.getRegistry().containsBeanDefinition(ChannelInitializer.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME)){
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(inputChannelName)) {
|
||||
if (parserContext.getRegistry().containsBeanDefinition(ChannelInitializer.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME)) {
|
||||
BeanDefinition channelRegistry = parserContext.getRegistry().
|
||||
getBeanDefinition(ChannelInitializer.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME);
|
||||
ConstructorArgumentValues caValues = channelRegistry.getConstructorArgumentValues();
|
||||
ValueHolder vh = caValues.getArgumentValue(0, Collection.class);
|
||||
if (vh == null){ //although it should never happen if it does we can fix it
|
||||
if (vh == null) { //although it should never happen if it does we can fix it
|
||||
caValues.addIndexedArgumentValue(0, new ManagedSet<String>());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<String> channelCandidateNames = (Collection<String>) caValues.getArgumentValue(0, Collection.class).getValue();
|
||||
Collection<String> channelCandidateNames = (Collection<String>) caValues.getArgumentValue(0, Collection.class).getValue();
|
||||
channelCandidateNames.add(inputChannelName);
|
||||
}
|
||||
else {
|
||||
@@ -144,7 +146,8 @@ public abstract class AbstractConsumerEndpointParser extends AbstractBeanDefinit
|
||||
}
|
||||
IntegrationNamespaceUtils.configurePollerMetadata(pollerElementList.get(0), builder, parserContext);
|
||||
}
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, IntegrationNamespaceUtils.AUTO_STARTUP);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, IntegrationNamespaceUtils.PHASE);
|
||||
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
|
||||
String beanName = this.resolveId(element, beanDefinition, parserContext);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(beanDefinition, beanName));
|
||||
|
||||
@@ -71,8 +71,6 @@ public abstract class AbstractOutboundChannelAdapterParser extends AbstractChann
|
||||
IntegrationNamespaceUtils.configurePollerMetadata(pollerElement, builder, parserContext);
|
||||
}
|
||||
builder.addPropertyValue("inputChannelName", channelName);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "phase");
|
||||
|
||||
this.configureRequestHandlerAdviceChain(element, parserContext, handlerBeanComponentDefinition.getBeanDefinition(), builder);
|
||||
|
||||
|
||||
@@ -49,8 +49,6 @@ public abstract class AbstractPollingInboundChannelAdapterParser extends Abstrac
|
||||
if (pollerElement != null) {
|
||||
IntegrationNamespaceUtils.configurePollerMetadata(pollerElement, adapterBuilder, parserContext);
|
||||
}
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(adapterBuilder, element, "auto-startup");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(adapterBuilder, element, "phase");
|
||||
return adapterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
||||
@@ -99,8 +99,6 @@ public class ChainParser extends AbstractConsumerEndpointParser {
|
||||
}
|
||||
builder.addPropertyValue("handlers", handlerList);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-timeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "phase");
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@ public abstract class IntegrationNamespaceUtils {
|
||||
static final String EXPRESSION_ATTRIBUTE = "expression";
|
||||
public static final String HANDLER_ALIAS_SUFFIX = ".handler";
|
||||
public static final String REQUEST_HANDLER_ADVICE_CHAIN = "request-handler-advice-chain";
|
||||
public static final String AUTO_STARTUP = "auto-startup";
|
||||
public static final String PHASE = "phase";
|
||||
|
||||
/**
|
||||
* Property name on ChannelInitializer used to configure the default max subscribers for
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
@@ -66,7 +66,7 @@ import org.springframework.util.Assert;
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public class MessageHandlerChain extends AbstractMessageHandler implements MessageProducer, SmartLifecycle {
|
||||
public class MessageHandlerChain extends AbstractMessageHandler implements MessageProducer, Lifecycle {
|
||||
|
||||
private volatile List<MessageHandler> handlers;
|
||||
|
||||
@@ -85,10 +85,6 @@ public class MessageHandlerChain extends AbstractMessageHandler implements Messa
|
||||
|
||||
private final Object initializationMonitor = new Object();
|
||||
|
||||
private volatile boolean autoStartup = true;
|
||||
|
||||
private volatile int phase = Integer.MAX_VALUE;
|
||||
|
||||
private volatile boolean running;
|
||||
|
||||
private final ReentrantLock lifecycleLock = new ReentrantLock();
|
||||
@@ -176,14 +172,6 @@ public class MessageHandlerChain extends AbstractMessageHandler implements Messa
|
||||
* SmartLifecycle implementation (delegates to the {@link #handlers})
|
||||
*/
|
||||
|
||||
public final boolean isAutoStartup() {
|
||||
return this.autoStartup;
|
||||
}
|
||||
|
||||
public final int getPhase() {
|
||||
return this.phase;
|
||||
}
|
||||
|
||||
public final boolean isRunning() {
|
||||
this.lifecycleLock.lock();
|
||||
try {
|
||||
@@ -237,26 +225,18 @@ public class MessageHandlerChain extends AbstractMessageHandler implements Messa
|
||||
}
|
||||
}
|
||||
|
||||
public void setAutoStartup(boolean autoStartup) {
|
||||
this.autoStartup = autoStartup;
|
||||
}
|
||||
|
||||
public void setPhase(int phase) {
|
||||
this.phase = phase;
|
||||
}
|
||||
|
||||
private void doStop() {
|
||||
for (MessageHandler handler : this.handlers) {
|
||||
if (handler instanceof SmartLifecycle) {
|
||||
((SmartLifecycle) handler).stop();
|
||||
if (handler instanceof Lifecycle) {
|
||||
((Lifecycle) handler).stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doStart() {
|
||||
for (MessageHandler handler : this.handlers) {
|
||||
if (handler instanceof SmartLifecycle) {
|
||||
((SmartLifecycle) handler).start();
|
||||
if (handler instanceof Lifecycle) {
|
||||
((Lifecycle) handler).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -877,13 +877,6 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="auto-startup" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Lifecycle attribute signaling if this component should be started during Application Context startup.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="pattern" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -907,6 +900,7 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="smartLifeCycleAttributeGroup"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -1041,23 +1035,7 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="auto-startup" type="xsd:string" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Lifecycle attribute signaling if this component should be started during Application Context startup.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="phase" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
The Lifecycle attribute determining the start/stop order
|
||||
of the underlying MessageHandlerChain.
|
||||
</xsd:documentation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="smartLifeCycleAttributeGroup"/>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:complexType name="methodInvokingChannelAdapterType">
|
||||
@@ -1552,16 +1530,6 @@
|
||||
<xsd:group ref="chain-elements-group" maxOccurs="unbounded"/>
|
||||
</xsd:choice>
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
<xsd:attribute name="phase" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
The Lifecycle attribute determining the start/stop order
|
||||
of the underlying MessageHandlerChain.
|
||||
</xsd:documentation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
@@ -3066,17 +3034,6 @@
|
||||
-->
|
||||
|
||||
<xsd:attributeGroup name="topLevelRouterAttributeGroup">
|
||||
<xsd:attribute name="auto-startup" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Lifecycle attribute signaling if this component should be
|
||||
started during Application Context startup. Defaults to true.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="input-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
@@ -3099,6 +3056,7 @@
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="smartLifeCycleAttributeGroup"/>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<!--
|
||||
@@ -4025,17 +3983,7 @@ endpoint itself is a Polling Consumer for a channel with a queue.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="auto-startup" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Lifecycle attribute signaling if this component should be
|
||||
started during Application Context startup. Defaults to true.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="smartLifeCycleAttributeGroup"/>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:attributeGroup name="subscribersAttributeGroup">
|
||||
@@ -4117,4 +4065,24 @@ endpoint itself is a Polling Consumer for a channel with a queue.
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:attributeGroup name="smartLifeCycleAttributeGroup">
|
||||
<xsd:attribute name="auto-startup" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Boolean value indicating whether this endpoint should start automatically.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="phase" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The lifecycle phase within which this endpoint should start and stop.
|
||||
The lower the value the earlier this endpoint will start and the later it will stop. The
|
||||
default is 0. Values can be negative. See SmartLifeCycle.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
</xsd:schema>
|
||||
|
||||
@@ -53,6 +53,7 @@ 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.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.gateway.GatewayProxyFactoryBean;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.handler.LoggingHandler;
|
||||
@@ -335,9 +336,11 @@ public class ChainParserTests {
|
||||
@Test //INT-2605
|
||||
public void checkSmartLifecycleConfig() {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("ChainParserSmartLifecycleAttributesTest.xml", this.getClass());
|
||||
MessageHandlerChain handlerChain = ctx.getBean(MessageHandlerChain.class);
|
||||
assertEquals(false, handlerChain.isAutoStartup());
|
||||
assertEquals(256, handlerChain.getPhase());
|
||||
AbstractEndpoint chainEndpoint = ctx.getBean("chain", AbstractEndpoint.class);
|
||||
assertEquals(false, chainEndpoint.isAutoStartup());
|
||||
assertEquals(256, chainEndpoint.getPhase());
|
||||
|
||||
MessageHandlerChain handlerChain = ctx.getBean("chain.handler", MessageHandlerChain.class);
|
||||
assertEquals(3000L, TestUtils.getPropertyValue(handlerChain, "sendTimeout"));
|
||||
assertEquals(false, TestUtils.getPropertyValue(handlerChain, "running"));
|
||||
//INT-3108
|
||||
|
||||
Reference in New Issue
Block a user