2011-08-12 7 views
16

Jersey에 일반 함수를 작성하려고합니다. REST를 통해 같은 유형의 객체 목록을 가져 오는 데 사용할 수 있습니다. 나는이 포럼에있는 정보에 기반 : link목록으로 REST 리소스를 가져 오는 중

@Override 
public <T> List<T> fetchResourceAsList(String url) { 
    ClientConfig cc = new DefaultClientConfig(); 
    Client c = Client.create(cc); 
    if (userName!=null && password!=null) { 
    c.addFilter(new HTTPBasicAuthFilter(userName, password)); 
    } 
    WebResource resource = c.resource(url); 
    return resource.get(new GenericType<List<T>>() {}); 
} 

을하지만이 작동하지 않습니다. 만약 내가 그것을 실행하려고하면 다음 오류가 나타납니다 : SEVERE: A message body reader for Java class java.util.List, and Java type java.util.List<T>, and MIME media type application/xml was not found.

그러나 템플릿을 사용하지 않고이 함수를 작성하면 (T를 실제 클래스 이름으로 바꾼다) 괜찮습니다. 물론이 방법은 함수가 의미를 상실합니다.

해결 방법이 있습니까? 당신이 도움이 될 수 있습니다 저지의

+0

은 아래 링크를 참조 http://stackoverflow.com/questions/1603404/using-jaxb-to-unmarshal-marshal-a-liststring – fmucar

+0

@fmucar이 다시 서버로에 대한 팁이있다 내가 참조. 클라이언트에 대한 제네릭 형식 지원이 필요합니다. – NagyI

답변

21

내가 찾은 솔루션 https://java.net/projects/jersey/lists/users/archive/2011-08/message/37

public <T> List<T> getAll(final Class<T> clazz) { 

    ParameterizedType parameterizedGenericType = new ParameterizedType() { 
     public Type[] getActualTypeArguments() { 
      return new Type[] { clazz }; 
     } 

     public Type getRawType() { 
      return List.class; 
     } 

     public Type getOwnerType() { 
      return List.class; 
     } 
    }; 

    GenericType<List<T>> genericType = new GenericType<List<T>>(
      parameterizedGenericType) { 
    }; 

    return service.path(Path.ROOT).path(clazz.getSimpleName()) 
      .accept(MediaType.APPLICATION_XML).get(genericType); 
} 
+0

Jersey 2.9와 함께 작동하는이 양식은 정말 감사합니다 !! –

+0

BTW, 귀하의 예제를 확장하고 OwnerType과 RawType에 대한 기본 클래스 Collection.class를 사용했습니다. 그래서 모든 컬렉션 유형에 대해 단일 parameterizedType을 재사용 할 수 있어야합니다. –

6

참조 GenericType 클래스뿐만 아니라

Unmarshaller에는 반환 된 내용을 unmarhall 전에이 객체를 입력 한 내용을 알 필요가있다. 제네릭 정보는 런타임에 사용할 수 없으므로 사용자가 묻는 것은 불가능합니다. 그것은 말하지 않는다는 것을 말하지 않는다.

할 수있는 최선의 방법은 다음과 같습니다.

public <T> List<T> fetchResourceAsList(Class<?> beanClass, String url) { 
    ... 

    if(beanCLass.equals(MyBean.class)){ 
     return resource.get(new GenericType<List<MyBean>>() 
    }else if(...){ 
     ... 
    }... 
} 

또는 제네릭 경고와 함께

(이 작동하는지 확실하지 않다)

public List fetchResourceAsList(String url) { 
    ... 
     return resource.get(new GenericType<List<Serializable>>() 
} 
+0

서버 측 샘플을 제공했습니다. 이것이 클라이언트 측에서 어떻게 도움이 될 수 있습니까? Jersey 서버에서 생성 한 목록을 브라우저에서 볼 수 있습니다. 내 문제는 클라이언트가 위의 함수에서 제네릭 형식을 사용하고있는 경우 리소스를 가져올 수 없다는 것입니다. 특정 유형의 클라이언트를 매번 수동으로 구성하면 리소스를 가져올 수 있습니다. 그러나 나는 이것을 원하지 않는다. – NagyI

+0

알겠습니다. 그것은 여기에 설명 된 것과 같은 문제입니다 : http://janmaterne.wordpress.com/2008/10/10/getting-the-type-of-a-generic-class-at-runtime/ – NagyI

+0

왜 제네릭 정보가 isn 런타임 중에 사용할 수 없습니까? – gosua

3

user2323189에 확장, 당신은 컬렉션을 사용할 수 있습니다 List.class 대신 Collection을 확장하여 모든 유형의 컬렉션을 직렬화 할 수 있습니다. 내 기본 클라이언트 클래스에 간단한 getter를 만들고이 클래스를 사용하여 모든 유형의 Collection을 검색 할 수 있습니다. clazz 변수는 제공된 생성자에서 제공되지 않으므로 제공된 인수가 아닙니다. 아마도 이것을 정적 메소드로 바꾸고 클래스의 매개 변수와 함께 GenericType> 시그니처를 사용하여 훨씬 더 일반적인 것으로 만들 수 있습니다.

public GenericType<Collection<T>> getParameterizedCollectionType() { 
     ParameterizedType parameterizedGenericType = new ParameterizedType() { 
      public Type[] getActualTypeArguments() { 
       return new Type[] { clazz }; 
      } 

      public Type getRawType() { 
       return Collection.class; 
      } 

      public Type getOwnerType() { 
       return Collection.class; 
      } 
     }; 
     return new GenericType<Collection<T>>(parameterizedGenericType){}; 
    } 
관련 문제