[英]How to catch the original Exception, when using WebServices?
经过数天的搜索并阅读了与之相关的所有内容之后,我终于在这里发布了我的问题,因为我找不到适合自己特定问题的解决方案。
我希望我的REST WebServices返回已抛出的原始Exception,或者至少返回正确的StackTrace。 为了测试这一点,我使用JUnit集成测试和Wildfly 13作为应用程序服务器。 经过研究,我发现了2种可能的解决方案。
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的字段,即使存在该方法的构造函数,该字段似乎也是多余的。
长话短说:捕获所有可能的异常并检索完整堆栈跟踪的最佳方法是什么? 阅读这篇文章 ,我想捕获所有“异常”都很好,并且它们总是作为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();
}
}
经过更多的研究,我终于找到了适合自己的解决方案。
为什么StackTrace消失/格式错误?
出于安全原因。 Wildfly使用拦截器自动检测传出的StackTrace并对其进行审查。 我不确定您是否可以对此做任何事情,但是我想您还是不应该这样做。
最好的方法是什么?
使用异常映射器对我有用。 不必总是将它们捕获为WebApplicationException,而是始终可以期待带有适当错误代码的响应并以这种方式进行处理。 例如,错误代码200 = OK,执行此操作...错误代码404 = NOTFOUND,执行该操作...在这种情况下,您的Web服务应始终返回Responses并在Response的实体字段中包含要检索的对象。
随时向该解决方案添加其他信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.