/** * @param e The Exception. * @param message The failed message. * @return If 'e' is of type {@link ListenerExecutionFailedException} - return 'e' as it is, otherwise wrap it to * {@link ListenerExecutionFailedException} and return. */ protected ListenerExecutionFailedException wrapToListenerExecutionFailedExceptionIfNeeded(Exception e, Message message) { if (!(e instanceof ListenerExecutionFailedException)) { // Wrap exception to ListenerExecutionFailedException. return new ListenerExecutionFailedException("Listener threw exception", e, message); } return (ListenerExecutionFailedException) e; }
@Override public boolean isFatal(Throwable t) { Throwable cause = t.getCause(); while (cause instanceof MessagingException && !(cause instanceof org.springframework.messaging.converter.MessageConversionException) && !(cause instanceof MethodArgumentResolutionException)) { cause = cause.getCause(); } if (t instanceof ListenerExecutionFailedException && isCauseFatal(cause)) { if (this.logger.isWarnEnabled()) { this.logger.warn( "Fatal message conversion error; message rejected; " + "it will be dropped or routed to a dead letter exchange, if so configured: " + ((ListenerExecutionFailedException) t).getFailedMessage()); } return true; } return false; }
@Bean public RabbitListenerErrorHandler throwANewException() { return (m, sm, e) -> { throw new RuntimeException("from error handler", e.getCause()); }; }
if (messageIn.getMessageProperties().isFinalRetryForMessageWithNoId()) { if (this.statefulRetryFatalWithNullMessageId) { throw new FatalListenerExecutionException( "Illegal null id in message. Failed to manage retry for message: " + messageIn, ex); throw new ListenerExecutionFailedException("Cannot retry message more than once without an ID", new AmqpRejectAndDontRequeueException("Not retryable; rejecting and not requeuing", ex), messageIn);
if (ex.getCause() instanceof NoSuchMethodException) { throw new FatalListenerExecutionException("Invalid listener", ex);
@Override public void onMessage(Message message, Channel channel) throws Exception { String value = new String(message.getBody()); logger.info("Receiving: " + value); if (failed.compareAndSet(false, true)) { // intentional error (causes exception on connection thread): // channel.abort(); // throw new RuntimeException("Planned"); throw new FatalListenerExecutionException("Planned"); } else { latch.countDown(); } } }
throw new FatalListenerStartupException("Mismatched queues", e);
/** * @param e The Exception. * @param message The failed message. * @return If 'e' is of type {@link ListenerExecutionFailedException} - return 'e' as it is, otherwise wrap it to * {@link ListenerExecutionFailedException} and return. */ protected ListenerExecutionFailedException wrapToListenerExecutionFailedExceptionIfNeeded(Exception e, Message message) { if (!(e instanceof ListenerExecutionFailedException)) { // Wrap exception to ListenerExecutionFailedException. return new ListenerExecutionFailedException("Listener threw exception", e, message); } return (ListenerExecutionFailedException) e; }
if (messageIn.getMessageProperties().isFinalRetryForMessageWithNoId()) { if (this.statefulRetryFatalWithNullMessageId) { throw new FatalListenerExecutionException( "Illegal null id in message. Failed to manage retry for message: " + messageIn, ex); throw new ListenerExecutionFailedException("Cannot retry message more than once without an ID", new AmqpRejectAndDontRequeueException("Not retryable; rejecting and not requeuing", ex), messageIn);
if (ex.getCause() instanceof NoSuchMethodException) { throw new FatalListenerExecutionException("Invalid listener", ex);
@Override public boolean isFatal(Throwable t) { Throwable cause = t.getCause(); while (cause instanceof MessagingException && !(cause instanceof org.springframework.messaging.converter.MessageConversionException) && !(cause instanceof MethodArgumentResolutionException)) { cause = cause.getCause(); } if (t instanceof ListenerExecutionFailedException && isCauseFatal(cause)) { if (this.logger.isWarnEnabled()) { this.logger.warn( "Fatal message conversion error; message rejected; " + "it will be dropped or routed to a dead letter exchange, if so configured: " + ((ListenerExecutionFailedException) t).getFailedMessage()); } return true; } return false; }
setAttributesIfNecessary(message, null); getMessagingTemplate().send(getErrorChannel(), buildErrorMessage(null, new ListenerExecutionFailedException("Message conversion failed", e, message)));
@Override public boolean isFatal(Throwable t) { if (t instanceof ListenerExecutionFailedException) { ListenerExecutionFailedException lefe = (ListenerExecutionFailedException) t; logger.error("Failed to process inbound message from queue " + lefe.getFailedMessage().getMessageProperties().getConsumerQueue() + "; failed message: " + lefe.getFailedMessage(), t); } return super.isFatal(t); }
setAttributesIfNecessary(message, null); AmqpInboundGateway.this.messagingTemplate.send(errorChannel, buildErrorMessage(null, new ListenerExecutionFailedException("Message conversion failed", e, message)));
@Override public void recover(Message message, Throwable cause) { if (this.logger.isWarnEnabled()) { this.logger.warn("Retries exhausted for message " + message, cause); } throw new ListenerExecutionFailedException("Retry Policy Exhausted", new AmqpRejectAndDontRequeueException(cause), message); }
@Override public void recover(Message message, Throwable cause) { if (this.logger.isWarnEnabled()) { this.logger.warn("Retries exhausted for message " + message, cause); } throw new ListenerExecutionFailedException("Retry Policy Exhausted", new AmqpRejectAndDontRequeueException(cause), message); }
/** * Invoke the handler, wrapping any exception to a {@link ListenerExecutionFailedException} * with a dedicated error message. * @param amqpMessage the raw message. * @param channel the channel. * @param message the messaging message. * @return the result of invoking the handler. */ private InvocationResult invokeHandler(org.springframework.amqp.core.Message amqpMessage, Channel channel, Message<?> message) { try { return this.handlerAdapter.invoke(message, amqpMessage, channel); } catch (MessagingException ex) { throw new ListenerExecutionFailedException(createMessagingErrorMessage("Listener method could not " + "be invoked with the incoming message", message.getPayload()), ex, amqpMessage); } catch (Exception ex) { throw new ListenerExecutionFailedException("Listener method '" + this.handlerAdapter.getMethodAsString(message.getPayload()) + "' threw exception", ex, amqpMessage); } }
/** * Invoke the handler, wrapping any exception to a {@link ListenerExecutionFailedException} * with a dedicated error message. * @param amqpMessage the raw message. * @param channel the channel. * @param message the messaging message. * @return the result of invoking the handler. */ private InvocationResult invokeHandler(org.springframework.amqp.core.Message amqpMessage, Channel channel, Message<?> message) { try { return this.handlerAdapter.invoke(message, amqpMessage, channel); } catch (MessagingException ex) { throw new ListenerExecutionFailedException(createMessagingErrorMessage("Listener method could not " + "be invoked with the incoming message", message.getPayload()), ex, amqpMessage); } catch (Exception ex) { throw new ListenerExecutionFailedException("Listener method '" + this.handlerAdapter.getMethodAsString(message.getPayload()) + "' threw exception", ex, amqpMessage); } }
@Test public void testErrorHandlerListenerExecutionFailedExceptionFromListener() throws Exception { int messageCount = 3; CountDownLatch latch = new CountDownLatch(messageCount); doTest(messageCount, errorHandler, latch, new ThrowingExceptionListener(latch, new ListenerExecutionFailedException("Listener throws specific runtime exception", null, mock(Message.class)))); }
private void doTest(Throwable cause) { ConditionalRejectingErrorHandler handler = new ConditionalRejectingErrorHandler(); handler.handleError( new ListenerExecutionFailedException("test", cause, new org.springframework.amqp.core.Message(new byte[0], new MessageProperties()))); }