@Override protected ExecutorChannel doGet() { this.channel = new ExecutorChannel(this.executor, this.loadBalancingStrategy); if (this.failover != null) { this.channel.setFailover(this.failover); } if (this.maxSubscribers != null) { this.channel.setMaxSubscribers(this.maxSubscribers); } return super.doGet(); }
/** * Specify whether the channel's dispatcher should have failover enabled. * By default, it will. Set this value to 'false' to disable it. * @param failover The failover boolean. */ public void setFailover(boolean failover) { this.failover = failover; getDispatcher().setFailover(failover); }
@Test public void testEarlySubscribe() { ExecutorChannel channel = new ExecutorChannel(mock(Executor.class)); try { channel.subscribe(m -> { }); channel.setBeanFactory(mock(BeanFactory.class)); channel.afterPropertiesSet(); fail("expected Exception"); } catch (IllegalStateException e) { assertThat(e.getMessage(), equalTo("You cannot subscribe() until the channel " + "bean is fully initialized by the framework. Do not subscribe in a @Bean definition")); } }
@Test public void testExecutorChannelLoggingWithMoreThenOneSubscriber() { final ExecutorChannel channel = new ExecutorChannel(mock(Executor.class)); channel.setBeanName("executorChannel"); final Log logger = mock(Log.class); when(logger.isInfoEnabled()).thenReturn(true); ReflectionUtils.doWithFields(AbstractMessageChannel.class, field -> { if ("logger".equals(field.getName())) { field.setAccessible(true); field.set(channel, logger); } }); channel.subscribe(mock(MessageHandler.class)); channel.subscribe(mock(MessageHandler.class)); verify(logger, times(2)).info(Mockito.anyString()); }
@Test public void verifyDifferentThread() throws Exception { SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); taskExecutor.setThreadNamePrefix("test-"); ExecutorChannel channel = new ExecutorChannel(taskExecutor); CountDownLatch latch = new CountDownLatch(1); TestHandler handler = new TestHandler(latch); channel.subscribe(handler); channel.send(new GenericMessage<String>("test")); latch.await(1000, TimeUnit.MILLISECONDS); assertEquals(0, latch.getCount()); assertNotNull(handler.thread); assertFalse(Thread.currentThread().equals(handler.thread)); assertEquals("test-1", handler.thread.getName()); }
@Bean @BridgeTo("securedChannelQueue") public SubscribableChannel executorChannel() { return new ExecutorChannel(Executors.newSingleThreadExecutor()); }
@Override public final void onInit() { Assert.state(getDispatcher().getHandlerCount() == 0, "You cannot subscribe() until the channel " + "bean is fully initialized by the framework. Do not subscribe in a @Bean definition"); super.onInit(); if (!(this.executor instanceof ErrorHandlingTaskExecutor)) { ErrorHandler errorHandler = new MessagePublishingErrorHandler( new BeanFactoryChannelResolver(this.getBeanFactory())); this.executor = new ErrorHandlingTaskExecutor(this.executor, errorHandler); } UnicastingDispatcher unicastingDispatcher = new UnicastingDispatcher(this.executor); unicastingDispatcher.setFailover(this.failover); if (this.maxSubscribers == null) { this.maxSubscribers = getIntegrationProperty(IntegrationProperties.CHANNELS_MAX_UNICAST_SUBSCRIBERS, Integer.class); } unicastingDispatcher.setMaxSubscribers(this.maxSubscribers); if (this.loadBalancingStrategy != null) { unicastingDispatcher.setLoadBalancingStrategy(this.loadBalancingStrategy); } unicastingDispatcher.setMessageHandlingTaskDecorator(task -> { if (ExecutorChannel.this.executorInterceptorsSize > 0) { return new MessageHandlingTask(task); } else { return task; } }); this.dispatcher = unicastingDispatcher; }
private synchronized ExecutorChannel findOrCreateRequestReplyChannel(String name, String prefix, Properties properties) { String channelName = prefix + name; ExecutorChannel channel = this.requestReplyChannels.get(channelName); if (channel == null) { ThreadPoolTaskExecutor executor = createRequestReplyExecutor(name, properties); channel = new ExecutorChannel(executor); channel.setBeanFactory(getBeanFactory()); this.requestReplyChannels.put(channelName, channel); this.reqRepExecutors.put(name, executor); } return channel; }
throws Exception { final ExecutorChannel channel = (ExecutorChannel) ac.getBean("noLoadBalancerNoFailoverExecutor"); UnicastingDispatcher dispatcher = channel.getDispatcher(); dispatcher.addHandler(handlerA); dispatcher.addHandler(handlerB); Thread.currentThread().interrupt(); channel.send(message); }; for (int i = 0; i < TOTAL_EXECUTIONS; i++) {
@Test public void testProxyExecutor() throws Exception { assertTrue(AopUtils.isCglibProxy(this.executorChannel)); final AtomicReference<Message<?>> message = new AtomicReference<>(); final CountDownLatch latch = new CountDownLatch(1); this.executorChannel.subscribe(m -> { message.set(m); latch.countDown(); }); this.executorChannel.send(new GenericMessage<>("foo")); assertTrue(latch.await(10, TimeUnit.SECONDS)); assertNotNull(message.get()); }
@Override public void bindRequestor(final String name, MessageChannel requests, final MessageChannel replies, Properties properties) { validateConsumerProperties(name, properties, CONSUMER_REQUEST_REPLY_PROPERTIES); final MessageChannel requestChannel = this.findOrCreateRequestReplyChannel(name, "requestor.", properties); // TODO: handle Pollable ? Assert.isInstanceOf(SubscribableChannel.class, requests); ((SubscribableChannel) requests).subscribe(new MessageHandler() { @Override public void handleMessage(Message<?> message) throws MessagingException { requestChannel.send(message); } }); ExecutorChannel replyChannel = this.findOrCreateRequestReplyChannel(name, "replier.", properties); replyChannel.subscribe(new MessageHandler() { @Override public void handleMessage(Message<?> message) throws MessagingException { replies.send(message); } }); }
.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("test-")); ConcurrentTaskExecutor taskExecutor = new ConcurrentTaskExecutor(exec); ExecutorChannel channel = new ExecutorChannel(taskExecutor, null); CountDownLatch latch = new CountDownLatch(numberOfMessages); TestHandler handler1 = new TestHandler(latch); TestHandler handler2 = new TestHandler(latch); TestHandler handler3 = new TestHandler(latch); channel.subscribe(handler1); channel.subscribe(handler2); channel.subscribe(handler3); handler1.shouldFail = true; for (int i = 0; i < numberOfMessages; i++) { channel.send(new GenericMessage<String>("test-" + i));
@Bean public ProxyFactoryBean executorChannel() { return createProxyFactory(new ExecutorChannel(executor())); }
@Override public final void onInit() { Assert.state(getDispatcher().getHandlerCount() == 0, "You cannot subscribe() until the channel " + "bean is fully initialized by the framework. Do not subscribe in a @Bean definition"); super.onInit(); if (!(this.executor instanceof ErrorHandlingTaskExecutor)) { ErrorHandler errorHandler = new MessagePublishingErrorHandler( new BeanFactoryChannelResolver(this.getBeanFactory())); this.executor = new ErrorHandlingTaskExecutor(this.executor, errorHandler); } UnicastingDispatcher unicastingDispatcher = new UnicastingDispatcher(this.executor); unicastingDispatcher.setFailover(this.failover); if (this.maxSubscribers == null) { this.maxSubscribers = getIntegrationProperty(IntegrationProperties.CHANNELS_MAX_UNICAST_SUBSCRIBERS, Integer.class); } unicastingDispatcher.setMaxSubscribers(this.maxSubscribers); if (this.loadBalancingStrategy != null) { unicastingDispatcher.setLoadBalancingStrategy(this.loadBalancingStrategy); } unicastingDispatcher.setMessageHandlingTaskDecorator(task -> { if (ExecutorChannel.this.executorInterceptorsSize > 0) { return new MessageHandlingTask(task); } else { return task; } }); this.dispatcher = unicastingDispatcher; }
@Test public void failoverNoLoadBalancingWithExecutorConcurrent() throws Exception { final ExecutorChannel channel = (ExecutorChannel) ac.getBean("noLoadBalancerFailoverExecutor"); final UnicastingDispatcher dispatcher = channel.getDispatcher(); dispatcher.addHandler(handlerA); dispatcher.addHandler(handlerB); Thread.currentThread().interrupt(); channel.send(message); }; for (int i = 0; i < TOTAL_EXECUTIONS; i++) {
@Override protected ExecutorChannel doGet() { this.channel = new ExecutorChannel(this.executor, this.loadBalancingStrategy); if (this.failover != null) { this.channel.setFailover(this.failover); } if (this.maxSubscribers != null) { this.channel.setMaxSubscribers(this.maxSubscribers); } return super.doGet(); }
@Test public void interceptorWithModifiedMessage() { ExecutorChannel channel = new ExecutorChannel(new SyncTaskExecutor()); channel.setBeanFactory(mock(BeanFactory.class)); channel.afterPropertiesSet(); MessageHandler handler = mock(MessageHandler.class); Message<?> expected = mock(Message.class); BeforeHandleInterceptor interceptor = new BeforeHandleInterceptor(); interceptor.setMessageToReturn(expected); channel.addInterceptor(interceptor); channel.subscribe(handler); channel.send(new GenericMessage<Object>("foo")); verify(handler).handleMessage(expected); assertEquals(1, interceptor.getCounter().get()); assertTrue(interceptor.wasAfterHandledInvoked()); }
.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("test-")); ConcurrentTaskExecutor taskExecutor = new ConcurrentTaskExecutor(exec); ExecutorChannel channel = new ExecutorChannel( taskExecutor, new RoundRobinLoadBalancingStrategy()); CountDownLatch latch = new CountDownLatch(numberOfMessages); TestHandler handler2 = new TestHandler(latch); TestHandler handler3 = new TestHandler(latch); channel.subscribe(handler1); channel.subscribe(handler2); channel.subscribe(handler3); for (int i = 0; i < numberOfMessages; i++) { channel.send(new GenericMessage<String>("test-" + i));
@Test public void noFailoverLoadBalancingWithExecutorConcurrent() throws Exception { final ExecutorChannel channel = (ExecutorChannel) ac.getBean("loadBalancerNoFailoverExecutor"); UnicastingDispatcher dispatcher = channel.getDispatcher(); dispatcher.addHandler(handlerA); dispatcher.addHandler(handlerB); Thread.currentThread().interrupt(); channel.send(message); }; for (int i = 0; i < TOTAL_EXECUTIONS; i++) {
/** * Specify whether the channel's dispatcher should have failover enabled. * By default, it will. Set this value to 'false' to disable it. * @param failover The failover boolean. */ public void setFailover(boolean failover) { this.failover = failover; getDispatcher().setFailover(failover); }