在泽西岛利用 GenericEntity
Taking advantage of GenericEntity in Jersey
我正在 Java 中编写 RESTful Web 服务。我使用的技术:
- GlassFish 3(基于 Java6)
- JDKv7
- 泽西岛(应用服务器的一部分)
- Eclipse EE 开普勒
带注释的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();
}
当我在 Web 浏览器上通过 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 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
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 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
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()
现在,我的第二版客户端来了,现在利用 Jersey 客户端 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
对象以便更好地理解 Jersey/Java EE 的来龙去脉。
有什么想法可以解决这个问题吗?
给你,这是一个解决方案,至少在球衣方面-client.jar API。
我需要添加以下行:
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());
然后就可以在客户端读取通用实体了。
我正在 Java 中编写 RESTful Web 服务。我使用的技术:
- GlassFish 3(基于 Java6)
- JDKv7
- 泽西岛(应用服务器的一部分)
- Eclipse EE 开普勒
带注释的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();
}
当我在 Web 浏览器上通过 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 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
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 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
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()
现在,我的第二版客户端来了,现在利用 Jersey 客户端 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
对象以便更好地理解 Jersey/Java EE 的来龙去脉。
有什么想法可以解决这个问题吗?
给你,这是一个解决方案,至少在球衣方面-client.jar API。 我需要添加以下行:
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());
然后就可以在客户端读取通用实体了。