【问题标题】:Custom Jersey Error Handling, how to catch response at client side?自定义泽西错误处理,如何在客户端捕获响应?
【发布时间】:2016-01-19 05:23:12
【问题描述】:

我正在我的网络服务上尝试一些自定义错误处理。在我的 Web 服务中,我创建了一个自定义 Exception 类,该类扩展 WebApplicationException,如 JAX-RS / Jersey how to customize error handling? 中所述:

public class InternalServerErrorException extends WebApplicationException {
    public InternalServerErrorException(String message) {
        super(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
            .header("errorMessage", message).type(MediaType.TEXT_PLAIN).build());
        System.out.println(message);
    }
}

为了进行测试,我有一个简单的 Country 服务,它提供了国家/地区列表。我确定会发生错误来测试 InternalServerErrorException 的抛出:

@GET
@Override
@Path("countries")
@Produces({"application/xml"})
public List<Country> findAll() {
    try {
        int i = Integer.parseInt("moo"); //<-- generate error
        List<Country> countries = super.findAll();
        return countries;
    } catch (Exception ex) {
        throw new InternalServerErrorException("I want this message to show at client side");
    }
}

在我的客户那里,我有一个 CountryClient,方法如下:

public List<Country> findAll() throws ClientErrorException {
    WebTarget resource = webTarget;
    resource = resource.path("countries");
    return resource.request(javax.ws.rs.core.MediaType.APPLICATION_XML).get(new GenericType<List<Country>>(){});
}

在我的控制器中我是这样使用它的:

    try {
        CountryClientSSL cc = new CountryClientSSL();
        cc.setUsernamePassword(USERNAME, PASSWORD);
        ObservableList<Country> olCountries = FXCollections.observableArrayList(cc.findAll());

        tblCountries.setItems(olCountries);
        tcCountry.setSortType(SortType.ASCENDING);
        tblCountries.getSortOrder().add(tcCountry);
    } catch (Exception ex) {
        System.out.println(ex.getMessage());
    }

所以每次我在客户端使用 findAll() 方法时,我都会在输出窗口中看到以下信息:Info: I want this message to show at client side 在服务器端,HTTP 500 Internal Server Error 在客户端。

有没有办法在不使用Response 作为返回类型的情况下在客户端(在catch 块中)获取errorMessage?

我想要实现的是:当客户端发生错误时,用户可以向我的 JIRA 实例发送调试报告,其中包含大量信息,例如客户端的堆栈跟踪、有关系统,谁已登录,... 将服务器的堆栈跟踪也附在其中会很好。还是有更好的方法来实现这一目标?

【问题讨论】:

  • 是否有不能从服务器端向JIRA提交异常的原因?到目前为止,这将是上传所有异常详细信息的最简单方法。否则,您必须将其序列化为 JSON 或其他格式,以便客户端可以执行此操作。
  • 基本上是因为我想把客户端错误信息和服务器端错误信息联系起来。我能做的是从服务器端创建一个 JIRA 问题,然后将唯一键作为 errorMessage 并将其链接到在客户端创建的问题......但是我仍然需要在客户端获取 errorMessage 字符串。这会导致 2 个问题对应一个实际问题...
  • 对于 Jersey 2,如果有人想抑制 500 响应代码上的异常,请参阅此答案:stackoverflow.com/a/31360598/403999

标签: java web-services rest error-handling jersey


【解决方案1】:

有没有办法在不使用Response 作为返回类型的情况下在客户端(在catch 块中)获取errorMessage?

您可以使用response.readEntity(new GenericType&lt;List&lt;Country&gt;&gt;(){})。这样您仍然可以访问Response。虽然在这种情况下不会有堆栈跟踪。当您尝试使用get(ParsedType) 时,客户端上只有一个例外。原因是使用get(ParsedType),没有其他方法可以处理错误状态。但是使用Response,开发人员应该检查状态。所以这个方法看起来更像

public List<Country> findAll() throws ClientErrorException {
    WebTarget resource = webTarget;
    resource = resource.path("countries");
    Response response =  resource.request(javax.ws.rs.core.MediaType.APPLICATION_XML).get();
    if (response.getStatus() != 200) {
        System.out.println(response.getHeaderString("errorResponse"));
        return null;
    } else {
        return response.readEntity(new GenericType<List<Country>>(){});
    }
}

虽然不是在标题中,但我只是将消息作为响应正文发送出去。这就是我

super(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
        .entity( message).type(MediaType.TEXT_PLAIN).build());

客户端

if (response.getStatus() != 200) {
    System.out.println(response.readEntity(String.class));
    return null;
}

【讨论】:

  • 嗯,在控制器而不是 DAO 中处理响应不是更好的做法吗?在这种情况下,我必须将其更改为 public Response findAll(),我想避免这种情况,因为我有很多 DAO
  • 抱歉,我指的是服务,而不是 DAO :) 只是想知道在服务或控制器中处理响应的最佳实践。
  • 这样看。 DAO 的要点是抽象检索数据的方式。所以List&lt;Country&gt; findAll() 的调用者并不关心它是如何被检索的。它所关心的只是获取List&lt;Country&gt;。所以它不应该担心处理Response。你可以做的是创建一个专门的Exception。并且在“DAO”内部包装了调用者在调用方法时会感兴趣的所有信息。这样用户所需要做的就是处理异常,并且可以从异常中获取他们需要的所有信息。我个人认为会
  • 成为首选方式。希望你明白我在说什么。所以不要使用throws ClientErrorException,而是使用throws OtherException。然后用户可以捕获该异常并从中获取信息。
【解决方案2】:

我不相信您可以返回除 HTTP 200 (Response.ok().build) 以外的任何响应类型的自定义内容(即errorMessage)。

但是,您可以在服务器代码中引发异常,然后捕获它们并将它们转换为使用 ExceptionMapper 的有效响应。详情请见this question

【讨论】:

    猜你喜欢
    • 2013-08-02
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    • 2018-09-03
    相关资源
    最近更新 更多