[英]@XmlAnyElement does not unmarshal into specific Java type, but stop at JAXBElement
To learn how to use @XmlAnyElement
, I created the following test service: 为了学习如何使用
@XmlAnyElement
,我创建了以下测试服务:
@WebService(serviceName = "TestServices")
@Stateless()
public class TestServices {
@WebMethod(operationName = "testMethod")
public ServiceResult testMethod() {
ServiceResult result = new ServiceResult();
result.addObject(new SimpleObj(1, 2));
result.addObject(new SimpleObj(3, 4));
return result;
}
}
SimpleObj
is a simple class with 2 int
fields. SimpleObj
是具有2个int
字段的简单类。 Below is the code for the ServiceResult
class: 下面是
ServiceResult
类的代码:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({SimpleObj.class})
public class ServiceResult {
@XmlAnyElement(lax = true)
private List<Object> body;
public void addObject(Object objToAdd) {
if (this.body == null)
this.body = new ArrayList();
this.body.add(objToAdd);
}
// Getters and Setters
}
To consume the above service, I created an appclient with the following Main
class: 为了使用上述服务,我使用以下
Main
类创建了一个appclient:
public class Main {
@WebServiceRef(wsdlLocation = "META-INF/wsdl/localhost_8080/TestServices/TestServices.wsdl")
private static TestServices_Service service;
private static TestServices port;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
port = service.getAdminServicesPort();
ServiceResult result = port.testMethod();
for (Object o : result.getAny()) {
System.out.println("TEST: " + o);
}
}
}
Based on the documentation, with @XmlAnyElement
, the unmarshaller will eagerly unmarshal this element to a JAXB object. 根据文档,使用
@XmlAnyElement
,解组器会急切将此元素解组到JAXB对象。 However, what I observed is that JAXB only parsed my object into JAXBElement
instead of going all the way into SimpleObj
. 但是,我观察到的是JAXB仅将我的对象解析为
JAXBElement
而不是完全解析为SimpleObj
。
I'd be extremely grateful if you could show me how I can get SimpleObj
out of the ServiceResult
. 如果您能向我展示如何从
ServiceResult
获取SimpleObj
,我将不胜感激。
UPDATE : 更新 :
Below is the SimpleObj
class: 下面是
SimpleObj
类:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class SimpleObj {
private int a;
private int b;
public SimpleObj() {}
public SimpleObj(int a, int b) {
this.a = a;
this.b = b;
}
// Getters and Setters
}
I am unable to reproduce the issue that you are seeing. 我无法重现您看到的问题。 Below is some demo code that interacts directly with JAXB.
下面是一些直接与JAXB交互的演示代码。
import java.io.*;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(ServiceResult.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StringReader xml = new StringReader("<serviceResult><simpleObj/><simpleObj/></serviceResult>");
ServiceResult result = (ServiceResult) unmarshaller.unmarshal(xml);
for(Object item : result.getBody()) {
System.out.println(item.getClass());
}
}
}
The output from running the demo code shows that it is instances of SimpleObj
in the field annotated with @XmlAnyElement(lax=true)
. 运行演示代码的输出显示,它是在
@XmlAnyElement(lax=true)
注释的字段中的SimpleObj
实例。
class forum27871349.SimpleObj
class forum27871349.SimpleObj
On the side note, I've read your blog articles on @XmlAnyElement and I've never seen you had to include @XmlSeeAlso({SimpleObj.class}) in any of your examples.
在旁注中,我阅读了您在@XmlAnyElement上的博客文章,而且从未见过您必须在任何示例中都包含@XmlSeeAlso({SimpleObj.class})。
I'm not sure why I never leverage @XmlSeeAlso
in my examples. 我不确定为什么我在示例中从未使用
@XmlSeeAlso
。
However, in my case, if I don't have this, I would have the error saying Class *** nor any of its super class is known to this context.
但是,在我的情况下,如果我没有这个,我会得到这样的错误:***类或其任何超类都不为该上下文所知。 It'd be great if you could also show me if there is a way to make all of these classes known to the consumer without using @XmlSeeAlso
如果您还可以告诉我是否有一种方法可以让消费者在不使用@XmlSeeAlso的情况下了解所有这些类,那就太好了
When you are creating the JAXBContext
yourself, you simply need to include anything you would have referenced in an @XmlSeeAlso
annotation as part of the classes you used to bootstrap the JAXBContext
. 当您自己创建
JAXBContext
,只需要包含您在@XmlSeeAlso
批注中引用的所有内容, @XmlSeeAlso
作为用来引导JAXBContext
的类的一部分。
JAXBContext jc = JAXBContext.newInstance(ServiceResult.class, SimpleObj.class);
In a JAX-WS (or JAX-RS) setting where you don't have direct access to the JAXBContext
I would recommend using the @XmlSeeAlso
annotation like you have done. 在您没有直接访问
JAXBContext
的JAX-WS(或JAX-RS)设置中,我建议像您一样使用@XmlSeeAlso
批注。
Regarding the @XmlAnyElement, from the documentation, I thought if the unmarshaller cannot unmarshal elements into JAXB objects or JAXBElement objects, I will at least get a DOM node.
关于@XmlAnyElement,我从文档中认为,如果解组器无法将元素解组到JAXB对象或JAXBElement对象中,则至少会得到一个DOM节点。
When you have a property mapped with @XmlAnyElement(lax=true)
the following will happen: 当您使用
@XmlAnyElement(lax=true)
映射属性时,将发生以下情况:
@XmlRootElement
of a class, then you will get an instance of that class. @XmlRootElement
,则您将获得该类的实例。 @XmlElementDecl
of a class on the ObjectFactory
or another class annotated with @XmlRegistry
then you will get an instance of that class wrapped in an instance of JAXBElement
. ObjectFactory
上一个类的@XmlElementDecl
或另一个带有@XmlRegistry
注释的类,那么您将获得该类的实例,该实例包装在JAXBElement
的实例中。 Element
. Element
。 I will demonstrate below with an example. 我将在下面举例说明。
ObjectFactory 的ObjectFactory
import javax.xml.namespace.QName;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
@XmlRegistry
public class ObjectFactory {
@XmlElementDecl(name="simpleObjJAXBElement")
public JAXBElement<SimpleObj> createSimpleObj(SimpleObj simpleObj) {
return new JAXBElement<SimpleObj>(new QName("simpleObjJAXBElement"), SimpleObj.class, simpleObj);
}
}
Demo 演示
import java.io.*;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(ServiceResult.class, ObjectFactory.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StringReader xml = new StringReader("<serviceResult><simpleObj/><unmapped/><simpleObjJAXBElement/></serviceResult>");
ServiceResult result = (ServiceResult) unmarshaller.unmarshal(xml);
for(Object item : result.getBody()) {
System.out.println(item.getClass());
}
}
}
Output 产量
class forum27871349.SimpleObj
class com.sun.org.apache.xerces.internal.dom.ElementNSImpl
class javax.xml.bind.JAXBElement
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.