GH-2461: RabbitListenerErrorHandler with Async
Resolves https://github.com/spring-projects/spring-amqp/issues/2461
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2022 the original author or authors.
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -385,7 +385,7 @@ public abstract class AbstractAdaptableMessageListener implements ChannelAwareMe
|
||||
basicAck(request, channel);
|
||||
}
|
||||
else {
|
||||
asyncFailure(request, channel, t);
|
||||
asyncFailure(request, channel, t, source);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -396,7 +396,7 @@ public abstract class AbstractAdaptableMessageListener implements ChannelAwareMe
|
||||
}
|
||||
MonoHandler.subscribe(resultArg.getReturnValue(),
|
||||
r -> asyncSuccess(resultArg, request, channel, source, r),
|
||||
t -> asyncFailure(request, channel, t),
|
||||
t -> asyncFailure(request, channel, t, source),
|
||||
() -> basicAck(request, channel));
|
||||
}
|
||||
else {
|
||||
@@ -447,7 +447,7 @@ public abstract class AbstractAdaptableMessageListener implements ChannelAwareMe
|
||||
}
|
||||
}
|
||||
|
||||
private void asyncFailure(Message request, Channel channel, Throwable t) {
|
||||
protected void asyncFailure(Message request, Channel channel, Throwable t, Object source) {
|
||||
this.logger.error("Future, Mono, or suspend function was completed with an exception for " + request, t);
|
||||
try {
|
||||
channel.basicNack(request.getMessageProperties().getDeliveryTag(), false,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -160,6 +160,20 @@ public class MessagingMessageListenerAdapter extends AbstractAdaptableMessageLis
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void asyncFailure(org.springframework.amqp.core.Message request, Channel channel, Throwable t,
|
||||
Object source) {
|
||||
|
||||
try {
|
||||
handleException(request, channel, (Message<?>) source,
|
||||
new ListenerExecutionFailedException("Async Fail", t, request));
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
super.asyncFailure(request, channel, t, source);
|
||||
}
|
||||
|
||||
private void handleException(org.springframework.amqp.core.Message amqpMessage, Channel channel,
|
||||
@Nullable Message<?> message, ListenerExecutionFailedException e) throws Exception { // NOSONAR
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2021 the original author or authors.
|
||||
* Copyright 2018-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -126,7 +126,7 @@ class EnableRabbitKotlinTests {
|
||||
open class Multi {
|
||||
|
||||
@RabbitHandler
|
||||
fun handle(@Suppress("UNUSED_PARAMETER") data: String) {
|
||||
suspend fun handle(@Suppress("UNUSED_PARAMETER") data: String) {
|
||||
throw RuntimeException("fail")
|
||||
}
|
||||
|
||||
|
||||
@@ -3664,6 +3664,9 @@ Starting with version 3.0.5, the `@RabbitListener` (and `@RabbitHandler`) method
|
||||
All the mentioned rules about `AcknowledgeMode.MANUAL` are still apply.
|
||||
The `org.jetbrains.kotlinx:kotlinx-coroutines-reactor` dependency must be present in classpath to allow `suspend` function invocations.
|
||||
|
||||
Also starting with version 3.0.5, if a `RabbitListenerErrorHandler` is configured on a listener with an async return type (including Kotlin suspend functions), the error handler is invoked after a failure.
|
||||
See <<annotation-error-handling>> for more information about this error handler and its purpose.
|
||||
|
||||
[[threading]]
|
||||
===== Threading and Asynchronous Consumers
|
||||
|
||||
|
||||
@@ -48,9 +48,12 @@ See <<Jackson2JsonMessageConverter-from-message>> for more information
|
||||
You can now configure a `ReplyPostProcessor` via the container factory rather than via a property on `@RabbitListener`.
|
||||
See <<async-annotation-driven-reply>> for more information.
|
||||
|
||||
The `@RabbitListener` (and `@RabbitHandler`) methods can now be as a Kotlin `suspend` functions.
|
||||
The `@RabbitListener` (and `@RabbitHandler`) methods can now be declared as Kotlin `suspend` functions.
|
||||
See <<async-returns>> for more information.
|
||||
|
||||
Starting with version 3.0.5, listeners with async return types (including Kotlin suspend functions) invoke the `RabbitListenerErrorHandler` (if configured) after a failure.
|
||||
Previously, the error handler was only invoked with synchronous invocations.
|
||||
|
||||
==== Connection Factory Changes
|
||||
|
||||
The default `addressShuffleMode` in `AbstractConnectionFactory` is now `RANDOM`.
|
||||
|
||||
Reference in New Issue
Block a user