Воспользовавшись GenericEntity в Джерси

Я пишу RESTful веб-сервис на Java. Технологии, которые я использую:

  • GlassFish 3 (на основе Java 6)
  • JDK v7
  • Джерси (часть сервера приложений)
  • Eclipse EE Kepler

Аннотированный POJO:

     @XmlRootElement(name = "entity")
    @XmlType(propOrder={"stValue", "dValue", "list"})
    @XmlAccessorType(XmlAccessType.FIELD)
    public final class EntityJAXBxml {

        @XmlAttribute
        private int id

 = 0;
    @XmlElement
    private String stValue = "";
    @XmlElement
    private double dValue = 0.0;
    @XmlElement
    @XmlElementWrapper(name="elements")
    private List<Integer> list = null;

    public EntityJAXBxml(){}    

    public EntityJAXBxml(int id, String stValue, double dValue,
            List<Integer> list) {
        super();
        this.id = id;
        this.stValue = stValue;
        this.dValue = dValue;
        this.list = list;
    }
... Getters, setters

Это мой метод обслуживания:

@GET
@Produces(MediaType.APPLICATION_XML)
@Path("/receiveXMLInGenericEntity")
public Response receiveXMLInGenericEntity(){
    EntityJAXBxml entity = new EntityJAXBxml(1, "String_value", 193.7, util.generateIntList());
    EntityJAXBxml entity_1 = new EntityJAXBxml(2, "New_string_value", 439.5, util.generateIntList());

    List<EntityJAXBxml> list = new ArrayList<>(2);
    list.add(entity);
    list.add(entity_1);

    GenericEntity<List<EntityJAXBxml>> generic = new GenericEntity<List<EntityJAXBxml>>(list){};        
    return Response.ok().entity(generic).build();
}

Когда я получаю доступ к ресурсу через URI в веб-браузере, он печатает документ XML. Таким образом, пока все работает нормально. Проблемы возникают, когда я хочу получить ответ от службы через не браузерный клиент. Например, моя клиентская реализация:

private void receiveXMLInGenericEntity(String strUrl, String method){
    HttpURLConnection connect = null;
    try {
        URL url = new URL(strUrl);
        connect = (HttpURLConnection)url.openConnection();

        connect.setRequestProperty("Accept", MediaType.APPLICATION_XML);// Accept from server
        connect.setRequestMethod(method);//GET

        connect.connect();
        Class cls = new GenericEntity<List<EntityJAXBxml>>(new ArrayList<EntityJAXBxml>()){}.getClass();

        GenericEntity<List<EntityJAXBxml>> generic = (GenericEntity<List<EntityJAXBxml>>)JAXB.unmarshal(connect.getInputStream(), cls);
        List<EntityJAXBxml> entity = generic.getEntity();

        System.out.println("GenericEntity: "+entity.size());
    }
    catch(IOException e){ e.printStackTrace();}
}

И это дает мне следующее исключение:

 Exception in thread "main" javax.xml.bind.DataBindingException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
drill.rest.client.ClientXmlV6$1 is a non-static inner class, and JAXB can't handle those.
    this problem is related to the following location:
        at drill.rest.client.ClientXmlV6$1

    at javax.xml.bind.JAXB.unmarshal(JAXB.java:226)
    at drill.rest.client.ClientXmlV6.receiveXMLInGenericEntity(ClientXmlV6.java:199)
    at drill.rest.client.ClientXmlV6.main(ClientXmlV6.java:68)
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
drill.rest.client.ClientXmlV6$1 is a non-static inner class, and JAXB can't handle those.
    this problem is related to the following location:
        at drill.rest.client.ClientXmlV6$1

    at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:106)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:466)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:298)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:141)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1163)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:145)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:235)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:432)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:637)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
    at javax.xml.bind.JAXB$Cache.<init>(JAXB.java:112)
    at javax.xml.bind.JAXB.getContext(JAXB.java:139)
    at javax.xml.bind.JAXB.unmarshal(JAXB.java:223)
    ... 2 more

Это означает, что следующий способ получения Class неверное значение типа:

Class cls = new GenericEntity<List<EntityJAXBxml>>(new ArrayList<EntityJAXBxml>()){}.getClass();

Но мне нужно это значение типа, потому что необходимо ввести следующий метод:

JAXB.unmarshal()

Теперь, вот моя вторая версия клиента, и теперь я использую преимущества клиентского API Джерси:

private void receiveXMLInGenericEntityJerseyClient(String strUrl, String method){
    Client client = Client.create();
    WebResource resource = client.resource(strUrl);

    resource.accept(MediaType.APPLICATION_XML);
    resource.method(method);

    GenericType type = new GenericType(new ArrayList<EntityJAXBxml>(Collections.EMPTY_LIST).getClass()){};      
    GenericEntity<List<EntityJAXBxml>> generic = resource.get(type);
}

Это идет с этим исключением:

    Aug 12, 2016 6:45:48 PM com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: A message body reader for Java class java.util.ArrayList, and Java type class java.util.ArrayList, and MIME media type application/xml was not found
Aug 12, 2016 6:45:48 PM com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: The registered message body readers compatible with the MIME media type are:
application/xml ->
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App
  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.core.impl.provider.entity.XMLRootElementProvider$App
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App
  com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$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.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.moxy.MoxyMessageBodyWorker
  com.sun.jersey.moxy.MoxyListMessageBodyWorker

Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: A message body reader for Java class java.util.ArrayList, and Java type class java.util.ArrayList, and MIME media type application/xml 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.get(WebResource.java:196)
    at drill.rest.client.ClientXmlV6.receiveXMLInGenericEntityJerseyClient(ClientXmlV6.java:216)
    at drill.rest.client.ClientXmlV6.main(ClientXmlV6.java:69)

В конце я хочу просто прочитать выходные данные службы в моей клиентской конечной точке. Я хочу использовать GenericEntity объект для лучшего понимания входов и выходов из Джерси /Java EE. Есть идеи как обойти эту проблему?

1 ответ

Решение

Вот, пожалуйста, это решение, по крайней мере, с точки зрения API jersey-client.jar. Мне нужно было добавить следующие строки:

List<EntityJAXBxml> g = resource.get(new GenericType<List<EntityJAXBxml>>(){});
    EntityJAXBxml entity = g.get(1);
    System.out.println(g.size()+" : "+entity.getdValue()+" : Element count: "+entity.getList().size());
    //Also valid
    //ClientResponse response = resource.get(ClientResponse.class);
    //List<EntityJAXBxml> entity = response.getEntity(new GenericType<List<EntityJAXBxml>>(){});

    //EntityJAXBxml g = entity.get(1);
    //System.out.println(entity.size()+" : "+g.getdValue()+" : Element count: "+g.getList().size());

И тогда вы можете прочитать общую сущность на стороне клиента.

Другие вопросы по тегам