Developing JAXB Applications Using EclipseLink MOXy, Release 2.4
  Go To Table Of Contents
 Search
 PDF

Specifying Inheritance

EclipseLink MOXy provides several ways to represent your inheritance hierarchy in XML:

Using xsi:type

By default, EclipseLink will use the xsi:type attribute to represent inheritance in XML.

In this example an abstract super class (ContactInfo) contains all types of contact information. Address and PhoneNumber are the concrete implementations of ContactInfo.

Example 3-12 Sample Java Classes

public abstract class ContactInfo {
}
 
public class Address extends ContactInfo {
 
   private String street;
   ... 
 
}
 
public class PhoneNumber extends ContactInfo {
 
   private String number;
   ...
 
}
 

Because the Customer object can have different types of contact information, its property refers to the superclass.

@XmlRootElement
public class Customer {
 
   private ContactInfo contactInfo;
   ... 
 
}

Marshalling an example Customer would produce the following XML:

<customer>
   <contactInfo 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:type="address">
      <street>323 Main Street</street>
   </contactInfo>
</customer>
 

Note the xsi:type attribute on the contactInfo element.

Using Substitution Groups

Another way to model inheritance in XML is through XML Schema's substitution groups functionality. Using this approach, the element name itself determines which subclass to use.

Taking the same Example 3-12, we will add @XmlRootElement annotations to each of the subclasses, which will act as the inheritance indicator.

Example 3-13 Using @XmlRootElement Annotation

public abstract class ContactInfo {
}
 
@XmlRootElement
public class Address extends ContactInfo {
 
   private String street;
   ... 
 
}
 
@XmlRootElement
public class PhoneNumber extends ContactInfo {
 
   private String number;
   ...
 
}
 

We will also annotate the contactInfo property of the Customer object with @XmlElementRef to indicate the value type will be derived from the element name (and namespace URI).

public class Customer {
    private ContactInfo contactInfo;
 
    @XmlElementRef
    public ContactInfo getContactInfo() {
        return contactInfo;
    }

   ...
}
 

Using this approach, marshalling an example Customer would produce the following XML:

<customer>
   <address>
      <street>323 Main Street</street>
   </address>
</customer>
 

Note that the Address object is marshalled to the address element.

Using @XmlDiscriminatorNode/@XmlDiscriminatorValue

You can also use the MOXY-specific @XmlDiscriminatorNode and @XmlDiscriminatorValue annotations (introduced in EclipseLink 2.2) to represent inheritance. With this approach, you can select the attribute to represent the subtype.

Using Example 3-13, the ContactInfo class uses the @XmlDiscriminatorNode annotation to specify the XML attribute (classifier) that will hold the subclass indicator. Address and PhoneNumber are annotated with @XmlDiscriminatorValue, indicating that class' indicator name (address-classifier and phone-number-classifier).

Example 3-14 Using the @XmlDiscriminatorNode and @XmlDiscriminatorValue Annotations

@XmlDiscriminatorNode("@classifier")
public abstract class ContactInfo {
}
 
@XmlDiscriminatorValue("address-classifier")
public class Address extends ContactInfo {
 
   private String street;
   ... 
 
}
 
@XmlDiscriminatorValue("phone-number-classifier")
public class PhoneNumber extends ContactInfo {
 
   private String number;
   ...
 
}
 

Example 3-14 produces the following XML:

<customer>
   <contactInfo classifier="address-classifier">
      <street>323 Main Street</street>
   </contactInfo>
</customer>

Notice that Address is marshalled to the contactInfo element. Its classifier attribute contains the discriminator node value address-classifier.