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
SimpleObj
in the field annotated with@XmlAnyElement(lax=true)
.UPDATE #1
I'm not sure why I never leverage
@XmlSeeAlso
in my examples.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 theJAXBContext
.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.UPDATE #2
When you have a property mapped with
@XmlAnyElement(lax=true)
the following will happen:@XmlRootElement
of a class, then you will get an instance of that class.@XmlElementDecl
of a class on theObjectFactory
or another class annotated with@XmlRegistry
then you will get an instance of that class wrapped in an instance ofJAXBElement
.Element
.I will demonstrate below with an example.
ObjectFactory
Demo
Output