[英]JAX-RS Jersey Client marshaling JSON response with POJO MAPPING & Jackson
使用Jersey客戶端(1.11)並將JSONConfiguration.FEATURE_POJO_MAPPING設置為true時,我遇到了一些問題。 我的測試代碼如下所示:
MyFooCollectionWrapper<MyFooDTO> resp
= webResource.accept(MediaType.APPLICATION_JSON)
.get(new GenericType<MyFooCollectionWrapper<MyFooDTO>>() {});
在服務器上:
1)我的web.xml將POJO映射設置為true。
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看起來像這樣:
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 ..
}
我已驗證服務器在創建Json響應方面沒有問題。 如果將響應類型設置為String,則可以使用Jersey客戶代碼進行檢索。 當我使用
MyFooCollectionWrapper<MyFooDTO> resp = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<MyFooCollectionWrapper<MyFooDTO>>() {});
我希望POJO映射可以正常工作(將響應編組),而無需任何自定義消息正文閱讀器。 但是,我得到:
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)
客戶端測試中的類路徑包括:
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
我的期望是錯誤的還是我在這里缺少明顯的東西?
附帶說明一下,如果我使用相同的webResource get調用將JAXB注釋添加到我的實體(MyFooCollectionWrapper和MyFooDTO上的@XmlRootElement),則客戶端不會收到消息正文閱讀器異常,但是,響應被封送,使得MyFooCollectionWrapper看起來不錯,但是其集合不包含MyFooDTO,而是包含在節點/屬性中具有正確值的XML文檔-換句話說,MyFooDTP不會被封送。
當按照答案中的建議將java.util.logging設置為CONFIG時,我看到以下內容,盡管沒有任何變化。 這是到我的輸出的鏈接 ,由於長度原因,我將其粘貼到pastebin上。
謝謝,
-諾亞
更新-解決
最初,我的客戶端和客戶端配置是這樣創建的:
Client rootClient = new Client();
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = new Client(rootClient, clientConfig);
當我將其更改為簡單
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
一切正常。 看來rootClient覆蓋了新客戶端上的clientConfig。 奇怪的是,當您使用指定ClientConfig的構造函數時,該ClientConfig被rootClients配置覆蓋。
要在客戶端啟用POJO映射,只需執行以下操作:
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
我相信這是因為MyFooDTO
沒有no-arg構造函數。
如果將java.util.logging級別更改為CONFIG
,則應該看到許多有助於診斷此類問題的其他消息。
你知道我覺得更容易嗎?
MyFooDTO[] resp = webResource.accept(MediaType.APPLICATION_JSON).get(MyFooDTO[].class);
通過使用數組類型,marshaller可以准確知道要插入的類型,並且知道它是一個集合。 您沒有獲得Legit集合的所有功能,但可以立即對其進行迭代並進行流式處理。
您可以在客戶端啟用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);
如果您有對象列表作為響應,則可以執行此操作
List<POJOObject> pojoList = webResource.get(new GenericType<List<POJOObject>>() { });
您需要使用這些依賴項
<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.