/** * Create a PublishSubscribeChannel that will use an {@link Executor} * to invoke the handlers. If this is null, each invocation will occur in * the message sender's thread. * @param executor The executor. */ public PublishSubscribeChannel(@Nullable Executor executor) { super(executor); this.dispatcher = new BroadcastingDispatcher(executor); }
@Override protected AbstractDispatcher createDispatcher() { BroadcastingDispatcher broadcastingDispatcher = new BroadcastingDispatcher(true); broadcastingDispatcher.setBeanFactory(this.getBeanFactory()); return broadcastingDispatcher; }
@Test public void singleTargetWithTaskExecutor() throws Exception { dispatcher = new BroadcastingDispatcher(taskExecutorMock); dispatcher.addHandler(targetMock1); dispatcher.dispatch(messageMock); verify(targetMock1).handleMessage(eq(messageMock)); }
@Test public void multipleTargetsAllFail() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock2); dispatcher.addHandler(targetMock3); partialFailingExecutorMock(false, false, false); dispatcher.dispatch(messageMock); verify(targetMock1, Mockito.never()).handleMessage(eq(messageMock)); verify(targetMock2, Mockito.never()).handleMessage(eq(messageMock)); verify(targetMock3, Mockito.never()).handleMessage(eq(messageMock)); }
@Test public void multipleTargetsPartialFailureFirst() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock2); dispatcher.addHandler(targetMock3); partialFailingExecutorMock(false, true, true); dispatcher.dispatch(messageMock); verify(targetMock1, Mockito.never()).handleMessage(eq(messageMock)); verify(targetMock2).handleMessage(eq(messageMock)); verify(targetMock3).handleMessage(eq(messageMock)); }
@Test public void singleTargetWithoutTaskExecutor() throws Exception { dispatcher = new BroadcastingDispatcher(); dispatcher.addHandler(targetMock1); dispatcher.dispatch(messageMock); verify(targetMock1).handleMessage(eq(messageMock)); }
@Test public void multipleTargetsWithoutTaskExecutor() { dispatcher = new BroadcastingDispatcher(); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock2); dispatcher.addHandler(targetMock3); dispatcher.dispatch(messageMock); verify(targetMock1).handleMessage(eq(messageMock)); verify(targetMock2).handleMessage(eq(messageMock)); verify(targetMock3).handleMessage(eq(messageMock)); }
@Test public void multipleTargetsPartialFailureMiddle() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock2); dispatcher.addHandler(targetMock3); partialFailingExecutorMock(true, false, true); dispatcher.dispatch(messageMock); verify(targetMock1).handleMessage(eq(messageMock)); verify(targetMock2, Mockito.never()).handleMessage(eq(messageMock)); verify(targetMock3).handleMessage(eq(messageMock)); }
@Test public void multipleTargetsWithTaskExecutor() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock2); dispatcher.addHandler(targetMock3); dispatcher.dispatch(messageMock); verify(targetMock1).handleMessage(eq(messageMock)); verify(targetMock2).handleMessage(eq(messageMock)); verify(targetMock3).handleMessage(eq(messageMock)); }
@Test public void removeConsumerBetweenSends() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock2); dispatcher.addHandler(targetMock3); dispatcher.dispatch(messageMock); dispatcher.removeHandler(targetMock2); dispatcher.dispatch(messageMock); verify(targetMock1, Mockito.times(2)).handleMessage(eq(messageMock)); verify(targetMock2).handleMessage(eq(messageMock)); verify(targetMock3, Mockito.times(2)).handleMessage(eq(messageMock)); }
@Test public void multipleTargetsPartialFailureLast() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock2); dispatcher.addHandler(targetMock3); partialFailingExecutorMock(true, true, false); dispatcher.dispatch(messageMock); verify(targetMock1).handleMessage(eq(messageMock)); verify(targetMock2).handleMessage(eq(messageMock)); verify(targetMock3, Mockito.never()).handleMessage(eq(messageMock)); }
@Test public void removeConsumerBeforeSend() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock2); dispatcher.addHandler(targetMock3); dispatcher.removeHandler(targetMock2); dispatcher.dispatch(messageMock); verify(targetMock1).handleMessage(eq(messageMock)); verify(targetMock2, Mockito.never()).handleMessage(eq(messageMock)); verify(targetMock3).handleMessage(eq(messageMock)); }
/** * Verifies behavior when no handler is subscribed to the dispatcher. */ @Test public void testNoHandler() { dispatcher = new BroadcastingDispatcher(); assertTrue(dispatcher.dispatch(messageMock)); }
/** * Verifies behavior when no handler is subscribed to the dispatcher with executor. */ @Test public void testNoHandlerWithExecutor() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); assertTrue(dispatcher.dispatch(messageMock)); }
@Test public void noDuplicateSubscription() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock1); dispatcher.addHandler(targetMock1); dispatcher.dispatch(messageMock); verify(targetMock1).handleMessage(eq(messageMock)); }
private void configureDispatcher(boolean isPubSub) { if (isPubSub) { BroadcastingDispatcher broadcastingDispatcher = new BroadcastingDispatcher(true); broadcastingDispatcher.setBeanFactory(this.getBeanFactory()); this.dispatcher = broadcastingDispatcher; } else { UnicastingDispatcher unicastingDispatcher = new UnicastingDispatcher(); unicastingDispatcher.setLoadBalancingStrategy(new RoundRobinLoadBalancingStrategy()); this.dispatcher = unicastingDispatcher; } if (this.maxSubscribers == null) { this.maxSubscribers = this.getIntegrationProperty(isPubSub ? IntegrationProperties.CHANNELS_MAX_BROADCAST_SUBSCRIBERS : IntegrationProperties.CHANNELS_MAX_UNICAST_SUBSCRIBERS, Integer.class); } this.dispatcher.setMaxSubscribers(this.maxSubscribers); }
/** * Verifies that the dispatcher adds the message to the exception if it * was not attached by the handler. */ @Test public void testExceptionEnhancement() { dispatcher = new BroadcastingDispatcher(); dispatcher.addHandler(targetMock1); doThrow(new MessagingException("Mock Exception")) .when(targetMock1).handleMessage(eq(messageMock)); try { dispatcher.dispatch(messageMock); fail("Expected Exception"); } catch (MessagingException e) { assertEquals(messageMock, e.getFailedMessage()); } }
/** * Verifies behavior when dispatcher throws exception if no handler is subscribed * and requireSubscribers set to true. */ @Test public void testNoHandlerWithRequiredSubscriber() { dispatcher = new BroadcastingDispatcher(true); try { dispatcher.dispatch(messageMock); fail("Expected Exception"); } catch (MessageDispatchingException exception) { assertEquals(messageMock, exception.getFailedMessage()); } }
/** * Verifies behavior when dispatcher with executors throws exception if no handler is subscribed * and requireSubscribers set to true. */ @Test public void testNoHandlerWithExecutorWithRequiredSubscriber() { dispatcher = new BroadcastingDispatcher(taskExecutorMock, true); try { dispatcher.dispatch(messageMock); fail("Expected Exception"); } catch (MessageDispatchingException exception) { assertEquals(messageMock, exception.getFailedMessage()); } }
@Test public void applySequenceDisabledByDefault() { BroadcastingDispatcher dispatcher = new BroadcastingDispatcher(); final List<Message<?>> messages = Collections.synchronizedList(new ArrayList<Message<?>>()); MessageHandler target1 = new MessageStoringTestEndpoint(messages); MessageHandler target2 = new MessageStoringTestEndpoint(messages); dispatcher.addHandler(target1); dispatcher.addHandler(target2); dispatcher.dispatch(new GenericMessage<String>("test")); assertEquals(2, messages.size()); assertEquals(0, new IntegrationMessageHeaderAccessor(messages.get(0)).getSequenceNumber()); assertEquals(0, new IntegrationMessageHeaderAccessor(messages.get(0)).getSequenceSize()); assertEquals(0, new IntegrationMessageHeaderAccessor(messages.get(1)).getSequenceNumber()); assertEquals(0, new IntegrationMessageHeaderAccessor(messages.get(1)).getSequenceSize()); }