Мне нужна помощь в понимании того, как Websphere Liberty (18.0.0.1) обрабатывает исключения, возникающие при вызове конечной точки JAX-RS. Я использую функцию Liberty jaxrs-2.0
, поэтому реализация должна быть предоставлена WLP.
Теперь у моего приложения есть конечная точка POST HTTP, принимающая полезную нагрузку JSON, и я хотел бы предоставить настраиваемые сообщения об ошибках для всех возможных неправильных входных данных клиента.
Вот один случай, который работает так, как я ожидал:
- Клиент отправляет
application/xml
вместоapplication/json
- Контейнер выбрасывает
ClientErrorException
- Я могу использовать свой собственный сопоставитель исключений (реализующий
ExceptionMapper<WebApplicationException>
для обработки этого исключения (фактически для обработки всех исключений веб-приложений, с которыми я согласен) - Таким образом, я могу отформатировать сообщение об ошибке, пометить ошибку идентификатором и т. д. Это хорошо
А вот у меня не работает дело:
- Клиент отправляет
application/json
, но с пустым телом - Основным исключением в этом случае является
java.io.EOFException: No content to map to Object due to end of input
- да, это выглядит точно - Теперь, что я не могу понять - вместо того, чтобы оборачивать этот
EOFException
в какой-тоWebApplicationException
(с которым я мог бы легко справиться), WLP оборачивает проблему исключения вJaxRsRuntimeException
Пара моментов здесь:
- Я не хочу создавать преобразователь, реализующий
ExceptionMapper<JaxRsRuntimeException>
, потому что это исключение не является частью спецификации JAX-RS 2.0, и мне пришлось бы обеспечить импорт в JaxRsRuntimeException и связать приложение с некоторой библиотекой, специфичной для Liberty. - Возможное решение состоит в том, чтобы мой преобразователь реализовал общую проверку
ExceptionMapper<RuntimeException>
и строки, если он находит исключение имени класса «JaxRsRuntimeException», а затем обрабатывал его. Но мне это просто не кажется правильным.
Итак, это дизайн WLP, чтобы не дать мне исключение WebApplicationException в этом случае? Каким было бы элегантное решение для обработки этого сценария?
Спасибо
РЕДАКТИРОВАТЬ: добавлены некоторые части исходного кода.
Конечная точка REST и метод ресурса:
@Path("/books")
public class BookEndpoint {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createBook(Book book, @Context UriInfo uriInfo) {
bookDao.create(book);
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
builder.path(Integer.toString(book.getId()));
return Response.created(builder.build()).entity(book).build();
}
}
Объект с аннотациями JAXB:
@XmlRootElement
public class Book {
private int id;
private String title;
// getters, setters
}
Трассировка стека исключений:
com.ibm.ws.jaxrs20.JaxRsRuntimeException: java.io.EOFException: No content to map to Object duto end of input
at org.apache.cxf.jaxrs.utils.JAXRSUtils.toJaxRsRuntimeException(JAXRSUtils.java:1928)
at [internal classes]
at org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:201)
at [internal classes]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.EOFException: No content to map to Object duto end of input
at org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:2775)
at [internal classes]
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1413)
at [internal classes]
... 48 more