例外の処理
デフォルトでは、アノテーション付きのリスナーメソッドが例外をスローすると、コンテナーにスローされ、コンテナーとブローカーの構成に応じて、メッセージが再キューイングされ、再配信、破棄、デッドレター交換にルーティングされます。送信者には何も返されません。
バージョン 2.0 以降、@RabbitListener
アノテーションには errorHandler
と returnExceptions
という 2 つの新しい属性があります。
これらはデフォルトでは構成されていません。
errorHandler
を使用して、RabbitListenerErrorHandler
実装の Bean 名を指定できます。この関数インターフェースには、次の 1 つのメソッドがあります。
@FunctionalInterface
public interface RabbitListenerErrorHandler {
Object handleError(Message amqpMessage, org.springframework.messaging.Message<?> message,
ListenerExecutionFailedException exception) throws Exception;
}
ご覧のとおり、コンテナーから受信した生のメッセージ、メッセージコンバーターによって生成された spring-messaging Message<?>
オブジェクト、およびリスナーによってスローされた ( ListenerExecutionFailedException
にラップされた) 例外にアクセスできます。エラーハンドラーは、結果を返す (応答として送信される) か、元の例外または新しい例外をスローする (returnExceptions
設定に応じて、コンテナーにスローされるか、送信者に返される) ことができます。
returnExceptions
属性が true
の場合、送信者に例外が返されます。例外は RemoteInvocationResult
オブジェクトにラップされます。送信者側には、使用可能な RemoteInvocationAwareMessageConverterAdapter
があり、RabbitTemplate
に構成されている場合、サーバー側の例外を再スローし、AmqpRemoteException
にラップされます。サーバー例外のスタックトレースは、サーバーとクライアントのスタックトレースをマージすることによって合成されます。
このメカニズムは通常、Java シリアライゼーションを使用するデフォルトの SimpleMessageConverter でのみ機能します。通常、例外は「Jackson フレンドリー」ではなく、JSON に直列化できません。JSON を使用する場合は、errorHandler を使用して、例外がスローされたときに他の Jackson に適した Error オブジェクトを返すことを検討してください。 |
バージョン 2.1 では、このインターフェースはパッケージ o.s.amqp.rabbit.listener から o.s.amqp.rabbit.listener.api に移動しました。 |
バージョン 2.1.7 以降では、メッセージングメッセージヘッダーで Channel
が使用可能です。これにより、AcknowledgeMode.MANUAL
を使用するときに失敗したメッセージを確認または拒否することができます。
public Object handleError(Message amqpMessage, org.springframework.messaging.Message<?> message,
ListenerExecutionFailedException exception) {
...
message.getHeaders().get(AmqpHeaders.CHANNEL, Channel.class)
.basicReject(message.getHeaders().get(AmqpHeaders.DELIVERY_TAG, Long.class),
true);
}
バージョン 2.2.18 以降では、メッセージ変換例外がスローされた場合、エラーハンドラーが呼び出され、message
引数に null
が指定されます。これにより、アプリケーションは何らかの結果を呼び出し元に送信して、不適切な形式のメッセージを受信したことを示すことができます。以前は、このようなエラーはコンテナーによってスローされ、処理されていました。