Refactored channel adapter parsing to accommodate recent adapter changes.

This commit is contained in:
Mark Fisher
2008-01-02 16:55:56 +00:00
parent acd86b863a
commit 0377856bd1
10 changed files with 105 additions and 12 deletions

View File

@@ -43,6 +43,7 @@ public class DefaultTargetAdapter implements TargetAdapter {
public DefaultTargetAdapter(Target target) {
Assert.notNull(target, "'target' must not be null");
this.target = target;
}

View File

@@ -182,6 +182,9 @@ public class MessageBus implements ChannelRegistry, ApplicationContextAware, Lif
ConsumerPolicy policy = adapter.getConsumerPolicy();
DispatcherTask dispatcherTask = new DispatcherTask((MessageDispatcher) adapter, policy);
this.addDispatcherTask(dispatcherTask);
if (logger.isInfoEnabled()) {
logger.info("registered source adapter '" + name + "'");
}
}
}

View File

@@ -44,6 +44,10 @@ public class ChannelAdapterParser implements BeanDefinitionParser {
private static final String METHOD_ATTRIBUTE = "method";
private static final String CHANNEL_ATTRIBUTE = "channel";
private static final String PERIOD_ATTRIBUTE = "period";
private final boolean isInbound;
@@ -56,14 +60,25 @@ public class ChannelAdapterParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
String ref = element.getAttribute(REF_ATTRIBUTE);
String method = element.getAttribute(METHOD_ATTRIBUTE);
if (!StringUtils.hasText(ref) || !StringUtils.hasText(method)) {
throw new MessagingConfigurationException("'ref' and 'method' are both required");
String channel = element.getAttribute(CHANNEL_ATTRIBUTE);
if (!StringUtils.hasText(ref)) {
throw new MessagingConfigurationException("'ref' is required");
}
if (!StringUtils.hasText(method)) {
throw new MessagingConfigurationException("'method' is required");
}
if (!StringUtils.hasText(channel)) {
throw new MessagingConfigurationException("'channel' is required");
}
RootBeanDefinition adapterDef = null;
RootBeanDefinition invokerDef = null;
if (this.isInbound) {
adapterDef = new RootBeanDefinition(PollingSourceAdapter.class);
invokerDef = new RootBeanDefinition(MethodInvokingSource.class);
String period = element.getAttribute(PERIOD_ATTRIBUTE);
if (StringUtils.hasText(period)) {
adapterDef.getPropertyValues().addPropertyValue("period", period);
}
}
else {
adapterDef = new RootBeanDefinition(DefaultTargetAdapter.class);
@@ -74,6 +89,7 @@ public class ChannelAdapterParser implements BeanDefinitionParser {
String invokerBeanName = parserContext.getReaderContext().generateBeanName(invokerDef);
parserContext.registerBeanComponent(new BeanComponentDefinition(invokerDef, invokerBeanName));
adapterDef.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(invokerBeanName));
adapterDef.getPropertyValues().addPropertyValue("channel", new RuntimeBeanReference(channel));
adapterDef.setSource(parserContext.extractSource(element));
String beanName = element.getAttribute(ID_ATTRIBUTE);
if (!StringUtils.hasText(beanName)) {

View File

@@ -29,8 +29,8 @@ public class IntegrationNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("message-bus", new MessageBusParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenParser());
registerBeanDefinitionParser("channel", new ChannelParser());
registerBeanDefinitionParser("inbound-channel-adapter", new ChannelAdapterParser(true));
registerBeanDefinitionParser("outbound-channel-adapter", new ChannelAdapterParser(false));
registerBeanDefinitionParser("source-adapter", new ChannelAdapterParser(true));
registerBeanDefinitionParser("target-adapter", new ChannelAdapterParser(false));
registerBeanDefinitionParser("endpoint", new EndpointParser());
}

View File

@@ -54,33 +54,36 @@
</xsd:complexType>
</xsd:element>
<xsd:element name="inbound-channel-adapter">
<xsd:element name="source-adapter">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines an inbound channel adapter.
Defines a source (inbound) channel adapter.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="ref" type="xsd:string" use="required"/>
<xsd:attribute name="method" type="xsd:string" use="required"/>
<xsd:attribute name="channel" type="xsd:string" use="required"/>
<xsd:attribute name="period" type="xsd:int"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="outbound-channel-adapter">
<xsd:element name="target-adapter">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines an outbound channel adapter.
Defines a target (outbound) channel adapter.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="ref" type="xsd:string" use="required"/>
<xsd:attribute name="method" type="xsd:string" use="required"/>
<xsd:attribute name="channel" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

View File

@@ -51,6 +51,10 @@ public abstract class AbstractMessageHandlerAdapter<T> implements MessageHandler
private int order = Integer.MAX_VALUE;
private volatile boolean initialized;
private Object lifecycleMonitor = new Object();
public void setObject(T object) {
Assert.notNull(object, "'object' must not be null");
@@ -88,7 +92,17 @@ public abstract class AbstractMessageHandlerAdapter<T> implements MessageHandler
}
public final void afterPropertiesSet() {
this.invoker = new SimpleMethodInvoker<T>(this.object, this.methodName);
this.validate();
synchronized (this.lifecycleMonitor) {
this.invoker = new SimpleMethodInvoker<T>(this.object, this.methodName);
this.initialized = true;
}
}
public final boolean isInitialized() {
synchronized (this.lifecycleMonitor) {
return this.initialized;
}
}
public final Message<?> handle(Message<?> message) {
@@ -102,6 +116,12 @@ public abstract class AbstractMessageHandlerAdapter<T> implements MessageHandler
return null;
}
/**
* Subclasses may override this method to provide validation upon initialization.
*/
protected void validate() {
}
/**
* Subclasses must implement this method. The invoker has been created for
* the provided target object and method. May return an object of type

View File

@@ -28,6 +28,7 @@ import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.handler.AbstractMessageHandlerAdapter;
import org.springframework.integration.message.Message;
import org.springframework.integration.util.SimpleMethodInvoker;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@@ -50,7 +51,11 @@ public class RouterMessageHandlerAdapter extends AbstractMessageHandlerAdapter i
public RouterMessageHandlerAdapter(Object object, Method method, Map<String, ?> attributes) {
Assert.notNull(object, "'object' must not be null");
Assert.notNull(method, "'method' must not be null");
Assert.notNull(attributes, "'attributes' must not be null");
this.setObject(object);
this.setMethodName(method.getName());
this.method = method;
this.attributes = attributes;
}
@@ -61,6 +66,9 @@ public class RouterMessageHandlerAdapter extends AbstractMessageHandlerAdapter i
@Override
protected Object doHandle(Message message, SimpleMethodInvoker invoker) {
if (!this.isInitialized()) {
this.afterPropertiesSet();
}
if (method.getParameterTypes().length != 1) {
throw new MessagingConfigurationException(
"method must accept exactly one parameter");