2016-08-12 2 views
0

J'écris un service Web RESTful en Java. Les technologies que j'utilise:Profiter de GenericEntity à Jersey

  • GlassFish 3 (basé sur Java 6)
  • JDK
  • Jersey (partie du serveur d'applications)
  • Eclipse EE Kepler

annotés 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 

C'est ma méthode de service: Lorsque j'accède à la ressource via l'URI sur le navigateur Web, il imprime le document XML. Ainsi, jusqu'à présent, cela fonctionne bien. Des problèmes surviennent lorsque je souhaite obtenir la réponse du service via un client non navigateur. Par exemple, ce qui suit est mon implémentation client:

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

Et il me donne l'exception suivante:

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 

Cela signifie que la façon suivante d'obtenir Class valeur de type est erroné:

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

Mais j'ai besoin de cette valeur de type, car il faut entrer la méthode suivante:

JAXB.unmarshal() 

Maintenant, ici il vient ma deuxième version du client, et maintenant en profitant de Jersey API client:

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); 
} 

Il est livré avec cette exception:

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) 

En fin de compte, ce que je veux, c'est juste lire la sortie du service à mon client-end-point. Je souhaite utiliser l'objet GenericEntity afin de mieux comprendre les tenants et les aboutissants Jersey/Java EE. Des idées pour contourner ce problème?

Répondre

0

Voilà, c'est une solution, du moins en termes d'API jersey-client.jar. je besoin d'ajouter les lignes suivantes:

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()); 

Et vous pouvez lire une entité générique du côté client.