The <channel/> element is now used for creating all Point-to-Point channel types. It accepts a queue sub-element (options are: <queue/>, <priority-queue/>, or <rendezvous-queue/>). If no queue sub-element is provided, the channel type will be a DirectChannel.

This commit is contained in:
Mark Fisher
2008-09-01 22:50:56 +00:00
parent a27ae5726e
commit 788b2364ec
56 changed files with 442 additions and 358 deletions

View File

@@ -32,15 +32,18 @@ import org.springframework.integration.message.MessagePriority;
*/
public class PriorityChannel extends QueueChannel {
private static final int DEFAULT_MAX_CAPACITY = Integer.MAX_VALUE;
private final Semaphore semaphore;
/**
* Create a channel with the specified queue capacity.
* Priority will be based upon the provided {@link Comparator}.
* Priority will be determined by the provided {@link Comparator}.
*/
public PriorityChannel(int capacity, Comparator<Message<?>> comparator) {
super(new PriorityBlockingQueue<Message<?>>(capacity, comparator));
super(new PriorityBlockingQueue<Message<?>>(11, comparator));
this.semaphore = new Semaphore(capacity, true);
}
@@ -53,11 +56,19 @@ public class PriorityChannel extends QueueChannel {
}
/**
* Create a channel with the default queue capacity and dispatcher policy.
* Create a channel with the default queue capacity of {@link Integer#MAX_VALUE}.
* Priority will be determined by the provided {@link Comparator}.
*/
public PriorityChannel(Comparator<Message<?>> comparator) {
this(DEFAULT_MAX_CAPACITY, comparator);
}
/**
* Create a channel with the default queue capacity of {@link Integer#MAX_VALUE}.
* Priority will be based on the value of {@link MessageHeader#getPriority()}.
*/
public PriorityChannel() {
this(DEFAULT_CAPACITY, new MessagePriorityComparator());
this(DEFAULT_MAX_CAPACITY, new MessagePriorityComparator());
}

View File

@@ -37,9 +37,6 @@ import org.springframework.util.Assert;
*/
public class QueueChannel extends AbstractPollableChannel {
public static final int DEFAULT_CAPACITY = 100;
private final BlockingQueue<Message<?>> queue;
@@ -61,11 +58,12 @@ public class QueueChannel extends AbstractPollableChannel {
}
/**
* Create a channel with the default queue capacity.
* @see #DEFAULT_CAPACITY
* Create a channel with "unbounded" queue capacity. The actual capacity value is
* {@link Integer#MAX_VALUE}. Note that a bounded queue is recommended, since an
* unbounded queue may lead to OutOfMemoryErrors.
*/
public QueueChannel() {
this(DEFAULT_CAPACITY);
this(new LinkedBlockingQueue<Message<?>>());
}

View File

@@ -17,44 +17,36 @@
package org.springframework.integration.config;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.channel.interceptor.MessageSelectingInterceptor;
import org.springframework.integration.message.selector.PayloadTypeSelector;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
/**
* Base class for channel parsers.
*
* @author Mark Fisher
*/
public abstract class AbstractChannelParser extends AbstractSingleBeanDefinitionParser {
@Override
protected abstract Class<?> getBeanClass(Element element);
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
}
public abstract class AbstractChannelParser extends AbstractBeanDefinitionParser {
@Override
@SuppressWarnings("unchecked")
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = this.buildBeanDefinition(element, parserContext);
ManagedList interceptors = null;
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node child = childNodes.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE && child.getLocalName().equals("interceptors")) {
ChannelInterceptorParser interceptorParser = new ChannelInterceptorParser();
interceptors = interceptorParser.parseInterceptors((Element) child, parserContext);
}
Element interceptorsElement = DomUtils.getChildElementByTagName(element, "interceptors");
if (interceptorsElement != null) {
ChannelInterceptorParser interceptorParser = new ChannelInterceptorParser();
interceptors = interceptorParser.parseInterceptors(interceptorsElement, parserContext);
}
if (interceptors == null) {
interceptors = new ManagedList();
@@ -75,7 +67,16 @@ public abstract class AbstractChannelParser extends AbstractSingleBeanDefinition
interceptors.add(new RuntimeBeanReference(interceptorBeanName));
}
builder.addPropertyValue("interceptors", interceptors);
this.postProcess(builder, element);
return builder.getBeanDefinition();
}
/**
* Subclasses must implement this method to create the bean definition.
* The class must be defined, and any implementation-specific constructor
* arguments or properties should be configured. This base class will
* configure the interceptors including the 'datatype' interceptor if
* the 'datatype' attribute is defined on the channel element.
*/
protected abstract BeanDefinitionBuilder buildBeanDefinition(Element element, ParserContext parserContext);
}

