【发布时间】:2019-02-28 18:49:44
【问题描述】:
在搜索了几天并阅读了与此相关的几乎所有内容之后,我终于在这里发布了我的问题,因为我找不到针对我的具体问题的解决方案。
我希望我的 REST WebServices 返回已抛出的原始异常,或者至少返回正确的 StackTrace。为了测试这一点,我使用 JUnit 集成测试和 Wildfly 13 作为应用服务器。经过研究,我发现了两种可能的解决方案。
1.使用异常映射器
虽然这个神奇的东西捕获了我的所有异常并允许我返回一个响应,但我注意到如果我像示例中那样使用它,我的 StackTrace 会发生变化。例如,“com.test.TestClass”变成“null.thread”或“null.interceptor”。似乎不知何故,异常在途中发生了变化,通往班级的路径丢失或被审查,但我无法理解。 我也找不到 Response.entity 的任何限制,无论是大小、数据类型还是安全性。
据我了解,您可以捕获 ExceptionMapper 响应或包含响应的 WebApplicationException。在我的例子中,WebApplicationException 中的响应包含除了(正确的)StackTrace 之外的所有相关数据。
2.使用WebApplicationException
另一个解决方案是简单地抛出 WebApplicationException 而不是 ECEException 并且不使用映射器。如果我这样做并抓住它,那么异常是空的。它不包含任何数据集,它总是 500 - InternalServerError(我猜,Wildfly 无法处理它并自己抛出异常)。
或者它不应该像那样被抓住/扔掉?我是否需要将其转换为 JSon,或者我是否可以期望它通过我在 WebServiceInterface 和 Response MediaType 中的注释开箱即用?将完整的响应放在 WebApplicationException 中是否有意义?我的意思是,两者都包含错误代码的字段,这似乎是多余的,即使该方法有一个构造函数。
长话短说: 捕获所有可能的异常并检索完整堆栈跟踪的最佳方法是什么? Reading this post,我想捕获所有“异常”很好,它们总是作为 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();
}
}
【问题讨论】:
标签: json web-services jakarta-ee exception-handling jax-rs