DefaultMessageEndpoint now provides a ReplyHandler callback for ConcurrentHandlers.

This commit is contained in:
Mark Fisher
2008-01-21 16:34:20 +00:00
parent 33143a98d6
commit 89e990f661
15 changed files with 592 additions and 24 deletions

View File

@@ -120,6 +120,7 @@ public class ChannelParserTests {
assertEquals(DispatcherPolicy.DEFAULT_RECEIVE_TIMEOUT, dispatcherPolicy.getReceiveTimeout());
assertEquals(DispatcherPolicy.DEFAULT_REJECTION_LIMIT, dispatcherPolicy.getRejectionLimit());
assertEquals(DispatcherPolicy.DEFAULT_RETRY_INTERVAL, dispatcherPolicy.getRetryInterval());
assertTrue(dispatcherPolicy.getShouldFailOnRejectionLimit());
}
@Test
@@ -133,6 +134,7 @@ public class ChannelParserTests {
assertEquals(77, dispatcherPolicy.getReceiveTimeout());
assertEquals(777, dispatcherPolicy.getRejectionLimit());
assertEquals(7777, dispatcherPolicy.getRetryInterval());
assertFalse(dispatcherPolicy.getShouldFailOnRejectionLimit());
}

View File

@@ -16,7 +16,11 @@
<channel id="publishSubscribeChannel" publish-subscribe="true"/>
<channel id="channelWithDispatcherPolicy" publish-subscribe="true">
<dispatcher-policy max-messages-per-task="7" receive-timeout="77" rejection-limit="777" retry-interval="7777"/>
<dispatcher-policy max-messages-per-task="7"
receive-timeout="77"
rejection-limit="777"
retry-interval="7777"
should-fail-on-rejection-limit="false"/>
</channel>
</beans:beans>

View File

@@ -0,0 +1,100 @@
/*
* 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.dispatcher;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Collection;
import java.util.Iterator;
import org.junit.Test;
import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.channel.SimpleChannel;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.StringMessage;
/**
* @author Mark Fisher
*/
public class ChannelPollingMessageRetrieverTests {
@Test
public void testSingleMessagePerRetrieval() {
DispatcherPolicy dispatcherPolicy = new DispatcherPolicy();
dispatcherPolicy.setReceiveTimeout(0);
MessageChannel channel = new SimpleChannel(dispatcherPolicy);
ChannelPollingMessageRetriever retriever = new ChannelPollingMessageRetriever(channel);
Collection<Message<?>> results = retriever.retrieveMessages();
assertTrue(results.isEmpty());
channel.send(new StringMessage("test1"));
channel.send(new StringMessage("test2"));
results = retriever.retrieveMessages();
assertEquals(1, results.size());
assertEquals("test1", results.iterator().next().getPayload());
results = retriever.retrieveMessages();
assertEquals(1, results.size());
assertEquals("test2", results.iterator().next().getPayload());
}
@Test
public void testMultipleMessagesPerRetrieval() {
DispatcherPolicy dispatcherPolicy = new DispatcherPolicy();
dispatcherPolicy.setReceiveTimeout(0);
dispatcherPolicy.setMaxMessagesPerTask(2);
MessageChannel channel = new SimpleChannel(dispatcherPolicy);
ChannelPollingMessageRetriever retriever = new ChannelPollingMessageRetriever(channel);
Collection<Message<?>> results = retriever.retrieveMessages();
assertTrue(results.isEmpty());
channel.send(new StringMessage("test1"));
channel.send(new StringMessage("test2"));
channel.send(new StringMessage("test3"));
results = retriever.retrieveMessages();
assertEquals(2, results.size());
Iterator<Message<?>> iter = results.iterator();
assertEquals("test1", iter.next().getPayload());
assertEquals("test2", iter.next().getPayload());
results = retriever.retrieveMessages();
assertEquals(1, results.size());
assertEquals("test3", results.iterator().next().getPayload());
}
@Test
public void testMaxMessagesConfiguredDynamically() {
DispatcherPolicy dispatcherPolicy = new DispatcherPolicy();
dispatcherPolicy.setReceiveTimeout(0);
dispatcherPolicy.setMaxMessagesPerTask(1);
MessageChannel channel = new SimpleChannel(dispatcherPolicy);
ChannelPollingMessageRetriever retriever = new ChannelPollingMessageRetriever(channel);
Collection<Message<?>> results = retriever.retrieveMessages();
assertTrue(results.isEmpty());
channel.send(new StringMessage("test1"));
channel.send(new StringMessage("test2"));
channel.send(new StringMessage("test3"));
results = retriever.retrieveMessages();
assertEquals(1, results.size());
assertEquals("test1", results.iterator().next().getPayload());
channel.getDispatcherPolicy().setMaxMessagesPerTask(5);
results = retriever.retrieveMessages();
assertEquals(2, results.size());
Iterator<Message<?>> iter = results.iterator();
assertEquals("test2", iter.next().getPayload());
assertEquals("test3", iter.next().getPayload());
}
}

