[英]JAX-RS Jersey Client marshaling JSON response with POJO MAPPING & Jackson
I'm having a bit of an issue using Jersey client (1.11) with JSONConfiguration.FEATURE_POJO_MAPPING set to true. 使用Jersey客户端(1.11)并将JSONConfiguration.FEATURE_POJO_MAPPING设置为true时,我遇到了一些问题。 My test code looks like this:
我的测试代码如下所示:
MyFooCollectionWrapper<MyFooDTO> resp
= webResource.accept(MediaType.APPLICATION_JSON)
.get(new GenericType<MyFooCollectionWrapper<MyFooDTO>>() {});
On the server: 在服务器上:
1) my web.xml has POJO Mapping set to true. 1)我的web.xml将POJO映射设置为true。
2) MyFooDTO is simply a POJO that looks like this: 2)MyFooDTO只是一个POJO,看起来像这样:
public class MyFooDTO {
private long id;
private String propA;
pubic long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
pubic String getPropA() {
return propA;
}
public void setPropA(String propA) {
this.propA = propA;
}
public MyFooDTO(MyFoo aFoo) {
this.id = aFoo.getId();
this.propA = aFoo.getPropA();
}
public MyFooDTO() {}
}
3) MyFooCollectionWrapper looks like this: 3)MyFooCollectionWrapper看起来像这样:
public class MyFooCollectionWrapper<T> extends MyFooCollectionWrapperBase {
Collection<T> aCollection;
public MyFooCollectionWrapper() {
super();
}
public MyFooCollectionWrapper(boolean isOK, String msg, Collection<T> col) {
super(isOK, msg);
this.aCollection = col;
}
public void setCollection(Collection<T> collection) {
this.aCollection = collection;
}
@JsonProperty("values")
public Collection<T> getCollection() {
return aCollection;
}
}
public class MyFooCollectionWrapperBase {
private boolean isOK;
private String message;
public MyFooCollectionWrapperBase() {
this.message = "";
this.isOK = false;
}
public MyFooCollectionWrapperBase(boolean ok, String msg) {
this.isOK = ok;
this.message = msg;
}
.. standard getter/setters ..
}
I've verified server has no problem creating the Json response. 我已验证服务器在创建Json响应方面没有问题。 I can retrieve with my Jersey client code if I set the response type to String.
如果将响应类型设置为String,则可以使用Jersey客户代码进行检索。 When I use
当我使用
MyFooCollectionWrapper<MyFooDTO> resp = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<MyFooCollectionWrapper<MyFooDTO>>() {});
I would expect POJO mapping to just work (marshall the response) without any need for a custom message body reader. 我希望POJO映射可以正常工作(将响应编组),而无需任何自定义消息正文阅读器。 However, I get:
但是,我得到:
Jun 04, 2012 3:02:20 PM com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: A message body reader for Java class com.foo.MyFooCollectionWrapper, and Java type com.foo. MyFooCollectionWrapper<com.foo.MyFooDTO>, and MIME media type application/json was not found
Jun 04, 2012 3:02:20 PM com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: The registered message body readers compatible with the MIME media type are:
application/json ->
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$App
com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$App
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$App
*/* ->
com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider
com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.ReaderProvider
com.sun.jersey.core.impl.provider.entity.DocumentProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$General
com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$General
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General
com.sun.jersey.core.impl.provider.entity.EntityHolderReader
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General
com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy
com.sun.jersey.moxy.MoxyMessageBodyWorker
com.sun.jersey.moxy.MoxyListMessageBodyWorker
com.sun.jersey.api.client.ClientHandlerException: A message body reader for Java class com.foo.MyFooCollectionWrapper, and Java type com.foo. MyFooCollectionWrapper<com.foo. MyFooDTO>, and MIME media type application/json was not found
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:550)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:524)
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:686)
at com.sun.jersey.api.client.WebResource.access$300(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:508)
The class path on the client side test includes: 客户端测试中的类路径包括:
jersey-test-framework-core-1.11.jar
jersey-test-framework-embedded-glassfish-1.11.jar
jersey-test-framework-grizzly-1.11.jar
jersey-test-framework-http-1.11.jar
jersey-test-framework-inmemory-1.11.jar
jackson-core-asl.jar
jackson-jaxrs.jar
jackson-xc.jar
jackson-client.jar
jersey-client.jar
jersey-core.jar
jersey-json.jar
jettison.jar
Are my expectations wrong or am I missing something obvious here? 我的期望是错误的还是我在这里缺少明显的东西?
As a side note, if I add JAXB annotations to my entities (@XmlRootElement on MyFooCollectionWrapper and MyFooDTO) the using the same webResource get call, the client I do not get a message body reader exception, however, the response is marshaled such that MyFooCollectionWrapper looks ok but its collection does not contain a MyFooDTO it contains an XML Document with the proper values in the nodes/attrs - in other words MyFooDTP doesn't get marshaled. 附带说明一下,如果我使用相同的webResource get调用将JAXB注释添加到我的实体(MyFooCollectionWrapper和MyFooDTO上的@XmlRootElement),则客户端不会收到消息正文阅读器异常,但是,响应被封送,使得MyFooCollectionWrapper看起来不错,但是其集合不包含MyFooDTO,而是包含在节点/属性中具有正确值的XML文档-换句话说,MyFooDTP不会被封送。
When setting java.util.logging to CONFIG as was suggested in an Answer I see the following, though nothing jumps out to me. 当按照答案中的建议将java.util.logging设置为CONFIG时,我看到以下内容,尽管没有任何变化。 Here's a link to the output which I put on pastebin because of the length.
这是到我的输出的链接 ,由于长度原因,我将其粘贴到pastebin上。
Thanks, 谢谢,
-Noah -诺亚
UPDATE - SOLVED 更新-解决
Originally my client and client config were being created like so: 最初,我的客户端和客户端配置是这样创建的:
Client rootClient = new Client();
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = new Client(rootClient, clientConfig);
When I changed this to simply 当我将其更改为简单
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
Things worked. 一切正常。 It appears the rootClient was overriding the clientConfig on the new client.
看来rootClient覆盖了新客户端上的clientConfig。 It seems odd that when you use a constructor that specifies a ClientConfig the ClientConfig gets overridden by the rootClients config.
奇怪的是,当您使用指定ClientConfig的构造函数时,该ClientConfig被rootClients配置覆盖。
To enable POJO mapping on the client side, just do : 要在客户端启用POJO映射,只需执行以下操作:
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
I believe it is because MyFooDTO
does not have a no-arg constructor. 我相信这是因为
MyFooDTO
没有no-arg构造函数。
If you change the java.util.logging level up to CONFIG
, you should see a number of extra messages that help diagnose such problems. 如果将java.util.logging级别更改为
CONFIG
,则应该看到许多有助于诊断此类问题的其他消息。
You know what I find WAY easier? 你知道我觉得更容易吗?
MyFooDTO[] resp = webResource.accept(MediaType.APPLICATION_JSON).get(MyFooDTO[].class);
By using an array type the marshaller knows exactly what type you want to pull in and knows it's a collection. 通过使用数组类型,marshaller可以准确知道要插入的类型,并且知道它是一个集合。 You don't get all the functionality of a Legit collection, but you can immediately iterate it and stream it.
您没有获得Legit集合的所有功能,但可以立即对其进行迭代并进行流式处理。
you can enable POJO mapping on client side as shown below 您可以在客户端启用POJO映射,如下所示
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
WebResource webResource = client
.resource("http://localhost:8080/api/url");
ClientResponse response = webResource.accept("application/json")
.get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
POJOObject output = response.getEntity(POJOObject.class);
in case you have list of objects in response then you can do this 如果您有对象列表作为响应,则可以执行此操作
List<POJOObject> pojoList = webResource.get(new GenericType<List<POJOObject>>() { });
you need to use these dependencies 您需要使用这些依赖项
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.18.1</version>
</dependency>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.