private void sendInternal(Message<?> message) { String destination = SimpMessageHeaderAccessor.getDestination(message.getHeaders()); Assert.notNull(destination, "Destination header required"); long timeout = this.sendTimeout; boolean sent = (timeout >= 0 ? this.messageChannel.send(message, timeout) : this.messageChannel.send(message)); if (!sent) { throw new MessageDeliveryException(message, "Failed to send message to destination '" + destination + "' within timeout: " + timeout); } }
private MessageHandler createLateReplier(final CountDownLatch latch, final AtomicReference<Throwable> failure) { MessageHandler handler = message -> { try { Thread.sleep(500); MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel(); replyChannel.send(new GenericMessage<>("response")); failure.set(new IllegalStateException("Expected exception")); } catch (InterruptedException e) { failure.set(e); } catch (MessageDeliveryException ex) { String expected = "Reply message received but the receiving thread has exited due to a timeout"; String actual = ex.getMessage(); if (!expected.equals(actual)) { failure.set(new IllegalStateException( "Unexpected error: '" + actual + "'")); } } finally { latch.countDown(); } }; return handler; }
@Test public void simpleRegistryMappings() { loadConfig(SockJsSecurityConfig.class); clientInboundChannel().send(message("/permitAll")); try { clientInboundChannel().send(message("/denyAll")); fail("Expected Exception"); } catch (MessageDeliveryException expected) { assertThat(expected.getCause()).isInstanceOf(AccessDeniedException.class); } }
@Test public void errorChannelHeaderAndHandlerThrowsExceptionWithDelay() { this.delayHandler.setRetryDelay(1); DirectChannel errorChannel = new DirectChannel(); MessagePublishingErrorHandler errorHandler = new MessagePublishingErrorHandler(); errorHandler.setDefaultErrorChannel(errorChannel); taskScheduler.setErrorHandler(errorHandler); this.setDelayExpression(); startDelayerHandler(); output.unsubscribe(resultHandler); errorChannel.subscribe(resultHandler); output.subscribe(message -> { throw new UnsupportedOperationException("intentional test failure"); }); Message<?> message = MessageBuilder.withPayload("test") .setHeader("delay", "10") .setErrorChannel(errorChannel).build(); input.send(message); waitForLatch(10000); Message<?> errorMessage = resultHandler.lastMessage; assertEquals(MessageDeliveryException.class, errorMessage.getPayload().getClass()); MessageDeliveryException exceptionPayload = (MessageDeliveryException) errorMessage.getPayload(); assertSame(message.getPayload(), exceptionPayload.getFailedMessage().getPayload()); assertEquals(UnsupportedOperationException.class, exceptionPayload.getCause().getClass()); assertNotSame(Thread.currentThread(), resultHandler.lastThread); }
@Test public void testPriorityChannelWithIntegerDatatypeEnforced() { PollableChannel channel = this.context.getBean("integerOnlyPriorityChannel", PollableChannel.class); channel.send(new GenericMessage<>(3)); channel.send(new GenericMessage<>(2)); channel.send(new GenericMessage<>(1)); assertEquals(1, channel.receive(0).getPayload()); assertEquals(2, channel.receive(0).getPayload()); assertEquals(3, channel.receive(0).getPayload()); boolean threwException = false; try { channel.send(new GenericMessage<>("wrong type")); } catch (MessageDeliveryException e) { assertEquals("wrong type", e.getFailedMessage().getPayload()); threwException = true; } assertTrue(threwException); }
@Test public void defaultErrorChannelAndHandlerThrowsExceptionWithDelay() { this.delayHandler.setRetryDelay(1); StaticApplicationContext context = new StaticApplicationContext(); context.registerSingleton(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME, DirectChannel.class); context.refresh(); DirectChannel defaultErrorChannel = (DirectChannel) context .getBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME); MessagePublishingErrorHandler errorHandler = new MessagePublishingErrorHandler(); errorHandler.setBeanFactory(context); taskScheduler.setErrorHandler(errorHandler); this.setDelayExpression(); startDelayerHandler(); output.unsubscribe(resultHandler); defaultErrorChannel.subscribe(resultHandler); output.subscribe(message -> { throw new UnsupportedOperationException("intentional test failure"); }); Message<?> message = MessageBuilder.withPayload("test") .setHeader("delay", "10").build(); input.send(message); waitForLatch(10000); Message<?> errorMessage = resultHandler.lastMessage; assertEquals(MessageDeliveryException.class, errorMessage.getPayload().getClass()); MessageDeliveryException exceptionPayload = (MessageDeliveryException) errorMessage.getPayload(); assertSame(message.getPayload(), exceptionPayload.getFailedMessage().getPayload()); assertEquals(UnsupportedOperationException.class, exceptionPayload.getCause().getClass()); assertNotSame(Thread.currentThread(), resultHandler.lastThread); }
assertThat(cause, instanceOf(MessageDeliveryException.class)); MessageDeliveryException messageDeliveryException = (MessageDeliveryException) cause; Message<?> failedMessage = messageDeliveryException.getFailedMessage(); assertThat((String) failedMessage.getPayload(), containsString("preSend intentional Exception"));
@Override public boolean send(Message<?> message, long timeout) { this.replyMessage = message; boolean alreadyReceivedReply = this.hasReceived; this.replyLatch.countDown(); String errorDescription = null; if (this.hasTimedOut) { errorDescription = "Reply message received but the receiving thread has exited due to a timeout"; } else if (alreadyReceivedReply) { errorDescription = "Reply message received but the receiving thread has already received a reply"; } else if (this.hasSendFailed) { errorDescription = "Reply message received but the receiving thread has exited due to " + "an exception while sending the request message"; } if (errorDescription != null) { if (logger.isWarnEnabled()) { logger.warn(errorDescription + ":" + message); } if (this.throwExceptionOnLateReply) { throw new MessageDeliveryException(message, errorDescription); } } return true; } }
@Override public String getMessage() { String baseMessage = super.getMessage(); StringBuilder message = new StringBuilder(appendPeriodIfNecessary(baseMessage) + " Multiple causes:\n"); for (Exception exception : this.aggregatedExceptions) { message.append(" " + exception.getMessage() + "\n"); } message.append("See below for the stacktrace of the first cause."); return message.toString(); }
@Test public void msmsRegistryCustomPatternMatcher() throws Exception { loadConfig(MsmsRegistryCustomPatternMatcherConfig.class); clientInboundChannel().send(message("/app/a.b")); try { clientInboundChannel().send(message("/app/a.b.c")); fail("Expected Exception"); } catch (MessageDeliveryException expected) { assertThat(expected.getCause()).isInstanceOf(AccessDeniedException.class); } }
assertEquals(MessageDeliveryException.class, errorMessage.getPayload().getClass()); MessageDeliveryException exceptionPayload = (MessageDeliveryException) errorMessage.getPayload(); assertSame(message.getPayload(), exceptionPayload.getFailedMessage().getPayload()); assertEquals(UnsupportedOperationException.class, exceptionPayload.getCause().getClass()); assertNotSame(Thread.currentThread(), resultHandler.lastThread);
@Test public void validateSuccessfulErrorFlowDoesNotThrowErrors() { this.context.refresh(); DirectChannel outChannel = new DirectChannel(); outChannel.subscribe(message -> { throw new RuntimeException("problems"); }); PublishSubscribeChannel errorChannel = new PublishSubscribeChannel(); SuccessfulErrorService errorService = new SuccessfulErrorService(); ServiceActivatingHandler handler = new ServiceActivatingHandler(errorService); handler.setBeanFactory(this.context); handler.afterPropertiesSet(); errorChannel.subscribe(handler); MessageProducerSupport mps = new MessageProducerSupport() { }; mps.setOutputChannel(outChannel); mps.setErrorChannel(errorChannel); mps.setBeanFactory(this.context); mps.afterPropertiesSet(); mps.start(); Message<?> message = new GenericMessage<>("hello"); mps.sendMessage(message); assertThat(errorService.lastMessage, instanceOf(ErrorMessage.class)); ErrorMessage errorMessage = (ErrorMessage) errorService.lastMessage; assertEquals(MessageDeliveryException.class, errorMessage.getPayload().getClass()); MessageDeliveryException exception = (MessageDeliveryException) errorMessage.getPayload(); assertEquals(message, exception.getFailedMessage()); }
private void execute(Message<byte[]> message) { if (logger.isTraceEnabled()) { StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); if (accessor != null) { logger.trace("Sending " + accessor.getDetailedLogMessage(message.getPayload())); } } TcpConnection<byte[]> conn = this.connection; Assert.state(conn != null, "Connection closed"); try { conn.send(message).get(); } catch (ExecutionException ex) { throw new MessageDeliveryException(message, ex.getCause()); } catch (Throwable ex) { throw new MessageDeliveryException(message, ex); } }
@SuppressWarnings("unchecked") @Test public void testPtP() throws Exception { final Channel channel = mock(Channel.class); DeclareOk declareOk = mock(DeclareOk.class); when(declareOk.getQueue()).thenReturn("noSubscribersChannel"); when(channel.queueDeclare(anyString(), anyBoolean(), anyBoolean(), anyBoolean(), isNull())) .thenReturn(declareOk); Connection connection = mock(Connection.class); doAnswer(invocation -> channel).when(connection).createChannel(anyBoolean()); ConnectionFactory connectionFactory = mock(ConnectionFactory.class); when(connectionFactory.createConnection()).thenReturn(connection); SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); container.setConnectionFactory(connectionFactory); AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); PointToPointSubscribableAmqpChannel amqpChannel = new PointToPointSubscribableAmqpChannel("noSubscribersChannel", container, amqpTemplate); amqpChannel.setBeanName("noSubscribersChannel"); amqpChannel.setBeanFactory(mock(BeanFactory.class)); amqpChannel.afterPropertiesSet(); MessageListener listener = (MessageListener) container.getMessageListener(); try { listener.onMessage(new Message("Hello world!".getBytes(), null)); fail("Exception expected"); } catch (MessageDeliveryException e) { assertThat(e.getMessage(), containsString("Dispatcher has no subscribers for amqp-channel 'noSubscribersChannel'.")); } }
@Test public void overrideMsmsRegistryCustomPatternMatcher() throws Exception { loadConfig(OverrideMsmsRegistryCustomPatternMatcherConfig.class); clientInboundChannel().send(message("/app/a/b")); try { clientInboundChannel().send(message("/app/a/b/c")); fail("Expected Exception"); } catch (MessageDeliveryException expected) { assertThat(expected.getCause()).isInstanceOf(AccessDeniedException.class); } }
@Override public ListenableFuture<Void> forward(Message<?> message, StompHeaderAccessor accessor) { try { ListenableFuture<Void> future = super.forward(message, accessor); if (message.getHeaders().get(SimpMessageHeaderAccessor.IGNORE_ERROR) == null) { future.get(); } return future; } catch (Throwable ex) { throw new MessageDeliveryException(message, ex); } } }
@Test public void testMultiRouter() { Message<String> fooMessage = new GenericMessage<>("foo"); Message<String> barMessage = new GenericMessage<>("bar"); Message<String> badMessage = new GenericMessage<>("bad"); this.routerMultiInput.send(fooMessage); Message<?> result1a = this.fooChannel.receive(2000); assertNotNull(result1a); assertEquals("foo", result1a.getPayload()); Message<?> result1b = this.barChannel.receive(2000); assertNotNull(result1b); assertEquals("foo", result1b.getPayload()); this.routerMultiInput.send(barMessage); Message<?> result2a = this.fooChannel.receive(2000); assertNotNull(result2a); assertEquals("bar", result2a.getPayload()); Message<?> result2b = this.barChannel.receive(2000); assertNotNull(result2b); assertEquals("bar", result2b.getPayload()); try { this.routerMultiInput.send(badMessage); fail("MessageDeliveryException expected."); } catch (MessageDeliveryException e) { assertThat(e.getMessage(), containsString("No channel resolved by router")); } }
@Test public void defaultPatternMatcher() throws Exception { loadConfig(DefaultPatternMatcherConfig.class); clientInboundChannel().send(message("/app/a/b")); try { clientInboundChannel().send(message("/app/a/b/c")); fail("Expected Exception"); } catch (MessageDeliveryException expected) { assertThat(expected.getCause()).isInstanceOf(AccessDeniedException.class); } }
@Override public void run() { Message<?> message = this.inputMessage; try { message = applyBeforeHandle(message); if (message == null) { return; } this.messageHandler.handleMessage(message); triggerAfterMessageHandled(message, null); } catch (Exception ex) { triggerAfterMessageHandled(message, ex); if (ex instanceof MessagingException) { throw (MessagingException) ex; } String description = "Failed to handle " + message + " to " + this + " in " + this.messageHandler; throw new MessageDeliveryException(message, description, ex); } catch (Throwable err) { String description = "Failed to handle " + message + " to " + this + " in " + this.messageHandler; MessageDeliveryException ex2 = new MessageDeliveryException(message, description, err); triggerAfterMessageHandled(message, ex2); throw ex2; } }
@Test public void testMethodInvokingRouter() { Message<String> fooMessage = new GenericMessage<>("foo"); Message<String> barMessage = new GenericMessage<>("bar"); Message<String> badMessage = new GenericMessage<>("bad"); this.routerMethodInput.send(fooMessage); Message<?> result1a = this.fooChannel.receive(2000); assertNotNull(result1a); assertEquals("foo", result1a.getPayload()); assertNull(this.barChannel.receive(0)); this.routerMethodInput.send(barMessage); assertNull(this.fooChannel.receive(0)); Message<?> result2b = this.barChannel.receive(2000); assertNotNull(result2b); assertEquals("bar", result2b.getPayload()); try { this.routerMethodInput.send(badMessage); fail("MessageDeliveryException expected."); } catch (MessageDeliveryException e) { assertThat(e.getMessage(), containsString("No channel resolved by router")); } }