利用泽西岛的GenericEntity(Taking advantage of GenericEntity in Jersey)
我正在用Java编写RESTful Web服务。 我使用的技术:
- GlassFish 3(基于Java 6)
- JDK v7
- Jersey(应用程序服务器的一部分)
- 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(); }
当我通过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$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()
现在,它来到我的第二个版本的客户端,现在利用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的细节。 任何想法如何解决这个问题?I'm writing RESTful Web service in Java. The technologies that I use:
- GlassFish 3 (based on Java 6)
- JDK v7
- Jersey (part of the application server)
- Eclipse EE Kepler
The annotated 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
That's my service method:
@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(); }
When I access the resource via URI on the Web browser, it prints the XML document. Thus, so far it works fine. Problems come in when I want to get the response from the service via non-browser client. For example, the following is my client implementation:
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();} }
And it gives me the following exception:
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
That means that the following way of getting
Class
type value is wrong:Class cls = new GenericEntity<List<EntityJAXBxml>>(new ArrayList<EntityJAXBxml>()){}.getClass();
But I need that type value, because it's needed input at the following method:
JAXB.unmarshal()
Now, here it comes my second version of client, and now taking advantage of Jersey client 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); }
It comes with this 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)
In the end, what I want is just to read the output from the service at my client-end-point. I want to use the
GenericEntity
object in order to have better understanding of Jersey/Java EE ins-and-outs. Any ideas how to get around this problem?
原文:https://stackoverflow.com/questions/38923951
最满意答案
你获得所有空间的原因是因为你自己在
#spotlight
上放置了所有顶部填充和边距。 您似乎正在添加所有空间,以便为其中的浮动提供足够的空间。 不要那样做。 通过添加overflow: hidden
来使div包含其浮点数。 如果这有不必要的副作用,请添加clearfix
类,它已经在CSS中。你在IE7中看到所有空间的原因是因为
#spotlight
有一个宽度,即触发布局 。 这导致它已经包含它的浮动,推动所有顶部边缘并在其上方填充。哦,不要使用多个
id="spotlightbox"
。 这就是课程的用途。 ID必须是唯一的。 请改用class="spotlightbox"
。The reason you're getting all that space is because of all the top padding and margin you put on the
#spotlight
yourself. You seem to be adding all that space as a way of making enough room for the floats inside it. Don't do that. Make the div contain its floats by addingoverflow: hidden
to it. If that has unwanted side-effects, add theclearfix
class to it, which is already in your CSS.The reason you're seeing all that space in IE7 is because the
#spotlight
has a width, which is triggering layout. That causes it to contain its floats already, pushing all that top margin and padding up above it.Oh, and don't use multiple
id="spotlightbox"
. That's what classes are for. IDs must be unique. Useclass="spotlightbox"
instead.