Проблема исключения Джерси / Джексона с ExceptionMapper - PullRequest
14 голосов
/ 29 апреля 2011

Я использую Джерси для предоставления сервиса Java REST для внешнего мира.Я предлагаю некоторые функции, использующие JSON, и использую среду Джексона в сочетании с Джерси для преобразования их в POJO.

У меня проблема в том, что если на сервер отправляется неправильный формат Джексона, ответ (содержимоеhttp response) - описание исключений, характерных для Джексона.Если у меня есть POJO с атрибутом «фамилия» и я посылаю «sursname» в строке json на сервер, я получаю:

Unrecognized field "sursname" (Class XY), not marked as ignorable at [Source: sun.net.httpserver.FixedLengthInputStream@903025; line: 1, column: 49] (through reference chain: XY["sursname"])

Это вполне нормально, но я хотел бы иметь свой собственный ответНапример, мой собственный код ошибки.Я уже написал пользовательский ExceptionMapper , который должен отображать все Throwables.

@Provider
public class WebserviceExceptionMapper implements ExceptionMapper<Throwable> {

@Override
public Response toResponse(Exception e) {
    e.printStackTrace();
    return Response.status(400).entity("{\"errorcode\":\"CRITICAL_ERROR\"}").type(MediaType.APPLICATION_JSON).build();
    }
}

Кажется, что исключение Джексона выдается до вызова моего метода веб-сервиса, поэтому у меня нет шансов отобразить его?

У кого-нибудь есть идея?Большое спасибо и извините за мой английский;)

Ответы [ 5 ]

16 голосов
/ 21 мая 2015

Причина, по которой ваш пользовательский ExceptionMapper не перехватывает исключения, заключается в том, что библиотека Джексона предоставляет свои собственные средства отображения исключений, которые отлавливают исключение до того, как оно будет отловлено вашим генеральным средством отображения исключений.

Некоторые полагают, что вам следует реализовать собственные сопоставители исключений для JsonParseExceptionMapper и JacksonMappingExceptionMapper, но это, однако, даст противоречивые результаты. См. Эту проблему на их GitHub .

Для решения этой проблемы необходимо убедиться, что ни один из встроенных сопоставителей исключений не зарегистрирован. Если вы используете библиотеку jackson-jaxrs-provider для JSON: jackson-jaxrs-json-provider , убедитесь, что вы only регистрируете либо JacksonJaxbJsonProvider.class или JacksonJsonProvider.class в вашем классе приложений:

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(JacksonJaxbJsonProvider.class)
    }
}

Помните о JacksonFeature.class , так как он регистрирует встроенные ExceptionMappers. Также держитесь подальше от библиотеки jersey-media-json-jackson , которая автоматически добавит некоторые встроенные средства отображения исключений, без необходимости что-либо делать.

2 голосов
/ 05 августа 2013

Я столкнулся с подобной проблемой некоторое время назад при использовании Jackson и Apache CXF.Преобразователи исключений не были вызваны, если исключение не произошло в моем методе JAX-RS, а произошло в JacksonJsonProvider.Решение в моем случае состояло в том, чтобы расширить JacksonJsonProvider, перехватить определенные исключения Джексона json и отбросить их как WebApplicationException.

Вот мой переопределенный метод readFrom для моего расширенного JacksonJsonProvider:

    @Override
    public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
        try {
            return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
        } catch (JsonParseException jpe) {
            throw new WebApplicationException(jpe, Response.status(Status.BAD_REQUEST)
                    .entity(new ErrorEntity("Malformed json passed to server: \n" + jpe.getMessage())).build());
        } catch (JsonMappingException jme) {
            throw new WebApplicationException(jme, Response
                    .status(Status.BAD_REQUEST)
                    .entity(new ErrorEntity("Malformed json passed to server, incorrect data type used: \n"
                            + jme.getMessage())).build());
        }
    }
1 голос
/ 14 июля 2017

У меня была та же проблема, и я решил переопределить ExceptionMapper.Отлично!Еще одна вещь, которую я должен был сделать и не понимал на 100%, - это как переопределить JacksonProvider для моего приложения (я не знаю, было ли это связано с версией Джерси, которую я использовал - 2.19).Вот моя часть web.xml, которая переопределяет ее:

<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
        com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider
    </param-value>

1 голос
/ 29 апреля 2011

Конечно, раньше выдается исключение Джексона: вызывается поставщик Джексона, чтобы создать объект, который вы ожидаете в своем методе.Однако с ExceptionMapper вы сможете отображать не только свои исключения, но и исключения поставщиков.

Вы уверены, что ваш поставщик зарегистрирован?Вызывается ли это, если вы выбросили исключение из вашего метода, а не из провайдера?

Если ответ на предыдущий вопрос «да», попробуйте реализовать ExceptionMapper для конкретного исключения вместо Throwable.

0 голосов
/ 30 апреля 2011

Спасибо за вашу помощь, ExceptionMapper for JsonParseException не помог. Я удалил файлы Джексона Джара из моего проекта и включил источники Джексона. Затем я изменил ord.codehaus.jackson.jaxrs.JsonParseExceptionMapper и JacksonMappingExceptionMapper для возврата моего пользовательского содержимого ответа. Я не доволен этим, но теперь это работает!

Спасибо за вашу помощь!

...