Replaced UnicastMessageDispatcher with DefaultMessageDispatcher. Provides a 'broadcast' boolean option for publishing to all MessageReceivingExecutors. Default is 'false' for point-to-point messaging to one receiver even among multiple candidates.

This commit is contained in:
Mark Fisher
2008-01-09 20:50:22 +00:00
parent fada237b51
commit ca8ad17908
11 changed files with 513 additions and 189 deletions

View File

@@ -0,0 +1,344 @@
/*
* Copyright 2002-2007 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.bus;
import static org.junit.Assert.assertEquals;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.springframework.integration.MessageDeliveryException;
import org.springframework.integration.channel.SimpleChannel;
import org.springframework.integration.endpoint.GenericMessageEndpoint;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.StringMessage;
/**
* @author Mark Fisher
*/
public class DefaultMessageDispatcherTests {
@Test
public void testNonBroadcastingDispatcherSendsToExactlyOneEndpoint() throws InterruptedException {
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
final CountDownLatch latch = new CountDownLatch(1);
TestEndpoint endpoint1 = new TestEndpoint(counter1, latch);
TestEndpoint endpoint2 = new TestEndpoint(counter2, latch);
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1));
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1));
dispatcher.dispatch();
latch.await(100, TimeUnit.MILLISECONDS);
assertEquals("exactly one endpoint should have received message", 1, counter1.get() + counter2.get());
}
@Test
public void testBroadcastingDispatcherSendsToAllEndpoints() throws InterruptedException {
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
final CountDownLatch latch = new CountDownLatch(2);
TestEndpoint endpoint1 = new TestEndpoint(counter1, latch);
TestEndpoint endpoint2 = new TestEndpoint(counter2, latch);
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
dispatcher.setBroadcast(true);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1));
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1));
dispatcher.dispatch();
latch.await(100, TimeUnit.MILLISECONDS);
assertEquals("both endpoints should have received message", 2, counter1.get() + counter2.get());
}
@Test
public void testNonBroadcastingDispatcherSkipsInactiveExecutor() throws InterruptedException {
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
final AtomicInteger counter3 = new AtomicInteger();
final CountDownLatch latch = new CountDownLatch(1);
TestEndpoint endpoint1 = new TestEndpoint(counter1, latch);
TestEndpoint endpoint2 = new TestEndpoint(counter2, latch);
TestEndpoint endpoint3 = new TestEndpoint(counter3, latch);
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1) {
@Override
public void start() {
}
});
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1));
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint3, 1, 1));
dispatcher.dispatch();
latch.await(100, TimeUnit.MILLISECONDS);
assertEquals("inactive endpoint should not have received message", 0, counter1.get());
assertEquals("exactly one endpoint should have received message", 1, counter2.get() + counter3.get());
}
@Test
public void testBroadcastingDispatcherSkipsInactiveExecutor() throws InterruptedException {
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
final AtomicInteger counter3 = new AtomicInteger();
final CountDownLatch latch = new CountDownLatch(2);
TestEndpoint endpoint1 = new TestEndpoint(counter1, latch);
TestEndpoint endpoint2 = new TestEndpoint(counter2, latch);
TestEndpoint endpoint3 = new TestEndpoint(counter3, latch);
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
dispatcher.setBroadcast(true);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1));
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1) {
@Override
public void start() {
}
});
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint3, 1, 1));
dispatcher.dispatch();
latch.await(100, TimeUnit.MILLISECONDS);
assertEquals("inactive endpoint should not have received message", 0, counter2.get());
assertEquals("both active endpoints should have received message", 2, counter1.get() + counter3.get());
}
@Test
public void testDispatcherWithNoExecutors() {
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
assertEquals(0, dispatcher.dispatch());
}
@Test(expected=MessageDeliveryException.class)
public void testBroadcastingDispatcherReachesRejectionLimitAndShouldFail() {
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
final AtomicInteger counter3 = new AtomicInteger();
final CountDownLatch latch = new CountDownLatch(2);
TestEndpoint endpoint1 = new TestEndpoint(counter1, latch);
TestEndpoint endpoint2 = new TestEndpoint(counter2, latch);
TestEndpoint endpoint3 = new TestEndpoint(counter3, latch);
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
dispatcher.setBroadcast(true);
dispatcher.setRejectionLimit(2);
dispatcher.setRetryInterval(3);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1));
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1) {
@Override
public void processMessage(Message<?> message) {
throw new RejectedExecutionException();
}
});
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint3, 1, 1));
dispatcher.dispatch();
}
@Test
public void testBroadcastingDispatcherReachesRejectionLimitAndShouldNotFail() throws InterruptedException {
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
final AtomicInteger counter3 = new AtomicInteger();
final CountDownLatch latch = new CountDownLatch(2);
TestEndpoint endpoint1 = new TestEndpoint(counter1, latch);
TestEndpoint endpoint2 = new TestEndpoint(counter2, latch);
TestEndpoint endpoint3 = new TestEndpoint(counter3, latch);
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
dispatcher.setBroadcast(true);
dispatcher.setRejectionLimit(2);
dispatcher.setRetryInterval(3);
dispatcher.setShouldFailOnRejectionLimit(false);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1));
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1) {
@Override
public void processMessage(Message<?> message) {
throw new RejectedExecutionException();
}
});
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint3, 1, 1));
dispatcher.dispatch();
latch.await(100, TimeUnit.MILLISECONDS);
assertEquals("rejecting endpoint should not have received message", 0, counter2.get());
assertEquals("both non-rejecting endpoints should have received message", 2, counter1.get() + counter3.get());
}
@Test(expected=MessageDeliveryException.class)
public void testNonBroadcastingDispatcherReachesRejectionLimitAndShouldFail() {
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
final CountDownLatch latch = new CountDownLatch(1);
TestEndpoint endpoint1 = new TestEndpoint(counter1, latch);
TestEndpoint endpoint2 = new TestEndpoint(counter2, latch);
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
dispatcher.setRejectionLimit(2);
dispatcher.setRetryInterval(3);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1) {
@Override
public void processMessage(Message<?> message) {
throw new RejectedExecutionException();
}
});
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1) {
@Override
public void processMessage(Message<?> message) {
throw new RejectedExecutionException();
}
});
dispatcher.dispatch();
}
@Test
public void testNonBroadcastingDispatcherReachesRejectionLimitButShouldNotFail() {
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
final AtomicInteger rejectedCounter1 = new AtomicInteger();
final AtomicInteger rejectedCounter2 = new AtomicInteger();
final CountDownLatch latch = new CountDownLatch(1);
TestEndpoint endpoint1 = new TestEndpoint(counter1, latch);
TestEndpoint endpoint2 = new TestEndpoint(counter2, latch);
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
dispatcher.setRejectionLimit(2);
dispatcher.setRetryInterval(3);
dispatcher.setShouldFailOnRejectionLimit(false);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1) {
@Override
public void processMessage(Message<?> message) {
rejectedCounter1.incrementAndGet();
throw new RejectedExecutionException();
}
});
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1) {
@Override
public void processMessage(Message<?> message) {
rejectedCounter2.incrementAndGet();
throw new RejectedExecutionException();
}
});
dispatcher.dispatch();
assertEquals("rejecting endpoints should not have received message", 0, counter1.get() + counter2.get());
assertEquals("endpoint1 should have rejected two times", 2, rejectedCounter1.get());
assertEquals("endpoint2 should have rejected two times", 2, rejectedCounter2.get());
}
@Test
public void testNonBroadcastingDispatcherWithOneEndpointSucceeding() throws InterruptedException {
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
final AtomicInteger counter3 = new AtomicInteger();
final AtomicInteger rejectedCounter1 = new AtomicInteger();
final AtomicInteger rejectedCounter2 = new AtomicInteger();
final AtomicInteger rejectedCounter3 = new AtomicInteger();
final CountDownLatch latch = new CountDownLatch(1);
TestEndpoint endpoint1 = new TestEndpoint(counter1, latch);
TestEndpoint endpoint2 = new TestEndpoint(counter2, latch);
TestEndpoint endpoint3 = new TestEndpoint(counter3, latch);
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(retriever);
dispatcher.setRejectionLimit(2);
dispatcher.setRetryInterval(3);
dispatcher.setShouldFailOnRejectionLimit(false);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1) {
@Override
public void processMessage(Message<?> message) {
rejectedCounter1.incrementAndGet();
throw new RejectedExecutionException();
}
});
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1) {
@Override
public void processMessage(Message<?> message) {
if (rejectedCounter2.get() > 0) {
super.processMessage(message);
return;
}
rejectedCounter2.incrementAndGet();
throw new RejectedExecutionException();
}
});
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint3, 1, 1) {
@Override
public void processMessage(Message<?> message) {
rejectedCounter3.incrementAndGet();
throw new RejectedExecutionException();
}
});
dispatcher.dispatch();
latch.await(100, TimeUnit.MILLISECONDS);
assertEquals("endpoint1 should not have received message", 0, counter1.get());
assertEquals("endpoint2 should have received message the second time", 1, counter2.get());
assertEquals("endpoint3 should not have received message", 0, counter3.get());
assertEquals("endpoint1 should have rejected two times", 2, rejectedCounter1.get());
assertEquals("endpoint2 should have rejected one time", 1, rejectedCounter2.get());
assertEquals("endpoint3 should have rejected one time", 1, rejectedCounter3.get());
}
private static class TestEndpoint extends GenericMessageEndpoint<String> {
private AtomicInteger counter;
private CountDownLatch latch;
public TestEndpoint(AtomicInteger counter, CountDownLatch latch) {
this.counter = counter;
this.latch = latch;
}
@Override
public void messageReceived(Message<String> message) {
counter.incrementAndGet();
latch.countDown();
}
}
}

