27/01/2013

JAXB inheritance and XmlElementRef


If you want JAXB to use the subclass element root name (e.g in this case NotEmpty, NotNull), you have to indicate so adding the @XmlElementRef annotation on the collection containing the list of objects hierarchy. 



@XmlRootElement(name = "Property")
@XmlAccessorType(XmlAccessType.FIELD)
public class Property  {

public enum Type {
UUID,
STRING,
INTEGER,
LONG,
DECIMAL,
FLOAT,
DOUBLE,
BOOLEAN,
DATETIME
}

@NotNull
@XmlElement(name = "Name")
private String name;

@NotNull
@XmlElement(name = "Type")
private Type type;

@XmlElementWrapper(name = "Constraints")
@XmlElementRef
private List<PropertyConstraint> constraints;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Type getType() {
return type;
}

public void setType(Type type) {
this.type = type;
}

public void setConstraints(List<PropertyConstraint> constraints) {
this.constraints = constraints;
}

public List<PropertyConstraint> getConstraints() {
return constraints;
}
}

@XmlRootElement(name = "NotEmpty")
@XmlAccessorType(XmlAccessType.FIELD)
public class NotEmptyContraint extends PropertyConstraint {
}


@XmlRootElement(name = "NotNull")
@XmlAccessorType(XmlAccessType.FIELD)
public class NotNullConstraint extends PropertyConstraint {
}

public abstract class PropertyConstraint {
}


public static void main(String[] args) throws JAXBException {
Property p = new Property();
p.setType(Type.BOOLEAN);
p.setName("Name");
List<PropertyConstraint> asList = Arrays.asList(new PropertyConstraint[] {new NotEmptyContraint(), new NotNullConstraint()});
p.setConstraints(asList);

JAXBContext jaxc = JAXBContext.newInstance(Property.class, NotNullConstraint.class, NotEmptyContraint.class);
Marshaller m = jaxc.createMarshaller();
m.marshal(p, System.out);
}

will print : 


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Property>
<Name>Name</Name>
<Type>BOOLEAN</Type>
<Constraints>
<NotEmpty></NotEmpty>
<NotNull></NotNull>
</Constraints>
</Property>