@Bean public AbstractSubscribableChannel clientInboundChannel() { ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(clientInboundChannelExecutor()); channel.setLogger(SimpLogging.forLog(channel.getLogger())); ChannelRegistration reg = getClientInboundChannelRegistration(); if (reg.hasInterceptors()) { channel.setInterceptors(reg.getInterceptors()); } return channel; }
@Test public void handleMessageFromClientWithImmutableMessageInterceptor() { AtomicReference<Boolean> mutable = new AtomicReference<>(); ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(); channel.addInterceptor(new ChannelInterceptor() { @Override public Message<?> preSend(Message<?> message, MessageChannel channel) { mutable.set(MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class).isMutable()); return message; } }); channel.addInterceptor(new ImmutableMessageChannelInterceptor()); StompSubProtocolHandler handler = new StompSubProtocolHandler(); handler.afterSessionStarted(this.session, channel); TextMessage message = StompTextMessageBuilder.create(StompCommand.CONNECT).build(); handler.handleMessageFromClient(this.session, message, channel); assertNotNull(mutable.get()); assertTrue(mutable.get()); }
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof ExecutorSubscribableChannel) { ExecutorSubscribableChannel original = (ExecutorSubscribableChannel) bean; ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(); channel.setInterceptors(original.getInterceptors()); return channel; } return bean; }
/** * Install or remove an {@link ExecutorChannelInterceptor} that invokes a * completion task once the message is handled. * @param channel the channel to configure * @param preservePublishOrder whether preserve order is on or off based on * which an interceptor is either added or removed. */ static void configureOutboundChannel(MessageChannel channel, boolean preservePublishOrder) { if (preservePublishOrder) { Assert.isInstanceOf(ExecutorSubscribableChannel.class, channel, "An ExecutorSubscribableChannel is required for `preservePublishOrder`"); ExecutorSubscribableChannel execChannel = (ExecutorSubscribableChannel) channel; if (execChannel.getInterceptors().stream().noneMatch(i -> i instanceof CallbackInterceptor)) { execChannel.addInterceptor(0, new CallbackInterceptor()); } } else if (channel instanceof ExecutorSubscribableChannel) { ExecutorSubscribableChannel execChannel = (ExecutorSubscribableChannel) channel; execChannel.getInterceptors().stream().filter(i -> i instanceof CallbackInterceptor) .findFirst() .map(execChannel::removeInterceptor); } }
@Override @Bean public AbstractSubscribableChannel clientInboundChannel() { return new ExecutorSubscribableChannel(); // synchronous }
@Test public void sendWithExecutor() { BeforeHandleInterceptor interceptor = new BeforeHandleInterceptor(); TaskExecutor executor = mock(TaskExecutor.class); ExecutorSubscribableChannel testChannel = new ExecutorSubscribableChannel(executor); testChannel.addInterceptor(interceptor); testChannel.subscribe(this.handler); testChannel.send(this.message); verify(executor).execute(this.runnableCaptor.capture()); verify(this.handler, never()).handleMessage(this.message); this.runnableCaptor.getValue().run(); verify(this.handler).handleMessage(this.message); assertEquals(1, interceptor.getCounter().get()); assertTrue(interceptor.wasAfterHandledInvoked()); }
@Test // SPR-14690 public void handleMessageFromClientWithTokenAuthentication() { ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(); channel.addInterceptor(new AuthenticationInterceptor("__pete__@gmail.com")); channel.addInterceptor(new ImmutableMessageChannelInterceptor()); TestMessageHandler messageHandler = new TestMessageHandler(); channel.subscribe(messageHandler); StompSubProtocolHandler handler = new StompSubProtocolHandler(); handler.afterSessionStarted(this.session, channel); TextMessage wsMessage = StompTextMessageBuilder.create(StompCommand.CONNECT).build(); handler.handleMessageFromClient(this.session, wsMessage, channel); assertEquals(1, messageHandler.getMessages().size()); Message<?> message = messageHandler.getMessages().get(0); Principal user = SimpMessageHeaderAccessor.getUser(message.getHeaders()); assertNotNull(user); assertEquals("__pete__@gmail.com", user.getName()); }
@Test public void sendWithoutExecutor() { BeforeHandleInterceptor interceptor = new BeforeHandleInterceptor(); this.channel.addInterceptor(interceptor); this.channel.subscribe(this.handler); this.channel.send(this.message); verify(this.handler).handleMessage(this.message); assertEquals(1, interceptor.getCounter().get()); assertTrue(interceptor.wasAfterHandledInvoked()); }
@Before public void setup() { this.channel = new ExecutorSubscribableChannel(); this.messageHandler = new TestMessageHandler(); this.channel.subscribe(this.messageHandler); }
@Configuration @EnableWebSocketMessageBroker @EnableReactor public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @autowired Environment reactorEnv; @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry configurer) { configurer.setApplicationDestinationPrefixes("/app"); configurer.enableSimpleBroker("/topic", "/queue"); } @Bean public AbstractSubscribableChannel clientInboundChannel() { ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(new RingBufferAsyncTaskExecutor(this.reactorEnv)); ChannelRegistration reg = getClientOutboundChannelRegistration(); channel.setInterceptors(reg.getInterceptors()); return channel; } }
@Test public void postSendInterceptorMessageWasSent() { final AtomicBoolean preSendInvoked = new AtomicBoolean(false); final AtomicBoolean completionInvoked = new AtomicBoolean(false); this.channel.addInterceptor(new ChannelInterceptor() { @Override public void postSend(Message<?> message, MessageChannel channel, boolean sent) { assertInput(message, channel, sent); preSendInvoked.set(true); } @Override public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) { assertInput(message, channel, sent); completionInvoked.set(true); } private void assertInput(Message<?> message, MessageChannel channel, boolean sent) { assertNotNull(message); assertNotNull(channel); assertSame(ChannelInterceptorTests.this.channel, channel); assertTrue(sent); } }); this.channel.send(MessageBuilder.withPayload("test").build()); assertTrue(preSendInvoked.get()); assertTrue(completionInvoked.get()); }
@Test public void concurrentModification() { this.channel.subscribe(message1 -> channel.unsubscribe(handler)); this.channel.subscribe(this.handler); this.channel.send(this.message); verify(this.handler).handleMessage(this.message); }
@VisibleForTesting public void addInterceptorForUnitTest(ChannelInterceptor theInterceptor) { mySubscribableChannel.addInterceptor(theInterceptor); }
@VisibleForTesting public void clearInterceptorsForUnitTest() { mySubscribableChannel.setInterceptors(new ArrayList<>()); }
@Override public boolean sendInternal(Message<?> message, long timeout) { for (MessageHandler handler : getSubscribers()) { SendTask sendTask = new SendTask(message, handler); if (this.executor == null) { sendTask.run(); } else { this.executor.execute(sendTask); } } return true; }
CountDownLatch latch = new CountDownLatch(1); this.channel.subscribe(message -> { int expected = index.getAndIncrement(); Integer actual = (Integer) message.getHeaders().getOrDefault("seq", -1);
@Override @Bean public AbstractSubscribableChannel clientOutboundChannel() { return new ExecutorSubscribableChannel(); // synchronous } }
@Test public void interceptorWithNull() { BeforeHandleInterceptor interceptor1 = new BeforeHandleInterceptor(); NullReturningBeforeHandleInterceptor interceptor2 = new NullReturningBeforeHandleInterceptor(); this.channel.addInterceptor(interceptor1); this.channel.addInterceptor(interceptor2); this.channel.subscribe(this.handler); this.channel.send(this.message); verifyNoMoreInteractions(this.handler); assertEquals(1, interceptor1.getCounter().get()); assertEquals(1, interceptor2.getCounter().get()); assertTrue(interceptor1.wasAfterHandledInvoked()); }
/** * Install or remove an {@link ExecutorChannelInterceptor} that invokes a * completion task once the message is handled. * @param channel the channel to configure * @param preservePublishOrder whether preserve order is on or off based on * which an interceptor is either added or removed. */ static void configureOutboundChannel(MessageChannel channel, boolean preservePublishOrder) { if (preservePublishOrder) { Assert.isInstanceOf(ExecutorSubscribableChannel.class, channel, "An ExecutorSubscribableChannel is required for `preservePublishOrder`"); ExecutorSubscribableChannel execChannel = (ExecutorSubscribableChannel) channel; if (execChannel.getInterceptors().stream().noneMatch(i -> i instanceof CallbackInterceptor)) { execChannel.addInterceptor(0, new CallbackInterceptor()); } } else if (channel instanceof ExecutorSubscribableChannel) { ExecutorSubscribableChannel execChannel = (ExecutorSubscribableChannel) channel; execChannel.getInterceptors().stream().filter(i -> i instanceof CallbackInterceptor) .findFirst() .map(execChannel::removeInterceptor); } }