0

私は、場合によってはカスタム ビジネス例外をスローするカスタム応答フィルターを持つ jersey 2.27 サーバー アプリケーションを備えた glassfish 5 を使用しています。

応答フィルターは次のようになります。

public class CustomResponseFilter implements ContainerResponseFilter {

   ....

    @Override
    public void filter(ContainerRequestContext request, ContainerResponseContext response) {
        ....
        if (something_is_true) {
            throw new CustomException(A_CUSTOM_MESSAGE);
        }
    }

    ...

}

例外と例外マッパーは次のように定義されます。

public class CustomException extends RuntimeException {

    public CustomException(String message) {
        super(message);
    }
}
@Provider
public class CustomException400Mapper implements ExceptionMapper<CustomException> {

    ...

    @Override
    public Response toResponse(CustomException t) {
        Error entity = new Error(HttpServletResponse.SC_BAD_REQUEST,
                HEADER_INVALID, CONTRACT_NUMBER_HEADER);
        return Response.status(HttpServletResponse.SC_BAD_REQUEST).
                entity(entity).
                type(MediaType.APPLICATION_JSON).
                build();
    }
}

リクエストはエンドポイントを通過し、カスタム レスポンス フィルタに到達すると、上記のカスタム例外がスローされます。

例外は、jersey フレームワークによってキャッチされ、処理されます。例外マッパーを使用して応答に変換されます。

私の問題は、応答がクライアントに返されず、代わりにprocessResponse(response)メソッドが呼び出され、すべての応答フィルターが再度呼び出されることです。これは基本的に同じエラーを再びスローします。魔女はキャッチされ、 Internal Server Error にラップされます

私の側からのいくつかのコメントとともに、次のジャージ フレームワーク コードを確認できます。

package org.glassfish.jersey.server;

...

public class ServerRuntime {

    ...

    public void process(final Throwable throwable) {
            final ContainerRequest request = processingContext.request();

            ...

            ContainerResponse response = null;
            try {
                final Response exceptionResponse = mapException(throwable);
                try {
                    try {
                        response = convertResponse(exceptionResponse);
                        if (!runtime.disableLocationHeaderRelativeUriResolution) {
                            ensureAbsolute(response.getLocation(), response.getHeaders(), request,
                                    runtime.rfc7231LocationHeaderRelativeUriResolution);
                        }
                        processingContext.monitoringEventBuilder().setContainerResponse(response)
                                .setResponseSuccessfullyMapped(true);
                    } finally {
                        processingContext.triggerEvent(RequestEvent.Type.EXCEPTION_MAPPING_FINISHED);
                    }

                    // response is correctly mapped from CustomException400Mapper
                    // this triggers the response filters to be runned again
                    // throws the same Exception again
                    processResponse(response);
                } catch (final Throwable respError) { // the exception is catched here and retrown again
                    LOGGER.log(Level.SEVERE, LocalizationMessages.ERROR_PROCESSING_RESPONSE_FROM_ALREADY_MAPPED_EXCEPTION());
                    processingContext.monitoringEventBuilder()
                            .setException(respError, RequestEvent.ExceptionCause.MAPPED_RESPONSE);
                    processingContext.triggerEvent(RequestEvent.Type.ON_EXCEPTION);
                    throw respError;
                }
            } catch (final Throwable responseError) { // the exception is catched here
                if (throwable != responseError
                        && !(throwable instanceof MappableException && throwable.getCause() == responseError)) {
                    LOGGER.log(Level.FINE, LocalizationMessages.ERROR_EXCEPTION_MAPPING_ORIGINAL_EXCEPTION(), throwable);
                }

                // I`ve tried to use processResponseError method to return the response exception but it calls processResponse(...) method witch call`s the response filters and it fails and returns false. 
                if (!processResponseError(responseError)) {
                    // Pass the exception to the container.
                    LOGGER.log(Level.FINE, LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER(), responseError);

                    try {

                        // here it returns the exception mapped into an Internal Server Error Response
                        request.getResponseWriter().failure(responseError);
                    } finally {
                        completionCallbackRunner.onComplete(responseError);
                    }
                }
            } finally {
                release(response);
            }
        }

私の質問は、応答フィルターでスローされたカスタム例外から応答を返すにはどうすればよいですか?

どうも!

4

0 に答える 0