View File

@@ -1,35 +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.integration.channel.DirectChannel;
/**
* Parser for the &lt;direct-channel&gt; element.
*
* @author Mark Fisher
*/
public class DirectChannelParser extends AbstractChannelParser {
@Override
protected Class<?> getBeanClass(Element element) {
return DirectChannel.class;
}
}

View File

@@ -49,13 +49,13 @@ public class IntegrationNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("message-bus", new MessageBusParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenParser());
registerBeanDefinitionParser("channel", new QueueChannelParser());
registerBeanDefinitionParser("queue-channel", new QueueChannelParser());
registerBeanDefinitionParser("publish-subscribe-channel", new PublishSubscribeChannelParser());
registerBeanDefinitionParser("direct-channel", new DirectChannelParser());
registerBeanDefinitionParser("priority-channel", new PriorityChannelParser());
registerBeanDefinitionParser("rendezvous-channel", new RendezvousChannelParser());
registerBeanDefinitionParser("channel", new PointToPointChannelParser());
registerBeanDefinitionParser("queue-channel", new PointToPointChannelParser());
registerBeanDefinitionParser("direct-channel", new PointToPointChannelParser());
registerBeanDefinitionParser("priority-channel", new PointToPointChannelParser());
registerBeanDefinitionParser("rendezvous-channel", new PointToPointChannelParser());
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());

View File

@@ -0,0 +1,74 @@
/*
* 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.xml.ParserContext;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.PriorityChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.channel.RendezvousChannel;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
/**
* Parser for the &lt;channel&gt; element.
*
* @author Mark Fisher
*/
public class PointToPointChannelParser extends AbstractChannelParser {
private static final String CAPACITY_ATTRIBUTE = "capacity";
@Override
protected BeanDefinitionBuilder buildBeanDefinition(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = null;
Element queueElement = null;
if ((queueElement = DomUtils.getChildElementByTagName(element, "queue")) != null) {
builder = BeanDefinitionBuilder.genericBeanDefinition(QueueChannel.class);
this.parseQueueCapacity(builder, queueElement);
}
else if ((queueElement = DomUtils.getChildElementByTagName(element, "priority-queue")) != null) {
builder = BeanDefinitionBuilder.genericBeanDefinition(PriorityChannel.class);
this.parseQueueCapacity(builder, queueElement);
String comparatorRef = queueElement.getAttribute("comparator");
if (StringUtils.hasText(comparatorRef)) {
builder.addConstructorArgReference(comparatorRef);
}
}
else if ((queueElement = DomUtils.getChildElementByTagName(element, "rendezvous-queue")) != null) {
builder = BeanDefinitionBuilder.genericBeanDefinition(RendezvousChannel.class);
}
else {
builder = BeanDefinitionBuilder.genericBeanDefinition(DirectChannel.class);
}
return builder;
}
private void parseQueueCapacity(BeanDefinitionBuilder builder, Element queueElement) {
String capacity = queueElement.getAttribute(CAPACITY_ATTRIBUTE);
if (StringUtils.hasText(capacity)) {
if (!capacity.equals("UNBOUNDED")) {
builder.addConstructorArgValue(Integer.valueOf(capacity));
}
}
}
}

View File

