Java – Marshalling polymorphic objects in JAX-WS

javajax-wsjaxbweb-services

I'm creating a JAX-WS type webservice, with operations that return an object WebServiceReply. The class WebServiceReply itself contains a field of type Object. The individual operations would populate that field with a few different data-types, depending on the operation.

Publishing the WSDL (I'm using Netbeans 6.7), and getting a ASP.NET application to retrieve and parse the WSDL was fine, but when I tried to call an operation, I would receive the following exception:

javax.xml.ws.WebServiceException: javax.xml.bind.MarshalException
 - with linked exception:
[javax.xml.bind.JAXBException: class [LDataObject.Patient; nor any of its super class is known to this context.]

How do I mark the annotations in the DataObject.Patient class, as well as the WebServiceReply class to get it to work? I haven't been able to fine a definitive resource on marshalling based upon annotations within the target classes either, so it would be great if anybody could point me to that too.

WebServiceReply.java

@XmlRootElement(name="WebServiceReply")
public class WebServiceReply {


    private Object returnedObject;
    private String returnedType;
    private String message;
    private String errorMessage;

    .......... // Getters and setters follow

}

DataObject.Patient.java

@XmlRootElement(name="Patient")

public class Patient {

    private int uid;
    private Date versionDateTime;
    private String name;
    private String identityNumber;

    private List<Address> addressList;
    private List<ContactNumber> contactNumberList;
    private List<Appointment> appointmentList;
    private List<Case> caseList;
}

Solution

(Thanks to Gregory Mostizky for his answer)

I edited the WebServiceReply class so that all the possible return objects extend from a new class ReturnValueBase, and added the annotations using @XmlSeeAlso to ReturnValueBase. JAXB worked properly after that!

Nonetheless, I'm still learning about JAXB marshalling in JAX-WS, so it would be great if anyone can still post any tutorial on this.

Gregory: you might want to add-on to your answer that the return objects need to sub-class from ReturnValueBase. Thanks a lot for your help! I had been going bonkers over this problem for so long!

Best Solution

You need to use @XmlSeeAlso so that your JAXB implementation will now to include additional classes as well.

In your case it would go something like this:

@XmlRootElement
@XmlSeeAlso({Patient.class, ....})
public class ReturnValueBase {
}

And also change returnedObject property to be of type ReturnValueBase.

Related Question