【问题标题】:How to catch the original Exception, when using WebServices?使用 WebServices 时如何捕获原始异常?
【发布时间】: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


    【解决方案1】:

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

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

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

    最好的方法是什么?

    使用异常映射器对我有用。与其将它们作为 WebApplicationException 捕获,不如始终期望得到带有适当错误代码的响应并以这种方式处理它们。例如错误代码 200 = OK,执行此操作...错误代码 404 = NOTFOUND,执行此操作...在这种情况下,您的 WebServices 应始终返回响应并包含您要在响应的实体字段中检索的对象。

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

    【讨论】:

      猜你喜欢
      • 2014-04-25
      • 2011-01-03
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      • 2021-08-22
      • 1970-01-01
      • 2010-10-28
      • 2019-11-30
      相关资源
      最近更新 更多