web-dev-qa-db-ja.com

Spring RESTTemplateを使用したジェネリック

私はそのようなクラスを持っています:

public class Wrapper<T> {

 private String message;
 private T data;

 public String getMessage() {
    return message;
 }

 public void setMessage(String message) {
    this.message = message;
 }

 public T getData() {
    return data;
 }

 public void setData(T data) {
    this.data = data;
 }

}

そして、次のようにresttemplateを使用します。

...
Wrapper<Model> response = restTemplate.getForObject(URL, Wrapper.class, myMap);
Model model = response.getData();
...

ただし、以下をスローします。

ClassCastException

私はそれを読みました: Javaでジャクソンを使用しようとするときの問題 が助けにはなりませんでした。私の問題などに関連するトピックがいくつかあります。 https://jira.springsource.org/browse/SPR-7002 および https://jira.springsource.org/browse/ SPR-702

何か案は?

PS:私のエラーは:

Java.lang.ClassCastException: Java.util.LinkedHashMap cannot be cast to a.b.c.d.Model

Resttemplateはジェネリック変数を理解できず、ジェネリックTの代わりにオブジェクトとして受け入れるかもしれません。したがって、LinkedHashMapになります。あなたはそれから読むことができます here それは何からマーシャルするかを説明するとき、それを言う:

JSONタイプ| Javaタイプ

オブジェクト| LinkedHashMap

54
kamaci

この問題を回避するために、3.2 M2でParameterizedTypeReferenceが導入されました。

Wrapper<Model> response = restClient.exchange(loginUrl, 
                          HttpMethod.GET, 
                          null, 
                          new ParameterizedTypeReference<Wrapper<Model>>() {}).getBody();

ただし、postForObject/getForObjectバリアントは導入されていません。

105

あなたができると思う唯一のことは、Wrapperを拡張し、モデルをジェネリックとして使用する新しいクラスを作成することです。

class WrapperWithModel extends Wrapper<Model>{};

WrapperWithModel response = restTemplate.getForObject(URL, WrapperWithModel.class);

これは最善の解決策ではありませんが、少なくとも手動で応答をアンマーシャリングする必要はありません。

7
Juan Luis

RestTemplateでジェネリックを使用しないでください。ジェネリックを隠すラッパーオブジェクトで要求および応答オブジェクトをラップします。

3
Dima