Refactored the ChannelAdapterParser to MethodInvokingInboundChannelAdapterParser. MethodInvokingOutboundChannelAdapterParser had already been committed. The namespace now defines "inbound-channel-adapter" and "outbound-channel-adapter" elements instead of using "channel-adapter" for both.

This commit is contained in:
Mark Fisher
2008-09-24 01:42:28 +00:00
parent bc91df7db6
commit 6655511d3d
5 changed files with 77 additions and 108 deletions

View File

@@ -1,96 +0,0 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.config;
import org.w3c.dom.Element;
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.xml.ParserContext;
import org.springframework.integration.ConfigurationException;
import org.springframework.integration.endpoint.OutboundChannelAdapter;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.message.MethodInvokingConsumer;
import org.springframework.integration.message.MethodInvokingSource;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
/**
* Parser for the <channel-adapter/> element.
*
* @author Mark Fisher
*/
public class ChannelAdapterParser extends AbstractChannelAdapterParser {
@Override
protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) {
String source = element.getAttribute("source");
String target = element.getAttribute("target");
String methodName = element.getAttribute("method");
Element pollerElement = DomUtils.getChildElementByTagName(element, "poller");
BeanDefinitionBuilder adapterBuilder = null;
if (StringUtils.hasText(source)) {
if (StringUtils.hasText(target)) {
throw new ConfigurationException("both 'source' and 'target' are not allowed, provide only one");
}
if (StringUtils.hasText(methodName)) {
BeanDefinitionBuilder invokerBuilder = BeanDefinitionBuilder.genericBeanDefinition(MethodInvokingSource.class);
invokerBuilder.addPropertyReference("object", source);
invokerBuilder.addPropertyValue("methodName", methodName);
source = BeanDefinitionReaderUtils.registerWithGeneratedName(invokerBuilder.getBeanDefinition(), parserContext.getRegistry());
}
adapterBuilder = BeanDefinitionBuilder.genericBeanDefinition(SourcePollingChannelAdapter.class);
adapterBuilder.addPropertyReference("source", source);
adapterBuilder.addPropertyReference("outputChannel", channelName);
if (pollerElement != null) {
IntegrationNamespaceUtils.configureSchedule(pollerElement, adapterBuilder);
IntegrationNamespaceUtils.setValueIfAttributeDefined(adapterBuilder, pollerElement, "max-messages-per-poll");
Element txElement = DomUtils.getChildElementByTagName(pollerElement, "transactional");
if (txElement != null) {
IntegrationNamespaceUtils.configureTransactionAttributes(txElement, adapterBuilder);
}
}
}
else if (StringUtils.hasText(target)) {
if (StringUtils.hasText(methodName)) {
BeanDefinitionBuilder invokerBuilder = BeanDefinitionBuilder.genericBeanDefinition(MethodInvokingConsumer.class);
invokerBuilder.addConstructorArgReference(target);
invokerBuilder.addConstructorArgValue(methodName);
target = BeanDefinitionReaderUtils.registerWithGeneratedName(invokerBuilder.getBeanDefinition(), parserContext.getRegistry());
}
adapterBuilder = BeanDefinitionBuilder.genericBeanDefinition(OutboundChannelAdapter.class);
adapterBuilder.addConstructorArgReference(target);
if (pollerElement != null) {
if (!StringUtils.hasText(channelName)) {
throw new ConfigurationException("outbound channel-adapter with a 'poller' requires a 'channel' to poll");
}
IntegrationNamespaceUtils.configureSchedule(pollerElement, adapterBuilder);
Element txElement = DomUtils.getChildElementByTagName(pollerElement, "transactional");
if (txElement != null) {
IntegrationNamespaceUtils.configureTransactionAttributes(txElement, adapterBuilder);
}
}
adapterBuilder.addPropertyReference("inputChannel", channelName);
}
else {
throw new ConfigurationException("either 'source' or 'target' is required");
}
return adapterBuilder.getBeanDefinition();
}
}

View File

