Я начинаю использовать новую клиентскую библиотеку API в JAX-RS и действительно люблю ее до сих пор. Однако я нашел одно, чего не могу понять. API, который я использую, имеет собственный формат сообщения об ошибке, который выглядит следующим образом:
{
"code": 400,
"message": "This is a message which describes why there was a code 400."
}
Он возвращает 400 в качестве кода состояния, но также содержит описательное сообщение об ошибке, чтобы сообщить вам, что вы сделали неправильно.
Однако клиент JAX-RS 2.0 повторно отображает статус 400 во что-то общее, и я теряю хорошее сообщение об ошибке. Он правильно отображает его в BadRequestException, но с общим сообщением "HTTP 400 Bad Request".
javax.ws.rs.BadRequestException: HTTP 400 Bad Request
at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:908)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:770)
at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:90)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:671)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:424)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:667)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:396)
at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:296)
Есть ли какой-то перехватчик или настраиваемый обработчик ошибок, которые могут быть введены, чтобы я получил доступ к реальному сообщению об ошибке. Я просматривал документацию, но не вижу никакого способа сделать это.
Я использую Джерси прямо сейчас, но я попробовал это с помощью CXF и получил тот же результат. Вот как выглядит код.
Client client = ClientBuilder.newClient().register(JacksonFeature.class).register(GzipInterceptor.class);
WebTarget target = client.target("https://somesite.com").path("/api/test");
Invocation.Builder builder = target.request()
.header("some_header", value)
.accept(MediaType.APPLICATION_JSON_TYPE)
.acceptEncoding("gzip");
MyEntity entity = builder.get(MyEntity.class);
UPDATE:
Я реализовал решение, указанное в комментарии ниже. Это немного отличается, поскольку классы немного изменились в клиентском API JAX-RS 2.0. Я по-прежнему считаю неправильным, что поведение по умолчанию - дать общее сообщение об ошибке и отказаться от реального. Я понимаю, почему он не будет анализировать мой объект ошибки, но необработанная версия должна быть возвращена. В итоге я получаю репликационное отображение исключений, которое уже делает библиотека.
Спасибо за помощь.
Вот мой класс фильтра:
@Provider
public class ErrorResponseFilter implements ClientResponseFilter {
private static ObjectMapper _MAPPER = new ObjectMapper();
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
// for non-200 response, deal with the custom error messages
if (responseContext.getStatus() != Response.Status.OK.getStatusCode()) {
if (responseContext.hasEntity()) {
// get the "real" error message
ErrorResponse error = _MAPPER.readValue(responseContext.getEntityStream(), ErrorResponse.class);
String message = error.getMessage();
Response.Status status = Response.Status.fromStatusCode(responseContext.getStatus());
WebApplicationException webAppException;
switch (status) {
case BAD_REQUEST:
webAppException = new BadRequestException(message);
break;
case UNAUTHORIZED:
webAppException = new NotAuthorizedException(message);
break;
case FORBIDDEN:
webAppException = new ForbiddenException(message);
break;
case NOT_FOUND:
webAppException = new NotFoundException(message);
break;
case METHOD_NOT_ALLOWED:
webAppException = new NotAllowedException(message);
break;
case NOT_ACCEPTABLE:
webAppException = new NotAcceptableException(message);
break;
case UNSUPPORTED_MEDIA_TYPE:
webAppException = new NotSupportedException(message);
break;
case INTERNAL_SERVER_ERROR:
webAppException = new InternalServerErrorException(message);
break;
case SERVICE_UNAVAILABLE:
webAppException = new ServiceUnavailableException(message);
break;
default:
webAppException = new WebApplicationException(message);
}
throw webAppException;
}
}
}
}