Средство отображения исключений JAX-RS: А как насчет исключений в оболочке и случая по умолчанию? - PullRequest
0 голосов
/ 25 сентября 2018

Типичным способом обработки исключений в службе REST является определение пользовательских типов исключений (обычно из RuntimeException), а затем реализация класса сопоставления для создания кодов HTTP, например:

public class MyExceptionMapper implements ExceptionMapper<MyException> {
  @Override
  public Response toResponse(MyExceptionex) {
    return Response.status(400).entity("bad request")
      .type(MediaType.APPLICATION_JSON).build();
  }
}

ТеперьУ меня есть 2 вопроса:

  • Как бы я реализовал маппер для «случая по умолчанию», то есть для каждого исключения, не отображенного здесь или в другом маппере?Например, при реализации одного для Throwable для создания HTTP 500, не перехватит ли он мои собственные исключения снова?Или можно определить порядок, в котором работают мапперы?
  • При вызове управляемых компонентов, таких как EJB, из службы REST, не приведет ли исключение, генерируемое там, к EJBException или некоторому Transaction...Exception, обертывающему мой собственный?

1 Ответ

0 голосов
/ 25 сентября 2018

mapper для «случая по умолчанию» ...

Так же, как пишет в комментарии Пол Самсота, среда выполнения сервера JAX-RS должна выбрать наиболее конкретный модуль отображения исключений.Или процитировать спецификации JAX-RS (для JEE7 / версия 2.0):

3.3.4 Исключения

[...]

Если поставщик исключений (см. Раздел 4.4) доступен для исключения или одного из его суперклассов, реализация ДОЛЖНА использовать поставщика, универсальный тип которого является ближайшим суперклассом исключения, для создания экземпляра Response, который затем обрабатывается в соответствии ск разделу 3.3.3. [...]

Так что, я думаю, вы можете использовать преобразователь исключений для Throwable - его подпись все равно подтверждает это:

public interface ExceptionMapper<E extends Throwable> {...}

При вызове управляемых компонентов, таких как EJB, из службы REST ...

Контейнер EJB будет переносить исключение, если его необходимо заключить в оболочку.Не все исключения, выдаваемые EJB, должны быть упакованы.В спецификации EJB (v3.1) проводится различие между исключениями приложений (отмеченными javax.ejb.ApplicationException) и «всеми другими исключениями» (см. Раздел 14.3).Поэтому сделайте исключение @ApplicationException и предоставьте для него маппер.Но если вы все еще хотите отвечать на основе исключения обернутого :

Ответить на основе обернутого исключения

Вы не можете напрямую выбрать преобразователь на основе обернутого исключения.Но вы можете создать преобразователь исключений для исключения wrapper , который развернет его и выберет соответствующий преобразователь для исключения wrapped на основе контекста Providers (см.JAX-RS 2.0 раздел 9.2.6 и javax.ws.rs.ext.Providers Javadocs).Например, непроверенный код для гипотетического MyWrapperException будет выглядеть так:

@Provider
public class MyWrapperExceptionMapper implements ExceptionMapper<MyWrapperException> {
    @Context
    private Providers providers;

    public Response toResponse(MyWrapperException e) {
        Throwable t = e.getCause();
        ExceptionMapper mapper = providers.getExceptionMapper(t.getClass());
        if( mapper != null ) {
            return mapper.toResponse(t);
        }
        else {
            // custom handling...
        }
    }
}
...