2011-08-12 27 views
16

Tôi đang cố gắng viết một hàm chung trong Jersey có thể được sử dụng để tìm nạp Danh sách đối tượng cùng loại thông qua REST. Tôi dựa trên thông tin được tìm thấy trong diễn đàn này: linkTìm nạp tài nguyên REST dưới dạng Danh sách <T> với Jersey

@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>>() {}); 
} 

Tuy nhiên điều này không hiệu quả. Nếu tôi cố gắng thực hiện nó, tôi nhận được lỗi sau: 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.

Tuy nhiên nếu tôi viết chức năng này mà không cần templating (thay thế T với tên lớp thực tế) nó chỉ hoạt động tốt. Tất nhiên theo cách này, hàm sẽ mất đi ý nghĩa của nó.

Có cách nào để sửa lỗi này không?

+0

Xem bên dưới liên kết http://stackoverflow.com/questions/1603404/using-jaxb-to-unmarshal-marshal-a-liststring – fmucar

+0

@fmucar: này một lần nữa có lời khuyên cho các máy chủ như tôi hiểu rồi. Tôi cần hỗ trợ kiểu chung cho khách hàng. – NagyI

Trả lời

21

tôi đã tìm thấy giải pháp 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

Điều này làm việc với tôi với Jersey 2.9, cảm ơn bạn rất nhiều !! –

+0

BTW, Mở rộng trên ví dụ của bạn và sử dụng lớp cơ sở Collection.class cho OwnerType và RawType và điều này cũng làm việc. Vì vậy, tôi sẽ có thể sử dụng lại parameterizedType duy nhất cho tất cả các loại bộ sưu tập. –

6

Xem GenericType lớp áo mà có thể giúp bạn là tốt

Unmarshaller cần phải biết những gì loại đối tượng có trước khi nó có thể unmarhall nội dung trả lại. Như thông tin generics không có sẵn trong thời gian chạy nên những gì bạn đang yêu cầu là không thể. Nó không thể unsmarhall một cái gì đó mà nó không biết gì về.

tốt nhất bạn có thể làm là;

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

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

hoặc với Generics cảnh báo (tôi không chắc chắn nếu điều này sẽ làm việc)

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

Bạn đã cung cấp mẫu cho phía máy chủ. Làm thế nào điều này có thể giúp tôi ở phía khách hàng? Tôi có thể xem danh sách được tạo bởi máy chủ Jersey trong trình duyệt. Vấn đề của tôi là các khách hàng không thể lấy nguồn tài nguyên nếu tôi đang sử dụng chung loại trong các chức năng trên. Tôi có thể tìm nạp tài nguyên nếu tôi tự xây dựng ứng dụng khách mỗi lần tại một loại cụ thể. Tuy nhiên tôi không muốn điều này. – NagyI

+0

OK tôi hiểu. Đó là cùng một vấn đề được mô tả ở đây: http://janmaterne.wordpress.com/2008/10/10/getting-the-type-of-a-generic-class-at-runtime/ – NagyI

+0

Tôi có thể hỏi tại sao thông tin generics là không không có sẵn trong thời gian chạy? – gosua

3

Mở rộng trên user2323189, bạn có thể sử dụng Bộ sưu tập thay vì List.class để bạn có thể tuần tự hóa tất cả các loại mở rộng Bộ sưu tập. Tôi tạo một getter đơn giản trong lớp client cơ sở của mình và có thể sử dụng nó đơn giản để lấy lại bất kỳ kiểu Collection nào. Không phải biến clazz được cung cấp trong constructor của tôi vì vậy nó không phải là một đối số được cung cấp. Bạn có lẽ có thể biến điều này thành một phương thức tĩnh và sử dụng chữ ký GenericType> với một tham số cho Class để làm cho nó thậm chí còn chung chung hơn.

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){}; 
    } 
Các vấn đề liên quan