1. 概要

RESTfulサービスは、さまざまな理由で失敗する可能性があります。 このチュートリアルでは、統合されたRESTサービスがエラーをスローした場合に、Feignクライアントから元のメッセージを取得する方法を見ていきます。

2. 偽のクライアント

Feignは、プラグイン可能で宣言型のWebサービスクライアントであり、Webサービスクライアントの作成を容易にします。 さらに、Feignアノテーションに対して、 JAX-RS もサポートし、エンコーダーとデコーダーをサポートして、より多くのカスタマイズを提供します

3. ErrorDecoderからのメッセージの取得

エラーが発生した場合、 Feignクライアントは元のメッセージを抑制し、それを取得するには、カスタム ErrorDecoder を作成する必要があります。このようなカスタマイズがない場合、次のエラーが発生します。

feign.FeignException$NotFound: [404] during [POST] to [http://localhost:8080/upload-error-1] [UploadClient#fileUploadError(MultipartFile)]: [{"timestamp":"2022-02-18T13:25:22.083+00:00","status":404,"error":"Not Found","path":"/upload-error-1"}]
	at feign.FeignException.clientErrorStatus(FeignException.java:219) ~[feign-core-11.7.jar:na]
	at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-11.7.jar:na]

このエラーを処理するために、エラーメッセージを表す単純な ExceptionMessage Javabeanを作成します。

public class ExceptionMessage {
    private String timestamp;
    private int status;
    private String error;
    private String message;
    private String path;
    // standard getters and setters
}

ErrorDecoder のカスタマイズされた実装で抽出して、元のメッセージを取得しましょう。

public class RetreiveMessageErrorDecoder implements ErrorDecoder {
    private ErrorDecoder errorDecoder = new Default();

    @Override
    public Exception decode(String methodKey, Response response) {
        ExceptionMessage message = null;
        try (InputStream bodyIs = response.body()
            .asInputStream()) {
            ObjectMapper mapper = new ObjectMapper();
            message = mapper.readValue(bodyIs, ExceptionMessage.class);
        } catch (IOException e) {
            return new Exception(e.getMessage());
        }
        switch (response.status()) {
        case 400:
            return new BadRequestException(message.getMessage() != null ? message.getMessage() : "Bad Request");
        case 404:
            return new NotFoundException(message.getMessage() != null ? message.getMessage() : "Not found");
        default:
            return errorDecoder.decode(methodKey, response);
        }
    }
}

この実装では、発生する可能性のあるエラーに基づいてロジックを追加したため、要件に合わせてそれらをカスタマイズできます。 スイッチブロックのデフォルトの場合、を使用していますデフォルトの実装 ErrorDecoder。

Default 実装は、ステータスが2xxの範囲にない場合にHTTP応答をデコードします。 throwableretryableの場合、 RetryableException、のサブタイプである必要があり、可能な場合は常にアプリケーション固有の例外を発生させる必要があります。

カスタマイズされたErrorDecoderを構成するために、Feign構成にbeanとして実装を追加します。

@Bean
public ErrorDecoder errorDecoder() {
    return new RetreiveMessageErrorDecoder();
}

ここで、元のメッセージの例外を見てみましょう。

com.baeldung.cloud.openfeign.exception.NotFoundException: Page Not found
	at com.baeldung.cloud.openfeign.fileupload.config.RetreiveMessageErrorDecoder.decode(RetreiveMessageErrorDecoder.java:30) ~[classes/:na]
	at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:96) ~[feign-core-11.7.jar:na]

4. 結論

この記事では、 ErrorDecoder をカスタマイズして、Feignエラーをキャッチして元のメッセージをフェッチできるようにする方法を示しました。

いつものように、このチュートリアルで使用されるすべてのコードサンプルは、GitHubから入手できます。