Исключительный слушатель с Джерси

У меня есть приложение на Джерси (2.14), которое работает нормально. У меня там работает несколько служб. Теперь я хотел бы настроить ServletContainer таким образом, чтобы любые неотслеживаемые исключения были перехвачены, зарегистрированы или отправлены по электронной почте.

У меня уже есть реализация ApplicationEventListener и тестовая конечная точка для генерации исключения.

Это метод, который должен генерировать исключение (это работает:-):

@GET
@Path(TEST_EXCEPTION)
public String testException(@Context final ServletContext context) {
    String s = null;
    int size = 0;
    if (System.nanoTime() % 10 != 0) {
        s = null;
    } else {
        s = "No exception will occur";
    }
    size = s.length();
    return Integer.toString(size) + ":" + s;
}

И это реализация, если мой ApplicationEventListener:

public class MyApplicationEventListener implements ApplicationEventListener {
    private transient volatile int count = 0;
    private int exceptions = 0;

    @Override
    public void onEvent(final ApplicationEvent applicationEvent) {
        ApplicationEvent.Type type = applicationEvent.getType();
    }

    @Override
    public RequestEventListener onRequest(final RequestEvent requestEvent) {
        RequestEvent.Type type = requestEvent.getType();
        if (type == RequestEvent.Type.ON_EXCEPTION) {
            exceptions++;
        }
        count++;
        return null;
    }
}

И эта конфигурация в моем web.xml:

<servlet>
    <servlet-name>jersey-servlet</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com....rest</param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>
            com....filter.MyApplicationEventListener
        </param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.tracing</param-name>
        <param-value>ALL</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

onEvent () и onRequest() оба были вызваны, но когда возникает исключение, я получаю не ON_EXCEPTION, а START.

Что я делаю неправильно? Или как я могу получить все исключения, вытекающие из методов моего сервиса в Джерси?

Я хотел бы иметь / сделать что-то вроде Spring's HandlerExceptionResolver.

2 ответа

Решение

Вы можете сделать это довольно легко с ExceptionMapper. Если возникает исключение, вы все равно должны отправить ответ клиенту. Но здесь вы также можете отправить сообщение электронной почты или зарегистрировать билет и т. Д.

Вот пример, который я сделал для ConstraintViolations, но это может быть средством отображения исключений для типа Exception. Вы можете проверить тип исключения и сделать что-то соответственно. В toResponse вы можете реализовать метод notfiyEmail, который может отправлять трассировку стека и отправлять сообщения, например, на адрес электронной почты или регистрировать билет jira, который я делал в прошлом. Обратите внимание, что вам нужно добавить @Provider вверху и сказать остальным Application/ResourceConfig просканировать пакет на предмет этого класса. В качестве альтернативы вы можете зарегистрировать его вручную с помощью ResourceConfig.

@Provider
public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {

    private static final Logger logger = Logger.getLogger(ConstraintViolationExceptionMapper.class.getName());

    public Response toResponse(ConstraintViolationException exception) {            
            final int violationCount = exception.getConstraintViolations().size();

            ConstraintViolation<?>[] constraintViolations = exception.getConstraintViolations().toArray(
                    new ConstraintViolation<?>[violationCount]);
            Violation[] violations = new Violation[exception.getConstraintViolations().size()];

            for (int i = 0; i < violationCount; i++) {
                ConstraintViolation<?> cv = constraintViolations[i];
                Violation violation = new Violation(cv.getPropertyPath().toString(), cv.getMessage());
                violations[i] = violation;
            }

            ConstraintErrorResponse responseEntity = new ConstraintErrorResponse();
            responseEntity.setViolations(violations);

            logger.info("Seinding exception response");
            return Response.status(Response.Status.BAD_REQUEST).entity(responseEntity).build();
    }
}

... когда происходит исключение, я получаю не ON_EXCEPTION, а START.

Что я делаю неправильно?

Вам нужно возвращать экземпляр RequestEventListener из события START, а не возвращать NULL, чтобы указать Джерси продолжить запуск событий для запроса.

С 21.1.2. Слушатели событий:

Второй метод onRequest вызывается средой выполнения Джерси каждый раз, когда поступает новый запрос. Тип события запроса, передаваемый методу, всегда START. Если вы хотите прослушать любые другие события жизненного цикла запроса для нового запроса, вы должны вернуть экземпляр RequestEventListener, который обработает запрос.

См. /questions/18912377/dzhersi-kak-registrirovat-vse-isklyucheniya-no-pri-etom-vyizyivat-exceptionmappers/18912397#18912397 для примера, который регистрирует события исключений.

Другие вопросы по тегам