私は、場合によってはカスタム ビジネス例外をスローするカスタム応答フィルターを持つ 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);
}
}
私の質問は、応答フィルターでスローされたカスタム例外から応答を返すにはどうすればよいですか?
どうも!