2012-06-07 90 views
5

我在使用Jersey客戶端(1.11)時JSONConfiguration.FEATURE_POJO_MAPPING設置爲true時出現了一些問題。我的測試代碼如下所示:JAX-RS Jersey客戶端使用POJO MAPPING&Jackson編組JSON響應

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 

是我的預期錯了還是我缺少明顯的東西嗎?作爲一個方面說明,如果我添加JAXB註釋到我的實體(MyFooCollectionWrapper和MyFooDTO上的@XmlRootElement)使用相同的WebResource獲取調用,客戶端我沒有得到一個消息正文閱讀器異常,但是,響應是編組,使得MyFooCollectionWrapper看起來不錯,但它的集合不包含MyFooDTO,它包含一個XML文檔,其中包含節點/ attrs中的適當值 - 換句話說,MyFooDTP不會被封送。

當按照答案中的建議將java.util.logging設置爲CONFIG時,我會看到以下內容,儘管沒有任何東西跳出來給我看。這是一個link到我放在pastebin上的輸出,因爲它的長度。

感謝,

-Noah

更新 - 解決

本來我的客戶端和客戶端配置正在像這樣創建:

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配置覆蓋。

+0

你還可以顯示你的JSON嗎? – tomfumb

回答

6

在客戶端啓用POJO映射,只是做:

ClientConfig clientConfig = new DefaultClientConfig(); 
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); 
Client client = Client.create(clientConfig); 
+0

我已經在做所有這些。這就是我上面的問題的第一句話,「我使用JSONConfiguration.FEATURE_POJO_MAPPING設置爲true時使用Jersey客戶端(1.11)的問題」是指。 – NBW

+0

這種確切的方法有效。請參閱我上面的修改意見,瞭解錯誤的細節。 – NBW

+1

很好的答案。這在配置JerseyTest時也很重要,否則只有JerseyTest的服務器部分將與POJO一起工作,並且測試類中的客戶端將失敗:https://java.net/projects/jersey/lists/users/archive/2011- 07/message/43 – pulkitsinghal

0

我相信這是因爲MyFooDTO沒有一個無參數的構造函數。

如果將java.util.logging級別更改爲CONFIG,則應該看到許多額外的消息來幫助診斷此類問題。

+0

我的代碼實際上有沒有參數的構造函數,我已經把它放在上面的示例中,但是我已經添加了它。所以即使它有一個無參數我仍然有這個問題。 – NBW

+0

我添加了CONFIG輸出。問題沒有出現。 – NBW

0

你知道我發現的方式更容易嗎?

MyFooDTO[] resp = webResource.accept(MediaType.APPLICATION_JSON).get(MyFooDTO[].class); 

通過使用數組類型,編組人員確切知道你想要插​​入什麼類型並知道它是一個集合。您沒有獲得Legit集合的所有功能,但您可以立即對其進行迭代並進行流式處理。

0

您可以啓用客戶端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>