INT-711 Created LoadBalancingStrategy and improved encapsulation for the unicasting dispatcher (now contains the TaskExecutor LB strategy and a failover boolean flag).
This commit is contained in:
@@ -16,9 +16,8 @@
|
||||
|
||||
package org.springframework.integration.channel;
|
||||
|
||||
import org.springframework.integration.dispatcher.AbstractUnicastDispatcher;
|
||||
import org.springframework.integration.dispatcher.RoundRobinDispatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.integration.dispatcher.LoadBalancingStrategy;
|
||||
import org.springframework.integration.dispatcher.UnicastingDispatcher;
|
||||
|
||||
/**
|
||||
* A channel that invokes a single subscriber for each sent Message.
|
||||
@@ -30,21 +29,36 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class DirectChannel extends AbstractSubscribableChannel {
|
||||
|
||||
private final AbstractUnicastDispatcher dispatcher;
|
||||
private final UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
|
||||
|
||||
/**
|
||||
* Create a channel with no {@link LoadBalancingStrategy}.
|
||||
* The dispatcher for such a channel will invoke its
|
||||
* MessageHandlers in a fixed-order.
|
||||
*/
|
||||
public DirectChannel() {
|
||||
this.dispatcher = new RoundRobinDispatcher();
|
||||
}
|
||||
|
||||
public DirectChannel(AbstractUnicastDispatcher dispatcher) {
|
||||
Assert.notNull(dispatcher, "dispatcher must not be null");
|
||||
this.dispatcher = dispatcher;
|
||||
/**
|
||||
* Create a DirectChannel with a {@link LoadBalancingStrategy}. The
|
||||
* strategy <emphasis>must not</emphasis> be null.
|
||||
*/
|
||||
public DirectChannel(LoadBalancingStrategy loadBalancingStrategy) {
|
||||
this.dispatcher.setLoadBalancingStrategy(loadBalancingStrategy);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specify whether the channel's dispatcher should have failover enabled.
|
||||
* By default, it will. Set this value to 'false' to disable it.
|
||||
*/
|
||||
public void setFailover(boolean failover) {
|
||||
this.dispatcher.setFailover(failover);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractUnicastDispatcher getDispatcher() {
|
||||
protected UnicastingDispatcher getDispatcher() {
|
||||
return this.dispatcher;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,21 +16,13 @@
|
||||
|
||||
package org.springframework.integration.channel;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.dispatcher.AbstractUnicastDispatcher;
|
||||
import org.springframework.integration.dispatcher.MessageDispatcher;
|
||||
import org.springframework.integration.dispatcher.RoundRobinDispatcher;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.integration.dispatcher.UnicastingDispatcher;
|
||||
|
||||
/**
|
||||
* An implementation of {@link MessageChannel} that delegates to an instance of
|
||||
* {@link AbstractUnicastDispatcher} and wraps all send invocations within a
|
||||
* {@link UnicastingDispatcher} and wraps all send invocations within a
|
||||
* {@link TaskExecutor}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
@@ -38,66 +30,17 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class ExecutorChannel extends AbstractSubscribableChannel {
|
||||
|
||||
private final ExecutorDecoratingDispatcher dispatcher;
|
||||
private final UnicastingDispatcher dispatcher;
|
||||
|
||||
|
||||
public ExecutorChannel() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public ExecutorChannel(TaskExecutor taskExecutor) {
|
||||
this(null, taskExecutor);
|
||||
}
|
||||
|
||||
public ExecutorChannel(AbstractUnicastDispatcher dispatcher) {
|
||||
this(dispatcher, null);
|
||||
}
|
||||
|
||||
public ExecutorChannel(AbstractUnicastDispatcher dispatcher, TaskExecutor taskExecutor) {
|
||||
if (dispatcher == null) {
|
||||
dispatcher = new RoundRobinDispatcher();
|
||||
}
|
||||
this.dispatcher = new ExecutorDecoratingDispatcher(dispatcher, taskExecutor);
|
||||
this.dispatcher = new UnicastingDispatcher(taskExecutor);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected MessageDispatcher getDispatcher() {
|
||||
protected UnicastingDispatcher getDispatcher() {
|
||||
return this.dispatcher;
|
||||
}
|
||||
|
||||
|
||||
private static class ExecutorDecoratingDispatcher implements MessageDispatcher {
|
||||
|
||||
private final AbstractUnicastDispatcher targetDispatcher;
|
||||
|
||||
private final TaskExecutor taskExecutor;
|
||||
|
||||
|
||||
ExecutorDecoratingDispatcher(AbstractUnicastDispatcher dispatcher, TaskExecutor taskExecutor) {
|
||||
Assert.notNull(dispatcher, "'dispatcher' must not be null");
|
||||
this.targetDispatcher = dispatcher;
|
||||
this.taskExecutor = taskExecutor != null ? taskExecutor
|
||||
: new ConcurrentTaskExecutor(Executors.newSingleThreadExecutor());
|
||||
}
|
||||
|
||||
|
||||
public boolean addHandler(MessageHandler handler) {
|
||||
return this.targetDispatcher.addHandler(handler);
|
||||
}
|
||||
|
||||
public boolean removeHandler(MessageHandler handler) {
|
||||
return this.targetDispatcher.removeHandler(handler);
|
||||
}
|
||||
|
||||
public final boolean dispatch(final Message<?> message) {
|
||||
this.taskExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
targetDispatcher.dispatch(message);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,9 +18,8 @@ package org.springframework.integration.config.xml;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -37,6 +36,7 @@ public class PointToPointChannelParser extends AbstractChannelParser {
|
||||
|
||||
private static final String DISPATCHER_PACKAGE = IntegrationNamespaceUtils.BASE_PACKAGE + ".dispatcher";
|
||||
|
||||
|
||||
@Override
|
||||
protected BeanDefinitionBuilder buildBeanDefinition(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = null;
|
||||
@@ -81,23 +81,16 @@ public class PointToPointChannelParser extends AbstractChannelParser {
|
||||
else {
|
||||
builder = BeanDefinitionBuilder.genericBeanDefinition(CHANNEL_PACKAGE + ".DirectChannel");
|
||||
}
|
||||
parseDispatcher(element.getAttribute("dispatcher"), builder, parserContext);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
private void parseDispatcher(String dispatcherAttribute, BeanDefinitionBuilder builder, ParserContext parserContext) {
|
||||
if (dispatcherAttribute != null) {
|
||||
if (dispatcherAttribute.equals("failover")) {
|
||||
BeanDefinitionBuilder dispatcherBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(DISPATCHER_PACKAGE + ".FailOverDispatcher");
|
||||
dispatcherBuilder.setRole(BeanDefinition.ROLE_SUPPORT);
|
||||
builder.addConstructorArgReference(BeanDefinitionReaderUtils.registerWithGeneratedName(dispatcherBuilder
|
||||
.getBeanDefinition(), parserContext.getRegistry()));
|
||||
// this attribute is deprecated, but if set, we need to create a UnicastingDispatcher
|
||||
// without any LoadBalancerStrategy and the failover flag set to true (default).
|
||||
String dispatcherAttribute = element.getAttribute("dispatcher");
|
||||
if (!"failover".equals(dispatcherAttribute)) {
|
||||
// round-robin dispatcher by default, but TODO first we need to check for the dispatcher element.
|
||||
builder.addConstructorArgValue(new RootBeanDefinition(
|
||||
DISPATCHER_PACKAGE + ".RoundRobinLoadBalancingStrategy", null, null));
|
||||
}
|
||||
}
|
||||
// rely on the default for round-robin
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private boolean parseQueueCapacity(BeanDefinitionBuilder builder, Element queueElement) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.dispatcher;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
@@ -30,12 +31,12 @@ import org.springframework.integration.message.MessageDeliveryException;
|
||||
* @since 1.0.3
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AggregateMessageDeliverException extends MessageDeliveryException {
|
||||
public class AggregateMessageDeliveryException extends MessageDeliveryException {
|
||||
|
||||
private final List<? extends Exception> aggregatedExceptions;
|
||||
|
||||
|
||||
public AggregateMessageDeliverException(Message<?> undeliveredMessage,
|
||||
public AggregateMessageDeliveryException(Message<?> undeliveredMessage,
|
||||
String description, List<? extends Exception> aggregatedExceptions) {
|
||||
super(undeliveredMessage, description);
|
||||
this.aggregatedExceptions = aggregatedExceptions;
|
||||
@@ -43,7 +44,7 @@ public class AggregateMessageDeliverException extends MessageDeliveryException {
|
||||
|
||||
|
||||
public List<? extends Exception> getAggregatedExceptions() {
|
||||
return this.aggregatedExceptions;
|
||||
return Collections.unmodifiableList(this.aggregatedExceptions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
/* Copyright 2002-2009 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.
|
||||
@@ -16,29 +15,20 @@
|
||||
|
||||
package org.springframework.integration.dispatcher;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
|
||||
/**
|
||||
* {@link AbstractUnicastDispatcher} that will try its handlers in the
|
||||
* same order every dispatch.
|
||||
* Strategy for determining the iteration order of a MessageHandler list.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Iwein Fuld
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public class FailOverDispatcher extends AbstractUnicastDispatcher {
|
||||
public interface LoadBalancingStrategy {
|
||||
|
||||
@Override
|
||||
protected void handleExceptions(List<RuntimeException> allExceptions,
|
||||
Message<?> message, boolean isLast) {
|
||||
if (isLast) {
|
||||
if (allExceptions != null && allExceptions.size() == 1) {
|
||||
throw allExceptions.get(0);
|
||||
}
|
||||
throw new AggregateMessageDeliverException(message,
|
||||
"All attempts to deliver Message to MessageHandlers failed.", allExceptions);
|
||||
}
|
||||
}
|
||||
public Iterator<MessageHandler> getHandlerIterator(Message<?> message, List<MessageHandler> handlers);
|
||||
|
||||
}
|
||||
@@ -25,32 +25,26 @@ import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
|
||||
/**
|
||||
* Round-robin implementation of {@link AbstractUnicastDispatcher}. This
|
||||
* Round-robin implementation of {@link LoadBalancingStrategy}. This
|
||||
* implementation will keep track of the index of the handler that has been
|
||||
* tried first and use a different starting handler every dispatch.
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public class RoundRobinDispatcher extends AbstractUnicastDispatcher {
|
||||
|
||||
private volatile boolean failover = true;
|
||||
public class RoundRobinLoadBalancingStrategy implements LoadBalancingStrategy {
|
||||
|
||||
private final AtomicInteger currentHandlerIndex = new AtomicInteger();
|
||||
|
||||
|
||||
public void setFailover(boolean failover) {
|
||||
this.failover = failover;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator that starts at a new point in the list every time the
|
||||
* first part of the list that is skipped will be used at the end of the
|
||||
* iteration, so it guarantees all handlers are returned once on subsequent
|
||||
* <code>next()</code> invocations.
|
||||
*/
|
||||
@Override
|
||||
protected Iterator<MessageHandler> getHandlerIterator() {
|
||||
List<MessageHandler> handlers = this.getHandlers();
|
||||
public final Iterator<MessageHandler> getHandlerIterator(final Message<?> message, final List<MessageHandler> handlers) {
|
||||
int size = handlers.size();
|
||||
if (size == 0) {
|
||||
return handlers.iterator();
|
||||
@@ -72,16 +66,4 @@ public class RoundRobinDispatcher extends AbstractUnicastDispatcher {
|
||||
return indexTail < 0 ? indexTail + size : indexTail;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleExceptions(List<RuntimeException> allExceptions,
|
||||
Message<?> message, boolean isLast) {
|
||||
if (isLast || !this.failover) {
|
||||
if (allExceptions != null && allExceptions.size() == 1) {
|
||||
throw allExceptions.get(0);
|
||||
}
|
||||
throw new AggregateMessageDeliverException(message,
|
||||
"Failed to deliver Message to any MessageHandler.", allExceptions);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/* Copyright 2002-2009 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.dispatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.MessageDeliveryException;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of {@link MessageDispatcher} that will attempt to send a
|
||||
* {@link Message} to at most one of its handlers. The handlers will be tried
|
||||
* as determined by the {@link LoadBalancingStrategy} if one is configured. As
|
||||
* soon as <em>one</em> of the handlers accepts the Message, the dispatcher will
|
||||
* return <code>true</code> and ignore the rest of its handlers.
|
||||
* <p/>
|
||||
* If the dispatcher has no handlers, a {@link MessageDeliveryException} will be
|
||||
* thrown. If all handlers throw Exceptions, the dispatcher will throw an
|
||||
* {@link AggregateMessageDeliveryException}.
|
||||
* <p/>
|
||||
* A load-balancing strategy may be provided to this class to control the order in
|
||||
* which the handlers will be tried.
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class UnicastingDispatcher extends AbstractDispatcher {
|
||||
|
||||
private volatile boolean failover = true;
|
||||
|
||||
private volatile LoadBalancingStrategy loadBalancingStrategy;
|
||||
|
||||
private final TaskExecutor taskExecutor;
|
||||
|
||||
|
||||
public UnicastingDispatcher() {
|
||||
this.taskExecutor = null;
|
||||
}
|
||||
|
||||
public UnicastingDispatcher(TaskExecutor taskExecutor) {
|
||||
this.taskExecutor = taskExecutor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specify whether this dispatcher should failover when a single
|
||||
* {@link MessageHandler} throws an Exception. The default value is
|
||||
* <code>true</code>.
|
||||
*/
|
||||
public void setFailover(boolean failover) {
|
||||
this.failover = failover;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a {@link LoadBalancingStrategy} for this dispatcher.
|
||||
*/
|
||||
public void setLoadBalancingStrategy(LoadBalancingStrategy loadBalancingStrategy) {
|
||||
Assert.notNull(loadBalancingStrategy, "loadBalancingStrategy must not be null");
|
||||
this.loadBalancingStrategy = loadBalancingStrategy;
|
||||
}
|
||||
|
||||
public final boolean dispatch(final Message<?> message) {
|
||||
if (this.taskExecutor != null) {
|
||||
this.taskExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
doDispatch(message);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return this.doDispatch(message);
|
||||
}
|
||||
|
||||
private boolean doDispatch(Message<?> message) {
|
||||
boolean success = false;
|
||||
Iterator<MessageHandler> handlerIterator = this.getHandlerIterator(message);
|
||||
if (!handlerIterator.hasNext()) {
|
||||
throw new MessageDeliveryException(message, "Dispatcher has no subscribers.");
|
||||
}
|
||||
List<RuntimeException> exceptions = new ArrayList<RuntimeException>();
|
||||
while (success == false && handlerIterator.hasNext()) {
|
||||
MessageHandler handler = handlerIterator.next();
|
||||
try {
|
||||
handler.handleMessage(message);
|
||||
success = true; // we have a winner.
|
||||
}
|
||||
catch (Exception e) {
|
||||
RuntimeException runtimeException = (e instanceof RuntimeException)
|
||||
? (RuntimeException) e
|
||||
: new MessageDeliveryException(message,
|
||||
"Dispatcher failed to deliver Message.", e);
|
||||
exceptions.add(runtimeException);
|
||||
this.handleExceptions(exceptions, message, !handlerIterator.hasNext());
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the iterator that will be used to loop over the handlers.
|
||||
* Delegates to a {@link LoadBalancingStrategy} if available. Otherwise,
|
||||
* it simply returns the Iterator for the existing handler List.
|
||||
*/
|
||||
private Iterator<MessageHandler> getHandlerIterator(Message<?> message) {
|
||||
if (this.loadBalancingStrategy != null) {
|
||||
return this.loadBalancingStrategy.getHandlerIterator(message, this.getHandlers());
|
||||
}
|
||||
return this.getHandlers().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles Exceptions that occur while dispatching. If this dispatcher has
|
||||
* failover enabled, it will only throw an Exception when the handler list
|
||||
* is exhausted. The 'isLast' flag will be <emphasis>true</emphasis> if the
|
||||
* Exception occurred during the final iteration of the MessageHandlers.
|
||||
* If failover is disabled for this dispatcher, it will re-throw any
|
||||
* Exception immediately.
|
||||
*/
|
||||
private void handleExceptions(List<RuntimeException> allExceptions, Message<?> message, boolean isLast) {
|
||||
if (isLast || !this.failover) {
|
||||
if (allExceptions != null && allExceptions.size() == 1) {
|
||||
throw allExceptions.get(0);
|
||||
}
|
||||
throw new AggregateMessageDeliveryException(message,
|
||||
"All attempts to deliver Message to MessageHandlers failed.", allExceptions);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import static org.hamcrest.CoreMatchers.is;
|
||||
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;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -39,8 +40,8 @@ import org.springframework.integration.config.TestChannelInterceptor;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.core.MessagePriority;
|
||||
import org.springframework.integration.dispatcher.FailOverDispatcher;
|
||||
import org.springframework.integration.dispatcher.RoundRobinDispatcher;
|
||||
import org.springframework.integration.dispatcher.RoundRobinLoadBalancingStrategy;
|
||||
import org.springframework.integration.dispatcher.UnicastingDispatcher;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.message.MessageBuilder;
|
||||
import org.springframework.integration.message.MessageDeliveryException;
|
||||
@@ -79,17 +80,22 @@ public class ChannelParserTests {
|
||||
MessageChannel channel = (MessageChannel) context.getBean("defaultChannel");
|
||||
assertEquals(DirectChannel.class, channel.getClass());
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(channel);
|
||||
assertThat(accessor.getPropertyValue("dispatcher"), is(RoundRobinDispatcher.class));
|
||||
Object dispatcher = accessor.getPropertyValue("dispatcher");
|
||||
assertThat(dispatcher, is(UnicastingDispatcher.class));
|
||||
assertThat(new DirectFieldAccessor(dispatcher).getPropertyValue("loadBalancingStrategy"),
|
||||
is(RoundRobinLoadBalancingStrategy.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void channelWithRoundRobinDispatcher() throws Exception {
|
||||
public void channelWithFailoverDispatcherAttribute() throws Exception {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("channelParserTests.xml", this
|
||||
.getClass());
|
||||
MessageChannel channel = (MessageChannel) context.getBean("failOverChannel");
|
||||
MessageChannel channel = (MessageChannel) context.getBean("channelWithFailoverAttribute");
|
||||
assertEquals(DirectChannel.class, channel.getClass());
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(channel);
|
||||
assertThat(accessor.getPropertyValue("dispatcher"), is(FailOverDispatcher.class));
|
||||
Object dispatcher = accessor.getPropertyValue("dispatcher");
|
||||
assertThat(dispatcher, is(UnicastingDispatcher.class));
|
||||
assertNull(new DirectFieldAccessor(dispatcher).getPropertyValue("loadBalancingStrategy"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<channel id="defaultChannel" />
|
||||
|
||||
<channel id="failOverChannel" dispatcher="failover"/>
|
||||
<channel id="channelWithFailoverAttribute" dispatcher="failover"/>
|
||||
|
||||
<channel id="channelWithCustomQueue">
|
||||
<queue ref="customQueue"/>
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.dispatcher.FailOverDispatcher;
|
||||
import org.springframework.integration.dispatcher.RoundRobinLoadBalancingStrategy;
|
||||
import org.springframework.integration.message.MessageRejectedException;
|
||||
import org.springframework.integration.message.StringMessage;
|
||||
|
||||
@@ -45,7 +45,6 @@ public class SubscriberOrderTests {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.registerBeanDefinition("postProcessor", new RootBeanDefinition(MessagingAnnotationPostProcessor.class));
|
||||
RootBeanDefinition channelDefinition = new RootBeanDefinition(DirectChannel.class);
|
||||
channelDefinition.getConstructorArgumentValues().addGenericArgumentValue(new FailOverDispatcher());
|
||||
context.registerBeanDefinition("input", channelDefinition);
|
||||
RootBeanDefinition testBeanDefinition = new RootBeanDefinition(TestBean.class);
|
||||
testBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue(1);
|
||||
@@ -72,7 +71,6 @@ public class SubscriberOrderTests {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.registerBeanDefinition("postProcessor", new RootBeanDefinition(MessagingAnnotationPostProcessor.class));
|
||||
RootBeanDefinition channelDefinition = new RootBeanDefinition(DirectChannel.class);
|
||||
channelDefinition.getConstructorArgumentValues().addGenericArgumentValue(new FailOverDispatcher());
|
||||
context.registerBeanDefinition("input", channelDefinition);
|
||||
RootBeanDefinition testBeanDefinition = new RootBeanDefinition(TestBean.class);
|
||||
testBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue(2);
|
||||
@@ -112,6 +110,7 @@ public class SubscriberOrderTests {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.registerBeanDefinition("postProcessor", new RootBeanDefinition(MessagingAnnotationPostProcessor.class));
|
||||
RootBeanDefinition channelDefinition = new RootBeanDefinition(DirectChannel.class);
|
||||
channelDefinition.getConstructorArgumentValues().addGenericArgumentValue(new RoundRobinLoadBalancingStrategy());
|
||||
context.registerBeanDefinition("input", channelDefinition);
|
||||
RootBeanDefinition testBeanDefinition = new RootBeanDefinition(TestBean.class);
|
||||
testBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue(1000);
|
||||
|
||||
@@ -41,7 +41,7 @@ public class FailOverDispatcherTests {
|
||||
|
||||
@Test
|
||||
public void singleMessage() throws InterruptedException {
|
||||
FailOverDispatcher dispatcher = new FailOverDispatcher();
|
||||
UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
dispatcher.addHandler(createConsumer(TestHandlers.countDownHandler(latch)));
|
||||
dispatcher.dispatch(new StringMessage("test"));
|
||||
@@ -51,7 +51,7 @@ public class FailOverDispatcherTests {
|
||||
|
||||
@Test
|
||||
public void pointToPoint() throws InterruptedException {
|
||||
FailOverDispatcher dispatcher = new FailOverDispatcher();
|
||||
UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final AtomicInteger counter1 = new AtomicInteger();
|
||||
final AtomicInteger counter2 = new AtomicInteger();
|
||||
@@ -65,7 +65,7 @@ public class FailOverDispatcherTests {
|
||||
|
||||
@Test
|
||||
public void noDuplicateSubscriptions() {
|
||||
FailOverDispatcher dispatcher = new FailOverDispatcher();
|
||||
UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
MessageHandler target = new CountingTestEndpoint(counter, false);
|
||||
dispatcher.addHandler(target);
|
||||
@@ -81,7 +81,7 @@ public class FailOverDispatcherTests {
|
||||
|
||||
@Test
|
||||
public void removeConsumerBeforeSend() {
|
||||
FailOverDispatcher dispatcher = new FailOverDispatcher();
|
||||
UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
MessageHandler target1 = new CountingTestEndpoint(counter, false);
|
||||
MessageHandler target2 = new CountingTestEndpoint(counter, false);
|
||||
@@ -101,7 +101,7 @@ public class FailOverDispatcherTests {
|
||||
|
||||
@Test
|
||||
public void removeConsumerBetweenSends() {
|
||||
FailOverDispatcher dispatcher = new FailOverDispatcher();
|
||||
UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
MessageHandler target1 = new CountingTestEndpoint(counter, false);
|
||||
MessageHandler target2 = new CountingTestEndpoint(counter, false);
|
||||
@@ -136,7 +136,7 @@ public class FailOverDispatcherTests {
|
||||
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void removeConsumerLastTargetCausesDeliveryException() {
|
||||
FailOverDispatcher dispatcher = new FailOverDispatcher();
|
||||
UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
MessageHandler target = new CountingTestEndpoint(counter, false);
|
||||
dispatcher.addHandler(target);
|
||||
@@ -153,7 +153,7 @@ public class FailOverDispatcherTests {
|
||||
|
||||
@Test
|
||||
public void firstHandlerReturnsTrue() {
|
||||
FailOverDispatcher dispatcher = new FailOverDispatcher();
|
||||
UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
MessageHandler target1 = new CountingTestEndpoint(counter, true);
|
||||
MessageHandler target2 = new CountingTestEndpoint(counter, false);
|
||||
@@ -167,7 +167,7 @@ public class FailOverDispatcherTests {
|
||||
|
||||
@Test
|
||||
public void middleHandlerReturnsTrue() {
|
||||
FailOverDispatcher dispatcher = new FailOverDispatcher();
|
||||
UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
MessageHandler target1 = new CountingTestEndpoint(counter, false);
|
||||
MessageHandler target2 = new CountingTestEndpoint(counter, true);
|
||||
@@ -181,7 +181,7 @@ public class FailOverDispatcherTests {
|
||||
|
||||
@Test
|
||||
public void allHandlersReturnFalse() {
|
||||
FailOverDispatcher dispatcher = new FailOverDispatcher();
|
||||
UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
MessageHandler target1 = new CountingTestEndpoint(counter, false);
|
||||
MessageHandler target2 = new CountingTestEndpoint(counter, false);
|
||||
|
||||
@@ -46,7 +46,7 @@ public class RoundRobinDispatcherConcurrentTests {
|
||||
|
||||
private static final int TOTAL_EXECUTIONS = 40;
|
||||
|
||||
private RoundRobinDispatcher dispatcher = new RoundRobinDispatcher();
|
||||
private UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
|
||||
private ThreadPoolTaskExecutor scheduler = new ThreadPoolTaskExecutor();
|
||||
|
||||
@@ -67,6 +67,7 @@ public class RoundRobinDispatcherConcurrentTests {
|
||||
|
||||
@Before
|
||||
public void initialize() throws Exception {
|
||||
dispatcher.setLoadBalancingStrategy(new RoundRobinLoadBalancingStrategy());
|
||||
scheduler.setCorePoolSize(10);
|
||||
scheduler.setMaxPoolSize(10);
|
||||
scheduler.initialize();
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
|
||||
package org.springframework.integration.dispatcher;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -32,7 +34,7 @@ import org.springframework.integration.message.MessageHandler;
|
||||
@RunWith(MockitoJUnit44Runner.class)
|
||||
public class RoundRobinDispatcherTests {
|
||||
|
||||
private AbstractUnicastDispatcher dispatcher = new RoundRobinDispatcher();
|
||||
private UnicastingDispatcher dispatcher = new UnicastingDispatcher();
|
||||
|
||||
@Mock
|
||||
private MessageHandler handler;
|
||||
@@ -43,6 +45,12 @@ public class RoundRobinDispatcherTests {
|
||||
@Mock
|
||||
private MessageHandler differentHandler;
|
||||
|
||||
@Before
|
||||
public void setupDispatcher() {
|
||||
this.dispatcher.setLoadBalancingStrategy(new RoundRobinLoadBalancingStrategy());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void dispatchMessageWithSingleHandler() throws Exception {
|
||||
dispatcher.addHandler(handler);
|
||||
|
||||
Reference in New Issue
Block a user