View File

@@ -29,12 +29,12 @@ import org.junit.Test;
import org.springframework.integration.MessageDeliveryException;
import org.springframework.integration.channel.SimpleChannel;
import org.springframework.integration.dispatcher.DefaultMessageDispatcher;
import org.springframework.integration.dispatcher.MessageHandlerRejectedExecutionException;
import org.springframework.integration.endpoint.ConcurrencyPolicy;
import org.springframework.integration.endpoint.DefaultMessageEndpoint;
import org.springframework.integration.handler.ConcurrentHandler;
import org.springframework.integration.handler.InterceptingMessageHandler;
import org.springframework.integration.handler.MessageHandler;
import org.springframework.integration.handler.MessageHandlerRejectedExecutionException;
import org.springframework.integration.handler.TestHandlers;
import org.springframework.integration.message.ErrorMessage;
import org.springframework.integration.message.Message;

View File

@@ -0,0 +1,79 @@
/*
* 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.dispatcher;
import static org.junit.Assert.assertEquals;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.channel.SimpleChannel;
import org.springframework.integration.handler.TestHandlers;
import org.springframework.integration.message.StringMessage;
/**
* @author Mark Fisher
*/
public class DispatcherTaskTests {
@Test
public void testSimpleDispatch() throws InterruptedException {
MessageChannel channel = new SimpleChannel();
DispatcherTask task = new DispatcherTask(channel);
final CountDownLatch latch = new CountDownLatch(1);
task.addHandler(TestHandlers.countDownHandler(latch));
task.dispatchMessage(new StringMessage("test"));
latch.await(500, TimeUnit.MILLISECONDS);
assertEquals(0, latch.getCount());
}
@Test
public void testDispatchWithPointToPointChannel() throws InterruptedException {
MessageChannel channel = new SimpleChannel(new DispatcherPolicy(false));
DispatcherTask task = new DispatcherTask(channel);
final CountDownLatch latch = new CountDownLatch(1);
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
task.addHandler(TestHandlers.countingCountDownHandler(counter1, latch));
task.addHandler(TestHandlers.countingCountDownHandler(counter2, latch));
task.dispatchMessage(new StringMessage("test"));
latch.await(500, TimeUnit.MILLISECONDS);
assertEquals(0, latch.getCount());
assertEquals("only 1 handler should have received the message", 1, counter1.get() + counter2.get());
}
@Test
public void testDispatchWithPublishSubscribeChannel() throws InterruptedException {
MessageChannel channel = new SimpleChannel(new DispatcherPolicy(true));
DispatcherTask task = new DispatcherTask(channel);
final CountDownLatch latch = new CountDownLatch(2);
final AtomicInteger counter1 = new AtomicInteger();
final AtomicInteger counter2 = new AtomicInteger();
task.addHandler(TestHandlers.countingCountDownHandler(counter1, latch));
task.addHandler(TestHandlers.countingCountDownHandler(counter2, latch));
task.dispatchMessage(new StringMessage("test"));
latch.await(500, TimeUnit.MILLISECONDS);
assertEquals(0, latch.getCount());
assertEquals(1, counter1.get());
assertEquals(1, counter2.get());
}
}

