JAXB: How can derived object be returned as XML element of base type?
I write web-services using jax-ws and wsdl contains set of types. Java classes to XML mapps using jaxb. Let's look at the following example:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Person")
public class Person {
@XmlElement(name = "firstName")开发者_如何转开发
protected String firstName;
@XmlElement(name = "lastName")
protected String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String value) {
this.firstName = value;
}
public String getLastName() {
return lastName;
}
public void setLastName(String value) {
this.lastName = value;
}
}
So we have 'Person' XML type that included into WSDL. This class we can name as interface class (for web-service clients). Server code can have a set of derived classes. For example,
public class EmployeePerson extends Person {
protected String post;
}
public class ClientPerson extends Person {
}
Web-service operation returns object of Person type:
@WebMethod(operationName = "GETPERSON")
public Person getPerson(@WebParam(name = "ID") String personId);
Actually we can return one of derived types, but 'Person' XML type should be returned to client (xsi:type='ns:Person'
).
If we use @XmlTransient
, object of undefined type will be returned. How can we cast derived class to base type?
I've got where my misunderstood was. It is not neccessary to define 'xsi:type' explicitly in web-service responce, because one is described by WSDL. When we return derived class, the type is neccessary because client should know how it can unmarshall instance. According to this the using of @XmlTransient
annotation on derived type is the correct way if we want always return exactly instance of parent class.
You want to return always a Person
? If so, you don't have to worry about that, when you do
return someEmployeePerson
it will be returned as a Person
.
EDIT: I create a test example:
Person
public class Person {
public Person() {...}
public Person(String name) {...}
public String getName() {...}
public void setName(String name) {...}
private String name;
}
ClientPerson
public class ClientPerson extends Person {
public ClientPerson() {...}
public ClientPerson(String name, Double payment) {...}
public Double getPayment() {...}
public void setPayment(Double payment) {...}
private Double payment;
}
Web Service
@WebService()
public class testePerson {
@WebMethod
public Person getPeople() {
return new ClientPerson("Some Name", 100.0);
}
}
example.TestePersonService service = new example.TestePersonService();
example.TestePerson port = service.getTestePersonPort();
Person p = port.getPeople();
When you execute this, the result is a Person
, object. In fact the WSDL only announces the Person Class.
精彩评论