@@ -35,14 +35,15 @@ public class IntegrationNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("thread-local-channel", new ThreadLocalChannelParser());
registerBeanDefinitionParser("publish-subscribe-channel", new PublishSubscribeChannelParser());
registerBeanDefinitionParser("service-activator", new ServiceActivatorParser());
registerBeanDefinitionParser("channel-adapter", new ChannelAdapterParser());
registerBeanDefinitionParser("gateway", new GatewayParser());
registerBeanDefinitionParser("selector-chain", new SelectorChainParser());
registerBeanDefinitionParser("transformer", new TransformerParser());
registerBeanDefinitionParser("router", new RouterParser());
registerBeanDefinitionParser("splitter", new SplitterParser());
registerBeanDefinitionParser("aggregator", new AggregatorParser());
registerBeanDefinitionParser("resequencer", new ResequencerParser());
registerBeanDefinitionParser("inbound-channel-adapter", new MethodInvokingInboundChannelAdapterParser());
registerBeanDefinitionParser("outbound-channel-adapter", new MethodInvokingOutboundChannelAdapterParser());
registerBeanDefinitionParser("gateway", new GatewayParser());
registerBeanDefinitionParser("selector-chain", new SelectorChainParser());
registerBeanDefinitionParser("pool-executor", new PoolExecutorParser());
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.message.MethodInvokingSource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Parser for the <inbound-channel-adapter/> element.
*
* @author Mark Fisher
*/
public class MethodInvokingInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser {
@Override
protected String parseSource(Element element, ParserContext parserContext) {
String source = element.getAttribute("source");
Assert.hasText(source, "The 'source' attribute is required.");
String methodName = element.getAttribute("method");
if (StringUtils.hasText(methodName)) {
BeanDefinitionBuilder invokerBuilder = BeanDefinitionBuilder.genericBeanDefinition(MethodInvokingSource.class);
invokerBuilder.addPropertyReference("object", source);
invokerBuilder.addPropertyValue("methodName", methodName);
source = BeanDefinitionReaderUtils.registerWithGeneratedName(
invokerBuilder.getBeanDefinition(), parserContext.getRegistry());
}
return source;
}
}

View File

@@ -163,23 +163,37 @@
</xsd:complexType>
</xsd:element>
<xsd:element name="channel-adapter">
<xsd:element name="inbound-channel-adapter">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a Channel Adapter that is capable of either receiving from a MessageSource and sending
the result to a MessageChannel or receiving from a MessageChannel and sending the result to a
MessageTarget. Therefore, either "source" or "target" should be provided (but never both).
Defines a Channel Adapter that receives from a MessageSource and sends to a MessageChannel.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element ref="poller" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="channel" type="xsd:string"/>
<xsd:attribute name="source" type="xsd:string"/>
<xsd:attribute name="method" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="outbound-channel-adapter">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a Channel Adapter that receives from a MessageChannel and sends to a MessageConsumer.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element ref="poller" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="channel" type="xsd:string"/>
<xsd:attribute name="target" type="xsd:string"/>
<xsd:attribute name="method" type="xsd:string"/>
<xsd:attribute name="channel" type="xsd:string"/>
</xsd:complexType>
</xsd:element>

View File

@@ -13,13 +13,13 @@
<queue capacity="10"/>
</channel>
<channel-adapter id="outboundWithImplicitChannel" target="consumer"/>
<outbound-channel-adapter id="outboundWithImplicitChannel" target="consumer"/>
<channel-adapter id="methodInvokingConsumer" target="testBean" method="store"/>
<outbound-channel-adapter id="methodInvokingConsumer" target="testBean" method="store"/>
<channel-adapter id="methodInvokingSource" source="testBean" method="getMessage" channel="queueChannel">
<inbound-channel-adapter id="methodInvokingSource" source="testBean" method="getMessage" channel="queueChannel">
<poller period="10000" max-messages-per-poll="1"/>
</channel-adapter>
</inbound-channel-adapter>
<beans:bean id="consumer" class="org.springframework.integration.config.TestConsumer"/>