View File

@@ -18,6 +18,12 @@ package org.springframework.integration.endpoint;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
@@ -25,9 +31,15 @@ import org.springframework.integration.channel.ChannelRegistry;
import org.springframework.integration.channel.DefaultChannelRegistry;
import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.channel.SimpleChannel;
import org.springframework.integration.handler.ConcurrentHandler;
import org.springframework.integration.handler.MessageHandler;
import org.springframework.integration.handler.MessageHandlerNotRunningException;
import org.springframework.integration.handler.TestHandlers;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.StringMessage;
import org.springframework.integration.message.selector.MessageSelector;
import org.springframework.integration.message.selector.MessageSelectorRejectedException;
import org.springframework.integration.util.ErrorHandler;
/**
* @author Mark Fisher
@@ -79,4 +91,316 @@ public class DefaultMessageEndpointTests {
assertEquals("hello test", reply.getPayload());
}
@Test
public void testCustomErrorHandler() throws InterruptedException {
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.setConcurrencyPolicy(new ConcurrencyPolicy(1, 1));
final CountDownLatch latch = new CountDownLatch(2);
endpoint.setErrorHandler(new ErrorHandler() {
public void handle(Throwable t) {
latch.countDown();
}
});
endpoint.setHandler(TestHandlers.rejectingCountDownHandler(latch));
endpoint.start();
endpoint.handle(new StringMessage("test"));
latch.await(500, TimeUnit.MILLISECONDS);
assertEquals("both handler and errorHandler should have been invoked", 0, latch.getCount());
}
@Test
public void testConcurrentHandlerWithDefaultReplyChannel() throws InterruptedException {
MessageChannel replyChannel = new SimpleChannel();
ChannelRegistry channelRegistry = new DefaultChannelRegistry();
channelRegistry.registerChannel("replyChannel", replyChannel);
final CountDownLatch latch = new CountDownLatch(1);
MessageHandler handler = new MessageHandler() {
public Message<String> handle(Message<?> message) {
latch.countDown();
return new StringMessage("123", "hello " + message.getPayload());
}
};
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.setChannelRegistry(channelRegistry);
endpoint.setHandler(new ConcurrentHandler(handler));
endpoint.setDefaultOutputChannelName("replyChannel");
endpoint.start();
endpoint.handle(new StringMessage(1, "test"));
endpoint.stop();
latch.await(200, TimeUnit.MILLISECONDS);
assertEquals("handler should have been invoked within allotted time", 0, latch.getCount());
Message<?> reply = replyChannel.receive(100);
assertNotNull(reply);
assertEquals("hello test", reply.getPayload());
}
@Test
public void testHandlerReturnsNull() throws InterruptedException {
MessageChannel replyChannel = new SimpleChannel();
ChannelRegistry channelRegistry = new DefaultChannelRegistry();
channelRegistry.registerChannel("replyChannel", replyChannel);
final CountDownLatch latch = new CountDownLatch(1);
MessageHandler handler = new MessageHandler() {
public Message<String> handle(Message<?> message) {
latch.countDown();
return null;
}
};
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.setChannelRegistry(channelRegistry);
endpoint.setHandler(handler);
endpoint.setDefaultOutputChannelName("replyChannel");
endpoint.start();
endpoint.handle(new StringMessage(1, "test"));
endpoint.stop();
latch.await(200, TimeUnit.MILLISECONDS);
assertEquals("handler should have been invoked within allotted time", 0, latch.getCount());
Message<?> reply = replyChannel.receive(0);
assertNull(reply);
}
@Test
public void testConcurrentHandlerReturnsNull() throws InterruptedException {
MessageChannel replyChannel = new SimpleChannel();
ChannelRegistry channelRegistry = new DefaultChannelRegistry();
channelRegistry.registerChannel("replyChannel", replyChannel);
final CountDownLatch latch = new CountDownLatch(1);
MessageHandler handler = new MessageHandler() {
public Message<String> handle(Message<?> message) {
latch.countDown();
return null;
}
};
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.setChannelRegistry(channelRegistry);
endpoint.setHandler(new ConcurrentHandler(handler));
endpoint.setDefaultOutputChannelName("replyChannel");
endpoint.start();
endpoint.handle(new StringMessage(1, "test"));
endpoint.stop();
latch.await(200, TimeUnit.MILLISECONDS);
assertEquals("handler should have been invoked within allotted time", 0, latch.getCount());
Message<?> reply = replyChannel.receive(0);
assertNull(reply);
}
@Test
public void testConcurrentHandlerWithExplicitReplyChannel() throws InterruptedException {
MessageChannel replyChannel = new SimpleChannel();
ChannelRegistry channelRegistry = new DefaultChannelRegistry();
channelRegistry.registerChannel("replyChannel", replyChannel);
final CountDownLatch latch = new CountDownLatch(1);
MessageHandler handler = new MessageHandler() {
public Message<String> handle(Message<?> message) {
latch.countDown();
return new StringMessage("123", "hello " + message.getPayload());
}
};
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.setChannelRegistry(channelRegistry);
endpoint.setHandler(new ConcurrentHandler(handler));
endpoint.start();
StringMessage message = new StringMessage(1, "test");
message.getHeader().setReplyChannelName("replyChannel");
endpoint.handle(message);
endpoint.stop();
latch.await(200, TimeUnit.MILLISECONDS);
assertEquals("handler should have been invoked within allotted time", 0, latch.getCount());
Message<?> reply = replyChannel.receive(100);
assertNotNull(reply);
assertEquals("hello test", reply.getPayload());
}
@Test
public void testGeneratedConcurrentHandlerWithDefaultReplyChannel() throws InterruptedException {
MessageChannel replyChannel = new SimpleChannel();
ChannelRegistry channelRegistry = new DefaultChannelRegistry();
channelRegistry.registerChannel("replyChannel", replyChannel);
final CountDownLatch latch = new CountDownLatch(1);
MessageHandler handler = new MessageHandler() {
public Message<String> handle(Message<?> message) {
latch.countDown();
return new StringMessage("123", "hello " + message.getPayload());
}
};
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.setChannelRegistry(channelRegistry);
endpoint.setHandler(handler);
endpoint.setConcurrencyPolicy(new ConcurrencyPolicy(3, 14));
endpoint.setDefaultOutputChannelName("replyChannel");
endpoint.start();
endpoint.handle(new StringMessage(1, "test"));
endpoint.stop();
latch.await(200, TimeUnit.MILLISECONDS);
assertEquals("handler should have been invoked within allotted time", 0, latch.getCount());
Message<?> reply = replyChannel.receive(100);
assertNotNull(reply);
assertEquals("hello test", reply.getPayload());
}
@Test
public void testGeneratedConcurrentHandlerWithExplicitReplyChannel() throws InterruptedException {
MessageChannel replyChannel = new SimpleChannel();
ChannelRegistry channelRegistry = new DefaultChannelRegistry();
channelRegistry.registerChannel("replyChannel", replyChannel);
final CountDownLatch latch = new CountDownLatch(1);
MessageHandler handler = new MessageHandler() {
public Message<String> handle(Message<?> message) {
latch.countDown();
return new StringMessage("123", "hello " + message.getPayload());
}
};
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.setChannelRegistry(channelRegistry);
endpoint.setHandler(handler);
endpoint.setConcurrencyPolicy(new ConcurrencyPolicy(3, 14));
endpoint.start();
StringMessage message = new StringMessage(1, "test");
message.getHeader().setReplyChannelName("replyChannel");
endpoint.handle(message);
endpoint.stop();
latch.await(200, TimeUnit.MILLISECONDS);
assertEquals("handler should have been invoked within allotted time", 0, latch.getCount());
Message<?> reply = replyChannel.receive(100);
assertNotNull(reply);
assertEquals("hello test", reply.getPayload());
}
@Test(expected=MessageHandlerNotRunningException.class)
public void testEndpointDoesNotHandleMessagesWhenNotYetStarted() {
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.handle(new StringMessage("test"));
}
@Test
public void testEndpointDoesNotHandleMessagesAfterBeingStopped() {
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
AtomicInteger counter = new AtomicInteger();
boolean exceptionThrown = false;
try {
endpoint.start();
endpoint.setHandler(TestHandlers.countingHandler(counter));
endpoint.handle(new StringMessage("test1"));
endpoint.stop();
endpoint.handle(new StringMessage("test2"));
}
catch (MessageHandlerNotRunningException e) {
exceptionThrown = true;
}
assertEquals("handler should have been invoked exactly once", 1, counter.get());
assertTrue(exceptionThrown);
}
@Test(expected=MessageSelectorRejectedException.class)
public void testEndpointWithSelectorRejecting() {
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.addMessageSelector(new MessageSelector() {
public boolean accept(Message<?> message) {
return false;
}
});
endpoint.start();
endpoint.handle(new StringMessage("test"));
}
@Test
public void testEndpointWithSelectorAccepting() throws InterruptedException {
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
endpoint.addMessageSelector(new MessageSelector() {
public boolean accept(Message<?> message) {
return true;
}
});
CountDownLatch latch = new CountDownLatch(1);
endpoint.setHandler(TestHandlers.countDownHandler(latch));
endpoint.start();
endpoint.handle(new StringMessage("test"));
latch.await(100, TimeUnit.MILLISECONDS);
assertEquals("handler should have been invoked", 0, latch.getCount());
endpoint.stop();
}
@Test
public void testEndpointWithMultipleSelectorsAndFirstRejects() {
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
boolean exceptionThrown = false;
final AtomicInteger counter = new AtomicInteger();
endpoint.addMessageSelector(new MessageSelector() {
public boolean accept(Message<?> message) {
counter.incrementAndGet();
return false;
}
});
endpoint.addMessageSelector(new MessageSelector() {
public boolean accept(Message<?> message) {
counter.incrementAndGet();
return true;
}
});
endpoint.setHandler(TestHandlers.countingHandler(counter));
endpoint.start();
try {
endpoint.handle(new StringMessage("test"));
}
catch (MessageSelectorRejectedException e) {
exceptionThrown = true;
}
assertEquals("only the first selector should have been invoked", 1, counter.get());
assertTrue(exceptionThrown);
endpoint.stop();
}
@Test
public void testEndpointWithMultipleSelectorsAndFirstAccepts() {
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
boolean exceptionThrown = false;
final AtomicInteger counter = new AtomicInteger();
endpoint.addMessageSelector(new MessageSelector() {
public boolean accept(Message<?> message) {
counter.incrementAndGet();
return true;
}
});
endpoint.addMessageSelector(new MessageSelector() {
public boolean accept(Message<?> message) {
counter.incrementAndGet();
return false;
}
});
endpoint.setHandler(TestHandlers.countingHandler(counter));
endpoint.start();
try {
endpoint.handle(new StringMessage("test"));
}
catch (MessageSelectorRejectedException e) {
exceptionThrown = true;
}
assertEquals("both selectors should have been invoked but not the handler", 2, counter.get());
assertTrue(exceptionThrown);
endpoint.stop();
}
@Test
public void testEndpointWithMultipleSelectorsAndBothAccept() {
DefaultMessageEndpoint endpoint = new DefaultMessageEndpoint();
final AtomicInteger counter = new AtomicInteger();
endpoint.addMessageSelector(new MessageSelector() {
public boolean accept(Message<?> message) {
counter.incrementAndGet();
return true;
}
});
endpoint.addMessageSelector(new MessageSelector() {
public boolean accept(Message<?> message) {
counter.incrementAndGet();
return true;
}
});
endpoint.setHandler(TestHandlers.countingHandler(counter));
endpoint.start();
endpoint.handle(new StringMessage("test"));
assertEquals("both selectors and handler should have been invoked", 3, counter.get());
endpoint.stop();
}
}

View File

@@ -19,7 +19,6 @@ package org.springframework.integration.handler;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.integration.dispatcher.MessageHandlerRejectedExecutionException;
import org.springframework.integration.message.Message;
/**