@@ -1,46 +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.BeanDefinitionBuilder;
import org.springframework.integration.channel.PriorityChannel;
import org.springframework.util.StringUtils;
/**
* Parser for the &lt;priority-channel&gt; element.
*
* @author Mark Fisher
*/
public class PriorityChannelParser extends QueueChannelParser {
@Override
protected Class<?> getBeanClass(Element element) {
return PriorityChannel.class;
}
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
super.postProcess(builder, element);
String comparator = element.getAttribute("comparator");
if (StringUtils.hasText(comparator)) {
builder.addConstructorArgReference(comparator);
}
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.integration.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.util.StringUtils;
@@ -30,17 +31,14 @@ import org.springframework.util.StringUtils;
public class PublishSubscribeChannelParser extends AbstractChannelParser {
@Override
protected Class<?> getBeanClass(Element element) {
return PublishSubscribeChannel.class;
}
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
protected BeanDefinitionBuilder buildBeanDefinition(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(PublishSubscribeChannel.class);
String taskExecutorRef = element.getAttribute("task-executor");
if (StringUtils.hasText(taskExecutorRef)) {
builder.addConstructorArgReference(taskExecutorRef);
}
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "apply-sequence");
return builder;
}
}

View File

@@ -1,45 +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.BeanDefinitionBuilder;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.util.StringUtils;
/**
* Parser for the &lt;queue-channel&gt; element.
*
* @author Mark Fisher
*/
public class QueueChannelParser extends AbstractChannelParser {
@Override
protected Class<?> getBeanClass(Element element) {
return QueueChannel.class;
}
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
String capacityAttribute = element.getAttribute("capacity");
int capacity = (StringUtils.hasText(capacityAttribute)) ?
Integer.parseInt(capacityAttribute) : QueueChannel.DEFAULT_CAPACITY;
builder.addConstructorArgValue(capacity);
}
}

View File

@@ -1,35 +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.integration.channel.RendezvousChannel;
/**
* Parser for the &lt;rendezvous-channel&gt; element.
*
* @author Mark Fisher
*/
public class RendezvousChannelParser extends AbstractChannelParser {
@Override
protected Class<?> getBeanClass(Element element) {
return RendezvousChannel.class;
}
}

View File

