JAXB Can't Handle Interfaces in Generics
If you have a class with a List<Vehicle> and Vehicle is an interface, JAXB will throw an Exception at runtime:my.package.MyInterface is an interface,
and JAXB can't handle interfaces
public abstract class Vehicle {
public abstract String getType();
}
@XmlRootElement
public class Bus extends Vehicle {
private String type;
public Bus() { };
public Bus(String type) {
this.type = type;
}
@XmlElement
@Override
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
@XmlRootElement
public class Car extends Vehicle {
private String type;
public Car() {};
public Car(String type) {
this.type = type;
}
@XmlElement
@Override
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
@XmlRootElement
public class ObjectWithListOfVehicles {
private List<Vehicle> list;
@XmlElementWrapper(name="MyVehicleList")
@XmlElement
public List<Vehicle> getList() {
return list;
}
public void setList(List<Vehicle> list) {
this.list = list;
}
}
public static void interfaceExamples() throws JAXBException {
List<Vehicle> l = new ArrayList<Vehicle>();
l.add(new Bus("Large bus"));
l.add(new Bus("Small bus"));
l.add(new Car("Ferrari"));
// Object with generic list
ObjectWithListOfVehicles owgl
= new ObjectWithListOfVehicles();
owgl.setList(l);
JAXBContext jc = JAXBContext.newInstance(
Bus.class, Car.class,
ObjectWithListOfVehicles.class);
ObjectWithListOfVehicles retr
= marshallUnmarshall(owgl, jc);
for (Vehicle s : retr.getList()) {
System.out.println(
s.getClass().getSimpleName()
+ " - " + s.getType());
} System.out.println(" ");
}
public static <O> O marshallUnmarshall(O o, JAXBContext jc)
throws JAXBException {
// Creating a Marshaller
Marshaller jaxbMarshaller = jc.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter result = new StringWriter();
jaxbMarshaller.marshal(o, result);
// Printing XML
String xml = result.toString();
System.out.println(xml);
// Creating an Unmarshaller
Unmarshaller jaxbUnmarshaller = jc.createUnmarshaller();
StringReader sr = new StringReader(xml);
O retr = (O) jaxbUnmarshaller.unmarshal(sr);
return retr;
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<objectWithListOfVehicles>
<MyVehicleList>
<list xsi:type="bus" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<type>Large bus</type>
</list>
<list xsi:type="bus" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<type>Small bus</type>
</list>
<list xsi:type="car" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<type>Ferrari</type>
</list>
</MyVehicleList>
</objectWithListOfVehicles>
Bus - Large bus
Bus - Small bus
Car - Ferrari
Notice that JAXB is capable of recreating both Bus and Car instances.
Next
JAXB to XML • JAXB to JSON • JAXB Annotations Tutorial Table Of Content
Hi,
ReplyDeleteNice article. Here is an alternate approach that you can use with JAXB implementation when you are working with interfaces:
- JAXB and Interface Fronted Models
-Blaise
Hi,
ReplyDeleteReally very very nice article about JAXB...