View File

@@ -1,70 +0,0 @@
/*
* Copyright 2002-2007 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.bus;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
import org.springframework.integration.channel.SimpleChannel;
import org.springframework.integration.endpoint.GenericMessageEndpoint;
import org.springframework.integration.endpoint.MessageEndpoint;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.StringMessage;
/**
* @author Mark Fisher
*/
public class UnicastMessageDispatcherTests {
@Test
public void testDispatcherSendsToExactlyOneEndpoint() throws InterruptedException {
final AtomicBoolean endpoint1Received = new AtomicBoolean();
final AtomicBoolean endpoint2Received = new AtomicBoolean();
final CountDownLatch latch = new CountDownLatch(1);
MessageEndpoint<String> endpoint1 = new GenericMessageEndpoint<String>() {
@Override
public void messageReceived(Message<String> message) {
endpoint1Received.set(true);
latch.countDown();
}
};
MessageEndpoint<String> endpoint2 = new GenericMessageEndpoint<String>() {
@Override
public void messageReceived(Message<String> message) {
endpoint2Received.set(true);
latch.countDown();
}
};
ConsumerPolicy policy = new ConsumerPolicy();
SimpleChannel channel = new SimpleChannel();
channel.send(new StringMessage(1, "test"));
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
UnicastMessageDispatcher dispatcher = new UnicastMessageDispatcher(retriever, policy);
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint1, 1, 1));
dispatcher.addExecutor(new MessageReceivingExecutor(endpoint2, 1, 1));
dispatcher.dispatch();
latch.await(100, TimeUnit.MILLISECONDS);
assertTrue("exactly one endpoint should have received message",
endpoint1Received.get() ^ endpoint2Received.get());
}
}