Microprofile java.lang.ClassCastException: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream 不兼容

问题描述

我正在使用 microprofile 3.2 来调用在响应实体中返回 java bean 的休息 web 服务。当我尝试从响应中提取 bean 时,虽然我得到了一个

java.lang.classCastException: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream incompatible with <class>

错误

例如

我的豆子:

public class MyBean {
    private int id;
    public int getId() { return id; }
    public void setId(final int id) { this.id = id; }
}

REST WS api 接口:

@GET
@Path("/{id}")
Response getBean(@PathParam("id") Integer id);

REST 实现类:

public Response getBean(final Integer id) {
    MyBean myBean = new Service().getBean(id);
    return Response.ok(myBean).build();
}

RestClient:

IBeanResource beanResource = 
RestClientBuilder.newBuilder().baseUri(apiURI).build(IBeanResource.class);
Response beanResponse = beanResource.getBean(100);
if (beanResponse.getStatus() == Response.Status.OK.getStatusCode()) {
    MyBean bean = (MyBean) beanResponse.getEntity();
}

在线触发错误

MyBean bean = (MyBean) beanResponse.getEntity();

有人见过这个吗?文档不是很好。

解决方法

是的,这将是预期的行为。如果您在调试中检查 beanResponse 的值,您将看到 Response 的类型为 InboundJaxrsResonse,而 entity 的类型仅为 HttpUrlConnector。这就是为什么当您尝试将其强制转换为自定义 bean 类时,它会抛出 ClassCastException。您可以尝试以下任何一种方法:

  1. 你可以改为如下

    String jsonString = beanResponse.readEntity(String.class);

以上内容将以字符串形式为您提供 JSON 响应,然后您可以使用您选择的 gson 或 jackson 等库将其转换为您各自的类。

  1. 在您的 REST WS api 接口中,而不是返回 Response 返回您的模型 MyBean。根据 Microprofile rest Client 规范,Microprofile Rest 客户端的实现必须提供内置的 JSON-P 实体提供程序,如果它支持 JSON-B,则必须提供 JSON-B 实体提供程序。

microprofile-rest-client-spec-2.0

,

谢谢回复。我将再次查看返回模型的规范。我喜欢捕获响应而不是模型的想法,所以我也有任何标题或状态信息,例如找不到资源怎么办404?

我能够通过读取 InputStream 并使用 jsonb 绑定到 bean 来解决这个问题

InputStream is = (InputStream) beanResponse.getEntity();
return jsonb.fromJson(is,MyBean.class);