2013-09-23 288 views
0

當我使用String restTempate檢索JSON時出現錯誤。錯誤說在Spring restTemplate中找不到HttpMessageConverter

Could not extract response: no suitable HttpMessageConverter found for response type [class au.org.jeenee.mdm.models.PhoneResponse] and content type [application/json] 
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:107) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:492) 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:447) 
    at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:295) 
    at au.org.jeenee.mdm.services.EccClientServiceImpl.findPhoneByImei(EccClientServiceImpl.java:51) 
    at au.org.jeenee.mdm.controllers.DeviceController.showEditForm(DeviceController.java:308) 

我發現了該消息意味着沒有註冊任何JSON轉換器,但我有我的xml傑克遜消息變換。

的applicationContext.xml

<bean id="jacksonMessageConverter" 
    class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /> 

<bean 
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="messageConverters"> 
     <list> 
      <ref bean="jacksonMessageConverter" /> 
     </list> 
    </property> 
</bean> 

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> 
    <constructor-arg> 
     <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"> 
      <constructor-arg ref="httpClient"/> 
     </bean> 
    </constructor-arg> 
    <property name="messageConverters"> 
     <list> 
      <ref bean="jacksonMessageConverter" /> 
     </list> 
    </property> 
</bean> 

這裏是我的代碼使用RestTemplate。

public class MyRestClientService { 
@Override 
    public List<DeviceHolder> findDeviceHoldersByUserId(String userId) { 
     String uri = "/web/getpersonlist?userId=" + userId; 
     try { 
      DeviceHolderResponse response = restClient.getRestTemplate().postForObject(restClient.createUrl(uri), "", DeviceHolderResponse.class); 


      if (response!=null && response.isOk() && response.getResult()!=null){ 

       DeviceHolder[] deviceHolders = response.getResult(); 
       return Arrays.asList(deviceHolders); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     return Collections.emptyList(); 
    } 

    @Override 
    public Phone findPhoneByImei(String imei) { 
     log.info("findPhoneByImei:" + imei); 

     Phone phone = null; 
     String uri = "/ecc/getphoneplan?imei=" + imei; 
     try { 
      PhoneResponse response = restClient.getRestTemplate().postForObject(restClient.createUrl(uri), "", PhoneResponse.class); 
      if (response.getResult()!=null) 
       phone = response.getResult(); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     return phone; 
    } 
} 

PhoneResponse.java 
public class Phone implement Serializable { 
    private boolean ok; 
    private String message; 
    private Phone result; 

    //getters and setters 
} 


Phone.java 
public class Phone implements Serializable { 

    @JsonProperty(value="phoneid") 
    private long phoneId; 

    private Plan plan; 
    private String sim; 
    private String imei; 

    @JsonProperty(value="phonetype") 
    private String phoneType; 

    @JsonProperty(value="phonenumber") 
    private String phoneNumber; 
    private String label; 
    @JsonProperty(value="connecteddate") 
    private String connectedDate; 

//getters and setters 
} 

Plan.java 
public class Plan implements Serializable { 

    @JsonProperty(value="planid") 
    private long planId; 

    @JsonProperty(value="planname") 
    private String planName; 

    private double billingIncrement; 

    private double owiStdUnitCost; 

    private double owiFlagFall; 

    private double stdCap; 

    private double dataCap; 

    private double smsCap; 

    private double owiDataUnitCost; 

    private double owiSms; 

    //getters and setters 
} 

和響應包就像是以下幾點:

{ 
    "ok": true, 
    "message": "", 
    "result": 
    { 
     "phoneid": 600003, 
     "phonenumber": 478439503, 
     "phonetype": "Samsung Galaxy S2", 
     "imei": "1111111111", 
     "sim": "1111111111", 
     "label": "Person name", 
     "connecteddate": "2012-09-19 00:00:00.0", 
     "plan": 
     { 
      "planid": 34, 
      "planname": "$59 Plan", 
      "billingIncrement": 30, 
      "owiStdUnitCost": 81.8181818181818, 
      "owiFlagFall": 0, 
      "stdCap": 636.3636, 
      "dataCap": 227.2665, 
      "smsCap": 1363.638, 
      "owiDataUnitCost": 0.022194, 
      "owiSms": 22.7272727272727 
     } 
    } 
} 

奇怪的是,沒有任何錯誤,當我呼籲findPhoneByImei方法findDeviceHoldersByUserId方法,但誤差。這一直在努力。

我一次又一次嘗試,但我仍然有錯誤。請幫助解決問題。

謝謝。原因

+0

我沒有看到你在哪裏聲明瞭名稱或id爲jacksonMessageConverter的bean - 你能否澄清這個bean是在哪裏定義的 - 我很抱歉如果我錯過了這個聲明。 –

+0

@Dave我已經把它,但由於格式問題,它沒有顯示問題中的屬性。我修好了它。 – sunghun

+1

謝謝編輯回來 - 下一個問題 - 傑克遜你正在使用 - 1或2 - 我在印象之下1.試試這個 - 你可以在調試器中運行這段代碼嗎?在HttpMessageConverterExtractor.extractData()中放置一個斷點並確認它確實已經註冊了轉換器,以及被檢測轉換器的'canRead'方法可以解釋該響應。 –

回答

1

夫婦,我發現,這可能導致此問題是 -

的制定者/吸氣的
  1. 數據類型是不同的,從實際性能(在SUNGHUN的評論也提到)
  2. 的如果有重載的方法可能看起來像一個字段的setter/getter - 與setField或getField相同的名稱,其中field是該類的屬性。

我有一個場private boolean success和2 setter方法 -

public void setSuccess(List<Object> dataList); 
public void setSuccess(boolean success); 

在調試時,我發現,類com.fasterxml.jackson.databind.deser.BeanDeserializerFactory被拋出異常。這個例外在Jackson的lib中被壓制,RestTemplate拋出的異常與主題相同。

java.lang.IllegalArgumentException: Conflicting setter definitions for property "failure": com.test.dto.JsonResponse#setFailure(1 params) vs com.test.dto.JsonResponse#setFailure(1 params) 

我改變了方法爲public void setSuccessData(List<Object> dataList);它工作正常。

希望這可以幫助別人。

+1

爲了使調試更容易:異常被抑制的地方在org中.codehaus.jackson.map.deser.StdDeserializerProvider.hasValueDeserializerFor(DeserializationConfig,JavaType)。相關的代碼塊如下所示:'try {deser = _createAndCacheValueDeserializer(config,type,null); } catch(Exception e){return false; }'。在那裏設置一個斷點來進一步調查異常。 – cdauth

+0

在我們的例子中,問題是Java通用機制。我們有一個類'SuperClass ',它有一個getter'T getValue()'和一個setter'setValue(T)'。 'SubClass extends SuperClass '將setter重寫爲'setValue(Type)'。由於泛型的工作方式,getter返回Object而不是Type,所以PropertyDescriptor報告getter和setter之間不匹配。我們簡單地通過覆蓋getter來解決它:'類型getValue(){return super.getValue(); }' – cdauth

相關問題