@@ -18,6 +18,8 @@ package org.springframework.integration.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.channel.ThreadLocalChannel;
/**
@@ -28,8 +30,8 @@ import org.springframework.integration.channel.ThreadLocalChannel;
public class ThreadLocalChannelParser extends AbstractChannelParser {
@Override
protected Class<?> getBeanClass(Element element) {
return ThreadLocalChannel.class;
protected BeanDefinitionBuilder buildBeanDefinition(Element element, ParserContext parserContext) {
return BeanDefinitionBuilder.genericBeanDefinition(ThreadLocalChannel.class);
}
}

View File

@@ -47,32 +47,86 @@
</xsd:complexType>
</xsd:element>
<xsd:element name="channel" type="channelType">
<xsd:element name="channel">
<xsd:annotation>
<xsd:documentation>
Defines a generic channel type. The actual channel type
will be determined by the channel factory set on the message bus.
Defines a Point-to-Point MessageChannel.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="channelType">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element ref="queue"/>
<xsd:element ref="priority-queue"/>
<xsd:element ref="rendezvous-queue"/>
</xsd:choice>
<xsd:element name="interceptors" type="channelInterceptorsType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="queue-channel" type="capacityChannelType">
<xsd:annotation>
<xsd:documentation>
Defines a channel that buffers messages in a queue.
</xsd:documentation>
</xsd:annotation>
<xsd:element name="queue">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a bounded queue for messages.
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="capacity" use="required">
<xsd:simpleType>
<xsd:union>
<xsd:simpleType>
<xsd:restriction base="xsd:integer"/>
</xsd:simpleType>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="UNBOUNDED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:union>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="priority-queue">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a queue with priority-ordering for message reception.
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="capacity" type="xsd:integer" use="required"/>
<xsd:attribute name="comparator" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="rendezvous-queue">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a rendezvous queue where a sender will block until the receiver arrives or vice-versa.
</xsd:documentation>
</xsd:annotation>
</xsd:complexType>
</xsd:element>
<xsd:element name="publish-subscribe-channel">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a publish-subscribe channel that broadcasts to its targets.
Defines a Publish-Subscribe channel that broadcasts messages to its subscribers.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="channelType">
<xsd:sequence>
<xsd:element name="interceptors" type="channelInterceptorsType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="task-executor" type="xsd:string"/>
<xsd:attribute name="apply-sequence" type="xsd:string"/>
</xsd:extension>
@@ -80,55 +134,14 @@
</xsd:complexType>
</xsd:element>
<xsd:element name="direct-channel" type="channelType">
<xsd:annotation>
<xsd:documentation>
Defines a channel that invokes its handlers directly in the sender's thread.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="priority-channel">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a channel with priority-ordering for message reception.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="capacityChannelType">
<xsd:attribute name="comparator" type="xsd:string"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="rendezvous-channel" type="channelType"/>
<xsd:element name="thread-local-channel" type="channelType"/>
<xsd:complexType name="capacityChannelType">
<xsd:annotation>
<xsd:documentation>
Defines a channel with a configurable capacity.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="channelType">
<xsd:attribute name="capacity" type="xsd:integer"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="channelType">
<xsd:annotation>
<xsd:documentation>
Defines a message channel.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="interceptors" type="channelInterceptorsType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" use="required"/>
<xsd:attribute name="datatype" type="xsd:string"/>
</xsd:complexType>

View File

@@ -17,6 +17,7 @@
package org.springframework.integration.dispatcher;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageDeliveryException;
import org.springframework.integration.message.MessageRejectedException;
import org.springframework.integration.message.MessageTarget;
@@ -25,9 +26,10 @@ import org.springframework.integration.message.MessageTarget;
* to send a {@link Message} to one of its targets. As soon as <em>one</em>
* of the targets accepts the Message, the dispatcher will return 'true'.
* <p>
* If all targets reject the Message, the dispatcher will throw a
* MessageRejectedException. If all targets return 'false' (e.g. due
* to a timeout), the dispatcher will return 'false'.
* If the dispatcher has no targets, a {@link MessageDeliveryException}
* will be thrown. If all targets reject the Message, the dispatcher will
* throw a MessageRejectedException. If all targets return 'false'
* (e.g. due to a timeout), the dispatcher will return 'false'.
*
* @author Mark Fisher
*/
@@ -35,10 +37,7 @@ public class SimpleDispatcher extends AbstractDispatcher {
public boolean send(Message<?> message) {
if (this.targets.size() == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Dispatcher has no targets.");
}
return false;
throw new MessageDeliveryException(message, "Dispatcher has no targets.");
}
int count = 0;
int rejectedExceptionCount = 0;

View File

@@ -36,7 +36,7 @@ public interface MessageTarget {
* @throws MessageRejectedException if this particular Message is not accepted by the target
* (e.g. after consulting a {@link org.springframework.integration.message.selector.MessageSelector})
* @throws MessageDeliveryException if this target is unable to send the Message due
* to a transport error
* to a transport error.
*/
boolean send(Message<?> message) throws MessageRejectedException, MessageDeliveryException;

View File

@@ -26,10 +26,10 @@ import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.FatalBeanException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.TestChannelInterceptor;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.Message;
@@ -61,13 +61,11 @@ public class ChannelParserTests {
}
@Test
public void testQueueChannelByDefault() throws InterruptedException {
public void testDirectChannelByDefault() throws InterruptedException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"channelParserTests.xml", this.getClass());
MessageChannel channel = (MessageChannel) context.getBean("queueChannelByDefault");
//called to initialize the channel instance
channel.getName();
assertEquals(QueueChannel.class, channel.getClass());
MessageChannel channel = (MessageChannel) context.getBean("defaultChannel");
assertEquals(DirectChannel.class, channel.getClass());
}
@Test

View File

@@ -8,12 +8,14 @@
http://www.springframework.org/schema/integration/spring-integration-core-1.0.xsd">
<channel id="channelWithInterceptorRef">
<queue capacity="5"/>
<interceptors>
<ref bean="interceptor"/>
</interceptors>
</channel>
<channel id="channelWithInterceptorInnerBean">
<queue capacity="5"/>
<interceptors>
<beans:bean class="org.springframework.integration.transformer.MessageTransformingChannelInterceptor">
<beans:constructor-arg>

View File

@@ -7,20 +7,28 @@
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-core-1.0.xsd">
<queue-channel id="capacityChannel" capacity="10"/>
<channel id="capacityChannel">
<queue capacity="10"/>
</channel>
<channel id="queueChannelByDefault"/>
<channel id="defaultChannel"/>
<publish-subscribe-channel id="publishSubscribeChannel"/>
<publish-subscribe-channel id="publishSubscribeChannelWithTaskExecutorRef"
task-executor="taskExecutor"/>
<channel id="integerChannel" datatype="java.lang.Integer"/>
<channel id="integerChannel" datatype="java.lang.Integer">
<queue capacity="10"/>
</channel>
<channel id="numberChannel" datatype="java.lang.Number"/>
<channel id="numberChannel" datatype="java.lang.Number">
<queue capacity="10"/>
</channel>
<channel id="stringOrNumberChannel" datatype="java.lang.String,java.lang.Number"/>
<channel id="stringOrNumberChannel" datatype="java.lang.String,java.lang.Number">
<queue capacity="10"/>
</channel>
<beans:bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>

View File

@@ -7,11 +7,17 @@
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-core-1.0.xsd">
<priority-channel id="priorityChannelWithDefaultComparator"/>
<channel id="priorityChannelWithDefaultComparator">
<priority-queue capacity="10"/>
</channel>
<priority-channel id="priorityChannelWithCustomComparator" comparator="payloadComparator"/>
<channel id="priorityChannelWithCustomComparator">
<priority-queue capacity="10" comparator="payloadComparator"/>
</channel>
<priority-channel id="integerOnlyPriorityChannel" datatype="java.lang.Integer" comparator="payloadComparator"/>
<channel id="integerOnlyPriorityChannel" datatype="java.lang.Integer">
<priority-queue capacity="10" comparator="payloadComparator"/>
</channel>
<beans:bean id="payloadComparator"
class="org.springframework.integration.channel.MessagePayloadTestComparator"/>

View File

@@ -7,6 +7,8 @@
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-core-1.0.xsd">
<rendezvous-channel id="channel"/>
<channel id="channel">
<rendezvous-queue/>
</channel>
</beans:beans>

View File

@@ -7,6 +7,6 @@
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-core-1.0.xsd">
<direct-channel id="channel"/>
<channel id="channel"/>
</beans:beans>

View File

@@ -9,7 +9,9 @@
<message-bus auto-startup="false"/>
<queue-channel id="queueChannel" capacity="10"/>
<channel id="queueChannel">
<queue capacity="10"/>
</channel>
<channel-adapter id="outboundWithImplicitChannel" target="target"/>

View File

@@ -17,6 +17,7 @@
package org.springframework.integration.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
@@ -24,6 +25,7 @@ import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.endpoint.EndpointInterceptor;
import org.springframework.integration.endpoint.MessageEndpoint;
import org.springframework.integration.message.StringMessage;
@@ -52,21 +54,24 @@ public class EndpointInterceptorTests {
@SuppressWarnings("unchecked")
private static void testInterceptors(MessageEndpoint endpoint, ClassPathXmlApplicationContext context, boolean innerBeans) {
MessageChannel channel = null;
TestPreHandleInterceptor preInterceptor = null;
TestPostHandleInterceptor postInterceptor = null;
if (innerBeans) {
channel = (MessageChannel) context.getBean("inputChannelForBeans");
DirectFieldAccessor accessor = new DirectFieldAccessor(endpoint);
List<EndpointInterceptor> interceptors = (List<EndpointInterceptor>) accessor.getPropertyValue("interceptors");
preInterceptor = (TestPreHandleInterceptor) interceptors.get(0);
postInterceptor = (TestPostHandleInterceptor) interceptors.get(1);
}
else {
channel = (MessageChannel) context.getBean("inputChannelForRefs");
preInterceptor = (TestPreHandleInterceptor) context.getBean("preInterceptor");
postInterceptor = (TestPostHandleInterceptor) context.getBean("postInterceptor");
}
assertEquals(0, preInterceptor.getCount());
assertEquals(0, postInterceptor.getCount());
endpoint.send(new StringMessage("test"));
assertTrue(channel.send(new StringMessage("test")));
assertEquals(1, preInterceptor.getCount());
assertEquals(1, postInterceptor.getCount());
context.stop();

View File

@@ -10,8 +10,12 @@
<message-bus/>
<channel id="inputChannel"/>
<channel id="outputChannel"/>
<channel id="discardChannel"/>
<channel id="outputChannel">
<queue capacity="5"/>
</channel>
<channel id="discardChannel">
<queue capacity="5"/>
</channel>
<aggregator id="aggregatorWithReference" ref="aggregatorBean" input-channel="inputChannel"/>

View File

@@ -10,7 +10,10 @@
<message-bus/>
<channel id="inputChannel"/>
<channel id="outputChannel"/>
<channel id="outputChannel">
<queue capacity="5"/>
</channel>
<service-activator input-channel="inputChannel" ref="simpleHandler" output-channel="outputChannel"/>

View File

@@ -13,7 +13,9 @@
<integration:channel id="inputChannel"/>
<integration:channel id="outputChannel"/>
<integration:channel id="outputChannel">
<integration:queue capacity="5"/>
</integration:channel>
<bean id="endpoint" class="org.springframework.integration.endpoint.annotation.MessageParameterAnnotatedEndpoint"/>

View File

@@ -13,7 +13,9 @@
<integration:channel id="inputChannel"/>
<integration:channel id="outputChannel"/>
<integration:channel id="outputChannel">
<integration:queue capacity="5"/>
</integration:channel>
<bean id="endpoint" class="org.springframework.integration.config.annotation.SimpleAnnotatedEndpoint"/>

View File

@@ -11,7 +11,9 @@
<integration:channel id="inputChannel"/>
<integration:channel id="outputChannel"/>
<integration:channel id="outputChannel">
<integration:queue capacity="5"/>
</integration:channel>
<bean id="endpoint" class="org.springframework.integration.config.annotation.TypeConvertingTestEndpoint"/>

View File

@@ -7,17 +7,18 @@
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-core-1.0.xsd">
<message-bus auto-startup="false"/>
<message-bus/>
<channel id="testChannel"/>
<channel id="replyChannel"/>
<channel id="inputChannelForBeans"/>
<channel id="inputChannelForRefs"/>
<channel id="outputChannel">
<queue capacity="10"/>
</channel>
<service-activator id="endpointWithBeanInterceptors"
input-channel="testChannel"
input-channel="inputChannelForBeans"
ref="testHandler"
output-channel="replyChannel">
<poller period="10000" max-messages-per-poll="1"/>
output-channel="outputChannel">
<interceptors>
<beans:bean class="org.springframework.integration.config.TestPreHandleInterceptor"/>
<beans:bean class="org.springframework.integration.config.TestPostHandleInterceptor"/>
@@ -25,10 +26,9 @@
</service-activator>
<service-activator id="endpointWithRefInterceptors"
input-channel="testChannel"
input-channel="inputChannelForRefs"
ref="testHandler"
output-channel="replyChannel">
<poller period="10000" max-messages-per-poll="1"/>
output-channel="outputChannel">
<interceptors>
<ref bean="preInterceptor"/>
<ref bean="postInterceptor"/>

View File

@@ -9,7 +9,7 @@
<message-bus/>
<direct-channel id="channel"/>
<channel id="channel"/>
<service-activator id="endpoint" input-channel="channel" ref="handler" error-handler="errorHandler"/>

View File

@@ -9,9 +9,13 @@
<message-bus/>
<queue-channel id="testChannel" capacity="50"/>
<channel id="testChannel">
<queue capacity="5"/>
</channel>
<channel id="replyChannel"/>
<channel id="replyChannel">
<queue capacity="5"/>
</channel>
<handler-chain id="chain">
<handler ref="handler1"/>

View File

@@ -9,7 +9,9 @@
<message-bus/>
<queue-channel id="testChannel" capacity="50"/>
<channel id="testChannel">
<queue capacity="50"/>
</channel>
<service-activator id="endpoint" input-channel="testChannel"
ref="testHandler" selector="typeSelector">

View File

@@ -9,7 +9,9 @@
<beans:bean id="messageBus" class="org.springframework.integration.bus.DefaultMessageBus"/>
<queue-channel id="testChannel" capacity="50"/>
<channel id="testChannel">
<queue capacity="50"/>
</channel>
<service-activator input-channel="testChannel" ref="testBean" method="store">
<poller period="100"/>

View File

@@ -8,11 +8,15 @@
http://www.springframework.org/schema/integration/spring-integration-core-1.0.xsd">
<message-bus/>
<channel id="outputChannel" />
<channel id="discardChannel" />
<channel id="outputChannel">
<queue capacity="5"/>
</channel>
<channel id="discardChannel">
<queue capacity="5"/>
</channel>
<resequencer id="defaultResequencer"/>
<resequencer id="completelyDefinedResequencer"

View File

@@ -9,7 +9,9 @@
<beans:bean id="messageBus" class="org.springframework.integration.bus.DefaultMessageBus"/>
<queue-channel id="testChannel" capacity="50"/>
<channel id="testChannel">
<queue capacity="50"/>
</channel>
<service-activator input-channel="testChannel" ref="testHandler">
<poller period="100"/>

View File

@@ -8,24 +8,28 @@
http://www.springframework.org/schema/integration/spring-integration-core-1.0.xsd">
<channel id="simple">
<queue capacity="10"/>
<interceptors>
<wire-tap target="testTarget"/>
</interceptors>
</channel>
<channel id="accepting">
<queue capacity="10"/>
<interceptors>
<wire-tap target="testTarget" selector="acceptingSelector"/>
</interceptors>
</channel>
<channel id="rejecting">
<queue capacity="10"/>
<interceptors>
<wire-tap target="testTarget" selector="rejectingSelector"/>
</interceptors>
</channel>
<channel id="timeout">
<queue capacity="10"/>
<interceptors>
<wire-tap target="testTarget" timeout="1234"/>
</interceptors>

View File

@@ -30,6 +30,7 @@ import org.springframework.integration.endpoint.DefaultEndpoint;
import org.springframework.integration.handler.MessageHandler;
import org.springframework.integration.handler.TestHandlers;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageDeliveryException;
import org.springframework.integration.message.MessageRejectedException;
import org.springframework.integration.message.MessageTarget;
import org.springframework.integration.message.StringMessage;
@@ -108,9 +109,18 @@ public class SimpleDispatcherTests {
dispatcher.unsubscribe(target1);
dispatcher.send(new StringMessage("test3"));
assertEquals(6, counter.get());
dispatcher.unsubscribe(target3);
dispatcher.send(new StringMessage("test4"));
assertEquals(6, counter.get());
}
@Test(expected = MessageDeliveryException.class)
public void unsubscribeLastTargetCausesDeliveryException() {
SimpleDispatcher dispatcher = new SimpleDispatcher();
final AtomicInteger counter = new AtomicInteger();
MessageTarget target = new CountingTestTarget(counter, false);
dispatcher.subscribe(target);
dispatcher.send(new StringMessage("test1"));
assertEquals(1, counter.get());
dispatcher.unsubscribe(target);
dispatcher.send(new StringMessage("test2"));
}
@Test

View File

@@ -9,9 +9,17 @@
<message-bus/>
<channel id="input"/>
<channel id="output"/>
<channel id="errorChannel"/>
<channel id="input">
<queue capacity="1"/>
</channel>
<channel id="output">
<queue capacity="1"/>
</channel>
<channel id="errorChannel">
<queue capacity="1"/>
</channel>
<service-activator id="mandatory"
input-channel="input"

View File

@@ -9,8 +9,13 @@
<message-bus/>
<channel id="input"/>
<channel id="output"/>
<channel id="input">
<queue capacity="1"/>
</channel>
<channel id="output">
<queue capacity="1"/>
</channel>
<service-activator id="notSupported"
input-channel="input"

View File

@@ -9,8 +9,13 @@
<message-bus/>
<channel id="input"/>
<channel id="output"/>
<channel id="input">
<queue capacity="1"/>
</channel>
<channel id="output">
<queue capacity="1"/>
</channel>
<service-activator id="required"
input-channel="input"

View File

@@ -9,8 +9,13 @@
<message-bus/>
<channel id="input"/>
<channel id="output"/>
<channel id="input">
<queue capacity="1"/>
</channel>
<channel id="output">
<queue capacity="1"/>
</channel>
<service-activator id="requiresNew"
input-channel="input"

View File

@@ -9,8 +9,13 @@
<message-bus/>
<channel id="input"/>
<channel id="output"/>
<channel id="input">
<queue capacity="1"/>
</channel>
<channel id="output">
<queue capacity="1"/>
</channel>
<service-activator id="supports"
input-channel="input"

View File

@@ -9,9 +9,17 @@
<message-bus/>
<channel id="badInput"/>
<channel id="goodInput"/>
<channel id="output"/>
<channel id="badInput">
<queue capacity="1"/>
</channel>
<channel id="goodInput">
<queue capacity="1"/>
</channel>
<channel id="output">
<queue capacity="1"/>
</channel>
<service-activator input-channel="badInput"
ref="testBean"
@@ -27,7 +35,7 @@
method="good"
output-channel="output">
<poller period="10000" max-messages-per-poll="1">
<transactional transaction-manager="txManager" propagation="REQUIRED"/>
<transactional transaction-manager="txManager"/>
</poller>
</service-activator>

View File

@@ -10,18 +10,30 @@
<si:message-bus/>
<si:channel id="channel1"/>
<si:channel id="channel2"/>
<si:channel id="channel2">
<si:queue capacity="5"/>
</si:channel>
<si:channel id="channel3"/>
<si:channel id="channel4"/>
<si:channel id="channel5"/>
<si:channel id="replyChannel"/>
<si:channel id="errorChannel"/>
<si:channel id="channel5">
<si:queue capacity="5"/>
</si:channel>
<si:channel id="replyChannel">
<si:queue capacity="5"/>
</si:channel>
<si:channel id="errorChannel">
<si:queue capacity="5"/>
</si:channel>
<si:service-activator input-channel="channel1" ref="testBean" method="duplicate" output-channel="channel2"/>
<si:service-activator input-channel="channel2" ref="testBean" method="duplicate" output-channel="channel3"/>
<si:service-activator input-channel="channel3" ref="testBean" method="duplicate"/>
<si:service-activator input-channel="channel3" ref="testBean" method="duplicate" error-handler="errorHandler"/>
<si:service-activator input-channel="channel4" ref="testBean" method="duplicate" output-channel="replyChannel"/>
<bean id="errorHandler" class="org.springframework.integration.channel.MessagePublishingErrorHandler">
<property name="errorChannel" ref="errorChannel"/>
</bean>
<bean id="testBean" class="org.springframework.integration.endpoint.TestBean"/>
</beans>

View File

@@ -9,9 +9,13 @@
<message-bus/>
<channel id="requestChannel"/>
<channel id="requestChannel">
<queue capacity="100"/>
</channel>
<channel id="replyChannel"/>
<channel id="replyChannel">
<queue capacity="100"/>
</channel>
<gateway id="oneWay"
service-interface="org.springframework.integration.gateway.TestService"

View File

@@ -12,6 +12,7 @@
<channel id="requestChannel"/>
<channel id="replyChannel">
<queue capacity="100"/>
<interceptors>
<ref bean="interceptor"/>
</interceptors>

View File

@@ -11,9 +11,13 @@
<channel id="input"/>
<channel id="output1"/>
<channel id="output1">
<queue capacity="1"/>
</channel>
<channel id="output2"/>
<channel id="output2">
<queue capacity="1"/>
</channel>
<router id="router" ref="pojo" method="route" input-channel="input"/>

View File

@@ -9,9 +9,11 @@
<message-bus/>
<direct-channel id="numbers"/>
<direct-channel id="splits"/>
<channel id="results"/>
<channel id="numbers"/>
<channel id="splits"/>
<channel id="results">
<queue capacity="10"/>
</channel>
<splitter ref="splitter" method="split" input-channel="numbers" output-channel="splits"/>
<aggregator ref="aggregator" method="sum" input-channel="splits" output-channel="results"/>

View File

@@ -11,7 +11,9 @@
<channel id="channel1"/>
<channel id="channel2"/>
<channel id="channel2">
<queue capacity="5"/>
</channel>
<splitter id="splitter" ref="pojo" method="split"
input-channel="channel1" output-channel="channel2"/>