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?