@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)); }
@Override protected AbstractDispatcher createDispatcher() { BroadcastingDispatcher broadcastingDispatcher = new BroadcastingDispatcher(true); broadcastingDispatcher.setBeanFactory(this.getBeanFactory()); return broadcastingDispatcher; }
/** * Specify whether to apply the sequence number and size headers to the * messages prior to invoking the subscribed handlers. By default, this * value is <code>false</code> meaning that sequence headers will * <em>not</em> be applied. If planning to use an Aggregator downstream * with the default correlation and completion strategies, you should set * this flag to <code>true</code>. * @param applySequence true if the sequence information should be applied. */ public void setApplySequence(boolean applySequence) { this.applySequence = applySequence; getDispatcher().setApplySequence(applySequence); }
@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)); }
super.onInit(); if (this.executor != null) { Assert.state(getDispatcher().getHandlerCount() == 0, "When providing an Executor, you cannot subscribe() until the channel " + "bean is fully initialized by the framework. Do not subscribe in a @Bean definition"); this.dispatcher = new BroadcastingDispatcher(this.executor); getDispatcher().setIgnoreFailures(this.ignoreFailures); getDispatcher().setApplySequence(this.applySequence); getDispatcher().setMinSubscribers(this.minSubscribers); this.setMaxSubscribers(maxSubscribers); getDispatcher().setBeanFactory(this.getBeanFactory()); getDispatcher().setMessageHandlingTaskDecorator(task -> { if (PublishSubscribeChannel.this.executorInterceptorsSize > 0) { return new MessageHandlingTask(task);
@Test public void applySequenceEnabled() { BroadcastingDispatcher dispatcher = new BroadcastingDispatcher(); dispatcher.setApplySequence(true); final List<Message<?>> messages = Collections.synchronizedList(new ArrayList<Message<?>>()); MessageHandler target1 = new MessageStoringTestEndpoint(messages); MessageHandler target2 = new MessageStoringTestEndpoint(messages); MessageHandler target3 = new MessageStoringTestEndpoint(messages); dispatcher.addHandler(target1); dispatcher.addHandler(target2); dispatcher.addHandler(target3); Message<?> inputMessage = new GenericMessage<String>("test"); Object originalId = inputMessage.getHeaders().getId(); dispatcher.dispatch(inputMessage); assertEquals(3, messages.size()); assertEquals(1, new IntegrationMessageHeaderAccessor(messages.get(0)).getSequenceNumber()); assertEquals(3, new IntegrationMessageHeaderAccessor(messages.get(0)).getSequenceSize()); assertEquals(originalId, new IntegrationMessageHeaderAccessor(messages.get(0)).getCorrelationId()); assertEquals(2, new IntegrationMessageHeaderAccessor(messages.get(1)).getSequenceNumber()); assertEquals(3, new IntegrationMessageHeaderAccessor(messages.get(1)).getSequenceSize()); assertEquals(originalId, new IntegrationMessageHeaderAccessor(messages.get(1)).getCorrelationId()); assertEquals(3, new IntegrationMessageHeaderAccessor(messages.get(2)).getSequenceNumber()); assertEquals(3, new IntegrationMessageHeaderAccessor(messages.get(2)).getSequenceSize()); assertEquals(originalId, new IntegrationMessageHeaderAccessor(messages.get(2)).getCorrelationId()); }
/** * Verifies behavior when no handler is subscribed to the dispatcher. */ @Test public void testNoHandler() { dispatcher = new BroadcastingDispatcher(); assertTrue(dispatcher.dispatch(messageMock)); }
public void setBeanFactory(BeanFactory beanFactory) { if (this.taskExecutor != null) { if (!(this.taskExecutor instanceof ErrorHandlingTaskExecutor)) { if (this.errorHandler == null) { this.errorHandler = new MessagePublishingErrorHandler(new BeanFactoryChannelResolver(beanFactory)); } this.taskExecutor = new ErrorHandlingTaskExecutor(this.taskExecutor, this.errorHandler); } this.dispatcher = new BroadcastingDispatcher(this.taskExecutor); this.dispatcher.setIgnoreFailures(this.ignoreFailures); this.dispatcher.setApplySequence(this.applySequence); } }
int dispatched = 0; int sequenceNumber = 1; Collection<MessageHandler> handlers = this.getHandlers(); if (this.requireSubscribers && handlers.size() == 0) { throw new MessageDispatchingException(message, "Dispatcher has no subscribers"); messageToSend = getMessageBuilderFactory() .fromMessage(message) .pushSequenceDetails(sequenceId, sequenceNumber++, sequenceSize) Runnable task = createMessageHandlingTask(handler, messageToSend); this.executor.execute(task); dispatched++; if (this.invokeHandler(handler, messageToSend)) { dispatched++;
@Test public void defaultChannel() { PublishSubscribeChannel channel = this.context.getBean("defaultChannel", PublishSubscribeChannel.class); DirectFieldAccessor accessor = new DirectFieldAccessor(channel); BroadcastingDispatcher dispatcher = (BroadcastingDispatcher) accessor.getPropertyValue("dispatcher"); dispatcher.setApplySequence(true); dispatcher.addHandler(message -> { }); dispatcher.dispatch(new GenericMessage<>("foo")); DirectFieldAccessor dispatcherAccessor = new DirectFieldAccessor(dispatcher); assertNull(dispatcherAccessor.getPropertyValue("executor")); assertFalse((Boolean) dispatcherAccessor.getPropertyValue("ignoreFailures")); assertTrue((Boolean) dispatcherAccessor.getPropertyValue("applySequence")); Object mbf = this.context.getBean(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME); assertSame(mbf, dispatcherAccessor.getPropertyValue("messageBuilderFactory")); }
/** * 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); }
this.container.addMessageListener(adapter, new ChannelTopic(this.topicName)); this.container.afterPropertiesSet(); this.dispatcher.setBeanFactory(this.getBeanFactory()); this.initialized = true;
public boolean dispatch(Message<?> message) { boolean dispatched = false; int sequenceNumber = 1; List<MessageHandler> handlers = this.getHandlers(); int sequenceSize = handlers.size(); for (final MessageHandler handler : handlers) { final Message<?> messageToSend = (!this.applySequence) ? message : MessageBuilder.fromMessage(message) .setSequenceNumber(sequenceNumber++) .setSequenceSize(sequenceSize) .setCorrelationId(message.getHeaders().getId()) .setHeader(MessageHeaders.ID, UUID.randomUUID()) .build(); if (this.taskExecutor != null) { this.taskExecutor.execute(new Runnable() { public void run() { invokeHandler(handler, messageToSend); } }); dispatched = true; } else { boolean success = this.invokeHandler(handler, messageToSend); dispatched = (success || dispatched); } } return dispatched; }
/** * Specify whether failures for one or more of the handlers should be * ignored. By default this is <code>false</code> meaning that an Exception * will be thrown whenever a handler fails. To override this and suppress * Exceptions, set the value to <code>true</code>. * @param ignoreFailures true if failures should be ignored. */ public void setIgnoreFailures(boolean ignoreFailures) { this.ignoreFailures = ignoreFailures; getDispatcher().setIgnoreFailures(ignoreFailures); }
@Override public boolean unsubscribe(MessageHandler handler) { return this.dispatcher.removeHandler(handler); }
@Override public boolean subscribe(MessageHandler handler) { return this.dispatcher.addHandler(handler); }
@SuppressWarnings({ "unused" }) public void handleMessage(Object payload) { Message<?> siMessage = SubscribableRedisChannel.this.messageConverter.toMessage(payload, null); try { SubscribableRedisChannel.this.dispatcher.dispatch(siMessage); } catch (MessageDispatchingException e) { String exceptionMessage = e.getMessage(); throw new MessageDeliveryException(siMessage, (exceptionMessage == null ? e.getClass().getSimpleName() : exceptionMessage) + " for redis-channel '" + (StringUtils.hasText(SubscribableRedisChannel.this.topicName) ? SubscribableRedisChannel.this.topicName : "unknown") + "' (" + getFullChannelName() + ").", e); // NOSONAR false positive - never null } }
super.onInit(); if (this.executor != null) { Assert.state(getDispatcher().getHandlerCount() == 0, "When providing an Executor, you cannot subscribe() until the channel " + "bean is fully initialized by the framework. Do not subscribe in a @Bean definition"); this.dispatcher = new BroadcastingDispatcher(this.executor); getDispatcher().setIgnoreFailures(this.ignoreFailures); getDispatcher().setApplySequence(this.applySequence); getDispatcher().setMinSubscribers(this.minSubscribers); this.setMaxSubscribers(maxSubscribers); getDispatcher().setBeanFactory(this.getBeanFactory()); getDispatcher().setMessageHandlingTaskDecorator(task -> { if (PublishSubscribeChannel.this.executorInterceptorsSize > 0) { return new MessageHandlingTask(task);
@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 with executor. */ @Test public void testNoHandlerWithExecutor() { dispatcher = new BroadcastingDispatcher(taskExecutorMock); assertTrue(dispatcher.dispatch(messageMock)); }