После поисков в течение нескольких дней и прочтения почти всего, что с этим связано, я наконец-то разместил здесь свой вопрос, поскольку не смог найти решение для своей конкретной проблемы.
Я хочу, чтобы мои REST WebServices возвращали исходное исключение, которое было выброшено, или, по крайней мере, правильный StackTrace.Чтобы проверить это, я использую тесты интеграции JUnit и Wildfly 13 в качестве сервера приложений.После исследования я нашел 2 возможных решения.
1.Использование картографирования исключений
В то время как эта волшебная вещь захватывает все мои исключения и позволяет мне возвращать ответ, я 'Я заметил, что мой StackTrace изменился, если я использую его, как в примере.Например, «com.test.TestClass» превращается в «null.thread» или «null.interceptor».Кажется, что каким-то образом исключение меняется на пути, и пути к классу теряются или подвергаются цензуре, но я не могу понять это.Также я не смог найти никаких ограничений для Response.entity, будь то размер, тип данных или безопасность.
Насколько я понимаю, вы можете перехватить ExceptionMapper Response ИЛИ WebApplicationException, которая содержит ответ.В моем случае ответ в исключении WebApplicationEx содержит все соответствующие данные, кроме (правильного) StackTrace.
2.Использование исключения WebApplicationException
Другим решением было бы просто вызвать исключение WebApplicationException вместо ECEException и не использовать маппер.Если я это сделаю и поймаю, исключение будет пустым.Он не содержит никакого набора данных, он всегда равен 500 - InternalServerError (я думаю, тогда Wildfly не смог обработать его и сам выдал исключение).
Или он не должен быть перехвачен / брошенкак это?Нужно ли мне конвертировать его в JSon или можно ожидать, что он просто будет работать «из коробки» с моими аннотациями в WebServiceInterface и MediaType Response?Имеет ли смысл помещать полный ответ в исключение WebApplicationException?Я имею в виду, что оба содержат поля для ErrorCode, который кажется избыточным и даже при том, что есть конструктор для этого подхода.
Короче говоря: Какой лучший подход для перехвата всех возможных исключений иполучить полную трассировку стека? Читая этот пост , я думаю, что перехватывать все "Исключения" - это нормально, и они всегда возвращаются как WebApplicationExceptions, но трассировка стека все еще пропала / искажена ... ваши мысли?
**JUnitTest**
@Test
public void testCreateTask_ClusterInvalid() throws IOException {
final RPETask taskToCreate = new RPETask();;
try
{
final long tid = taskManagerWebService.createTask(taskToCreate);
}
catch (WebApplicationException e) //Responses are ALWAYS catched as WebApplicationException
{
Response response = e.getResponse();
String emString = response.readEntity(String.class);
Gson gson = new Gson();
ECEWebErrorMessage errorMessage = gson.fromJson(emString, ECEWebErrorMessage.class);
errorMessage.displayErrorInformationOnConsole();
}
}
**WebServiceInterface**
@POST
@Path(URI_CREATE_TASK)
@Consumes(WebServiceNames.JSON)
@Produces(WebServiceNames.JSON)
long createTask(final RPETask task) throws ECEException;
**WebService**
@Override
public long createTask(final RPETask task) throws ECEException {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("createTask(" + task + ")");
}
return taskManager.createTask(task);
}
**ManagerBeanInterface**
long createTask(RPETask task) throws ECEException;
**ManagerBean**
@Override
public long createTask(final RPETask task) throws ECEException {
final ClusterEngineBean cluster = find(ClusterEngineBean.class, task.getCluster());
if (cluster == null) {
throw new ECEObjectNotFoundException(ClusterEngineBean.class, task.getCluster());
}
}
**ExceptionMapper**
@Provider
public class GenericWebExceptionMapper implements ExceptionMapper<Exception> {
final Log logger = LogFactory.getLog(getClass());
@Override
public Response toResponse(Exception ex) {
//At this point, the Exception is fully available -> Sending it as Response breaks it!
logger.error("GenericWebExceptionMapper -> toResponse(Throwable ex)", ex);
ECEWebErrorMessage errorMessage = new ECEWebErrorMessage(500,
ex.getMessage(),
ex.getClass().getCanonicalName(),
ex.getStackTrace());
return Response.status(Status.INTERNAL_SERVER_ERROR)
.entity(errorMessage)
.type(MediaType.APPLICATION_JSON)
.build();
}
}