Jersey GET 请求可以返回多态实体吗​​?

发布于 2024-09-18 02:10:18 字数 1627 浏览 2 评论 0原文

我有一个 Resource 类,它尝试返回一个接口类型,例如“Shape”:

public interface Shape {...}

@XmlRootElement
public class Circle implements Shape {...}

@Path("/api/shapes")
public class ShapeResource {
    @GET
    @Path("/{shapeId}")
    public Shape get(@PathParam("shapeId") String shapeId) {
        ....
        return new Circle();
    }
}

通过上面的实验,我发现服务器正在返回 XML,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<circle>
...
</circle>

到目前为止一切顺利。问题是,客户端不知道如何解组它。我得到:

com.sun.jersey.api.client.ClientHandlerException: A message body for Java type, interface Shape, and MIME media type, application/xml, was not found

给定一个 WebResource,并请求 Shape.class 的实体类型会导致异常。

服务器似乎正在做正确的事情。我已经为如何让客户端反序列化此类而苦苦挣扎了几个小时。我什至尝试包装接口,我真的想进入包装器,如下所述: https ://jaxb.dev.java.net/guide/Mapping_interfaces.html。那也没用。

我的客户端代码如下所示:

    ClientResponse response = get(wr, ClientResponse.class); // wr == WebResource
    try {
        return response.getEntity(Shape.class); // <-- FAIL       
    } catch (Exception e) {
        e.printStackTrace();
        // com.sun.jersey.api.client.ClientHandlerException: A message body reader for Java type, interface Shape, and MIME media type, application/xml, was not found
    }
    try {
        return response.getEntity(Circle.class); // <-- WIN, but hacky and forces me to try every concrete type
    } catch (Exception e) {}
    return null;

非常感谢任何见解或指导。 提前致谢。

I've got a Resource class that attempts to return an interface type, say "Shape":

public interface Shape {...}

@XmlRootElement
public class Circle implements Shape {...}

@Path("/api/shapes")
public class ShapeResource {
    @GET
    @Path("/{shapeId}")
    public Shape get(@PathParam("shapeId") String shapeId) {
        ....
        return new Circle();
    }
}

Experimenting with the above, I see that the server is returning XML like so:

<?xml version="1.0" encoding="UTF-8"?>
<circle>
...
</circle>

So far so good. The problem is, the client doesn't know how to unmarshall this. I'm getting:

com.sun.jersey.api.client.ClientHandlerException: A message body for Java type, interface Shape, and MIME media type, application/xml, was not found

Given a WebResource, and asking for an entity type of Shape.class causes an exception.

The server seems to be doing the correct thing. I've been struggling for hours on how to get the Client to deserialize this class. I even tried wrapping the interface I'm really trying to get in a wrapper as outlined here: https://jaxb.dev.java.net/guide/Mapping_interfaces.html. That didn't work either.

My Client code looks like this:

    ClientResponse response = get(wr, ClientResponse.class); // wr == WebResource
    try {
        return response.getEntity(Shape.class); // <-- FAIL       
    } catch (Exception e) {
        e.printStackTrace();
        // com.sun.jersey.api.client.ClientHandlerException: A message body reader for Java type, interface Shape, and MIME media type, application/xml, was not found
    }
    try {
        return response.getEntity(Circle.class); // <-- WIN, but hacky and forces me to try every concrete type
    } catch (Exception e) {}
    return null;

Any insight or guidance is greatly appreciated.
Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

薄暮涼年 2024-09-25 02:10:18

问题可能不在于您正在使用的 JAXB 的实现,因为消息已正确编组。

相反,问题在于以下调用:

return response.getEntity(Shape.class); 

我不确定这是如何实现的,但我可以想象它会执行类似以下的操作,这将是无效的:

jaxbContext.createUnmarshaller.unmarshal(xmlSource, Shape.class);

因为看起来所有 Shape 的实现都用 @ 注释XmlRootElement,我们需要一种方法来触发对 JAXB 的以下调用:

jaxbContext.createUnmarshaller.unmarshal(xmlSource);

您可以在 Jersey 客户端 API 之外执行此操作:

URL url = new URL("http://www.example.com/api/shapes/123");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");

JAXBContext jaxbContext = JAXBContext.newInstance(Circle.class, Square.class, Triangle.class);
Shape shape = (Shape) jaxbContext.createUnmarshaller().unmarshal(connection.getInputStream());

connection.disconnect();

因此应该有一种方法可以使用 Jersey 客户端 API 来执行此操作。

The problem probably isn't with the implementation of JAXB that you are using since the message is being marshalled correctly.

Instead the problem is with the following call:

return response.getEntity(Shape.class); 

I'm not sure how this is implemented, but I can imagine that it does something like the following, which would be invalid:

jaxbContext.createUnmarshaller.unmarshal(xmlSource, Shape.class);

Since it appears that all of your implementations of Shape are annotated with @XmlRootElement, we need a way to trigger the following call to JAXB:

jaxbContext.createUnmarshaller.unmarshal(xmlSource);

You could doe this outside of the Jersey client APIs:

URL url = new URL("http://www.example.com/api/shapes/123");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");

JAXBContext jaxbContext = JAXBContext.newInstance(Circle.class, Square.class, Triangle.class);
Shape shape = (Shape) jaxbContext.createUnmarshaller().unmarshal(connection.getInputStream());

connection.disconnect();

So there should be a way to do it with Jersey client APIs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文