To learn how to use @XmlAnyElement, I created the following test service:
@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. Below is the code for the ServiceResult class:
@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:
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. However, what I observed is that JAXB only parsed my object into JAXBElement instead of going all the way into SimpleObj.
I'd be extremely grateful if you could show me how I can get SimpleObj out of the ServiceResult.
UPDATE:
Below is the SimpleObj class:
@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.
The output from running the demo code shows that it is instances of
SimpleObjin the field annotated with@XmlAnyElement(lax=true).UPDATE #1
I'm not sure why I never leverage
@XmlSeeAlsoin my examples.When you are creating the
JAXBContextyourself, you simply need to include anything you would have referenced in an@XmlSeeAlsoannotation as part of the classes you used to bootstrap theJAXBContext.In a JAX-WS (or JAX-RS) setting where you don't have direct access to the
JAXBContextI would recommend using the@XmlSeeAlsoannotation like you have done.UPDATE #2
When you have a property mapped with
@XmlAnyElement(lax=true)the following will happen:@XmlRootElementof a class, then you will get an instance of that class.@XmlElementDeclof a class on theObjectFactoryor another class annotated with@XmlRegistrythen you will get an instance of that class wrapped in an instance ofJAXBElement.Element.I will demonstrate below with an example.
ObjectFactory
Demo
Output