2016-12-16 4 views
3

Предположим, у меня есть конечная точка в Dropwizard, скажемКак я могу переопределить обработку исключений Dropwizard по умолчанию?

@GET 
public Response foo() { throw new NullPointerException(); } 

Когда я ударил эту конечную точку он регистрирует исключение, и все, что отлично! Я люблю это. То, что я люблю меньше, это то, что он возвращает объекту большого статуса пользователю с status: ERROR (и это хорошо), а также гигантская трассировка стека, в которой я менее взволнован.

Очевидно, что лучше поймать и справиться с исключениями самостоятельно, но время от времени они собираются проскользнуть. Написание блока catch try вокруг всего ресурса каждый раз в порядке, но (а) оно громоздко и (б) я всегда предпочитаю автоматические решения для «вы должны помнить» решения.

Так что я хотел бы что-то, что делает следующее:

  1. Журналы трассировки стека (я использую SLF4J, но я предполагаю, что он будет работать на любой другой)
  2. Возвращает ответ об ошибке общего назначения, который не предоставляет потенциально привилегированную информацию о моем сервере!

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

+2

проверить это: http://gary-rowe.com/agilestack/2012/10/23/how-to-implementation-a-runtimeexceptionmapper-for-dropwizard/ – Reek

+0

Предлагает начать дифференцировать исключение, которое вы бросаете. Используйте настраиваемое исключение для отказов, которые вы знаете, и бросайте те с довольно протоколированием. В то же время исключение должно быть выбрано и исправлено. Если вы не хотите отображать это для конечного пользователя, вы, вероятно, можете поймать общее исключение, зарегистрируйте данные и настройте 'Response' и' entity' соответственно. – nullpointer

ответ

0

Уже упоминалось об этом под комментариями, но потом подумал, что я попробую его использовать.

Предлагает вам начать дифференциацию Exception, которую вы выбрали. Используйте настраиваемое исключение для отказов, которые вы знаете, и бросайте те с довольно протоколированием. При этом фактически необходимо зафиксировать RuntimeException. Во всяком случае, если вы не хотите отображать трассировку стека конечному пользователю, вы, вероятно, можете поймать общее исключение, запишите данные и соответствующим образом настройте ответ и сущность.

Вы можете определить

public class ErrorResponse { 

    private int code; 
    private String message; 

    public ErrorResponse() { 
    } 

    public ErrorResponse(int code, String message) { 
     this.code = code; 
     this.message = message; 
    } 
    ... setters and getters 
} 

, а затем внутри вас ресурс код, который вы можете изменить метод как -

@GET 
public Response foo() { 
    try { 
     ... 
     return Response.status(HttpStatus.SC_OK).entity(response).build(); 
    } catch (CustomBadRequestException ce) { 
     log.error(ce.printStackTrace()); 
     return Response.status(HttpStatus.SC_BAD_REQUEST).entity(new ErrorResponse(HttpStatus.SC_BAD_REQUEST, ce.getMessage())).build(); 
    } catch (Exception e) { 
     log.error(e.printStackTrace(e)); 
     return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage())).build(); 
    }  
} 
+1

Это, пожалуй, хороший совет, но на самом деле он не затрагивает вопрос, как изменить поведение dropwizard при работе с неперехваченным исключением. Неявная предпосылка вопроса, с которым вы, по-видимому, не согласны, заключается в том, что я не хочу окружать каждую конечную точку в блоке try-catch, когда dropwizard по существу делает это для меня в любом случае. –

1

Как указывалось на реек в комментариях, ответ является ExceptionMapper. Вам нужен класс, как это:

@Provider 
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> { 
    @Override 
    public Response toResponse(RuntimeException runtime) { 
     // ... 
    } 
} 

Вы можете делать все, что протоколирование или т.п. Вам нравится в методе toResponse, а возвращаемое значение является то, что на самом деле послал к запрашивающему. Таким образом, вы имеете полный контроль и должны устанавливать нормальные значения по умолчанию - помните, что это для ошибок, которые проскальзывают, а не для тех ошибок, которые вы на самом деле ожидаете увидеть! Это также подходящее время для настройки разных типов поведения в зависимости от того, какие исключения вы получаете.

Чтобы на самом деле сделать это сделать что-нибудь, просто вставьте следующую строку (или аналогичную) в run методы вашего основного приложения dropwizard:

environment.jersey().register(new RuntimeExceptionMapper()); 

где environment является параметром run метода приложения Environment.Теперь, когда у вас есть нетканый RuntimeException, это приведет к срабатыванию, а не к тому, что раньше делал dropwizard.

NB: это все еще не оправдание, чтобы не ловить и не заниматься своими исключениями!

+0

Это интересно, но это не касается исключений, возникших при инициализации конфигурации, не так ли? Вы можете установить это только в методе 'run', правильно? Лично я хотел бы, чтобы Dropwizard позволял исключать исключения, возникшие во время инициализации конфигурации, убить процесс. –

1

Добавить следующее в ваш файл yaml. Обратите внимание, что он удалит все фильтры-исключения по умолчанию, которые добавляет dropwizard.

server: registerDefaultExceptionMappers: false

Написать картограф пользовательских исключений, как показано ниже:

public class CustomExceptionMapper implements ExceptionMapper<RuntimeException> { 
    @Override 
    public Response toResponse(RuntimeException runtime) { 
     // ... 
    } 
} 

Затем зарегистрировать картограф исключения из джерси: environment.jersey().register(new CustomExceptionMapper());

+0

Я попытался это сделать, но исключения, которые были выбраны во время инициализации конфигурации, все еще «пойманы» dropwizard, и поэтому процесс не завершается. Есть идеи по этому поводу? –

Смежные вопросы