使用WebServices时如何捕获原始异常?

时间:2018-09-25 07:52:43

标签: json web-services java-ee exception-handling jax-rs

在搜索了几天并阅读了几乎所有与之相关的内容之后,我终于在这里发布了我的问题,因为我找不到适合自己特定问题的解决方案。

我希望我的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();
        }
    }

1 个答案:

答案 0 :(得分:0)

经过更多研究,我终于为自己找到了解决方案。

为什么StackTrace消失/格式错误?

出于安全原因。 Wildfly使用拦截器自动检测传出的StackTrace并对其进行审查。我不确定您是否可以对此做任何事情,但我想您还是不应该这样做。

什么是最好的方法?

使用异常映射器为我工作。不必总是将它们捕获为WebApplicationException,而是始终可以期待带有适当错误代码的响应并以这种方式进行处理。例如,错误代码200 = OK,执行此操作...错误代码404 = NOTFOUND,执行此操作...在这种情况下,您的Web服务应始终返回Responses并在Response的实体字段中包含要检索的对象。 / p>

随时向该解决方案添加其他信息。