在搜索了几天并阅读了几乎所有与之相关的内容之后,我终于在这里发布了我的问题,因为我找不到适合自己特定问题的解决方案。
我希望我的REST WebServices返回已抛出的原始Exception,或者至少返回正确的StackTrace。为了测试这一点,我使用JUnit集成测试和Wildfly 13作为应用程序服务器。经过研究,我找到了两种可能的解决方案。
1。使用异常映射器
尽管这神奇的事情捕获了我所有的异常,并允许我返回一个Response,但我注意到如果像示例中那样使用它,我的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中的注释直接使用即可使用?将完整的Response放入WebApplicationException甚至有意义吗?我的意思是,这两个字段都包含ErrorCode的字段,即使存在该方法的构造函数,该字段似乎也是多余的。
长话短说: 捕获所有可能的异常并检索完整堆栈跟踪的最佳方法是什么? 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();
}
}
答案 0 :(得分:0)
经过更多研究,我终于为自己找到了解决方案。
为什么StackTrace消失/格式错误?
出于安全原因。 Wildfly使用拦截器自动检测传出的StackTrace并对其进行审查。我不确定您是否可以对此做任何事情,但我想您还是不应该这样做。
什么是最好的方法?
使用异常映射器为我工作。不必总是将它们捕获为WebApplicationException,而是始终可以期待带有适当错误代码的响应并以这种方式进行处理。例如,错误代码200 = OK,执行此操作...错误代码404 = NOTFOUND,执行此操作...在这种情况下,您的Web服务应始终返回Responses并在Response的实体字段中包含要检索的对象。 / p>
随时向该解决方案添加其他信息。