Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseLink/UserGuide/MOXy/Type Level/Handling Inheritance"

Line 12: Line 12:
 
== Using xsi:type ==
 
== Using xsi:type ==
  
You can use the '''xsi:type''' attribute to represent inheritance in JAXB.  
+
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'''.
+
In this example an abstract super class ('''ContactInfo''') contains all types of contact information. '''Address''' and '''PhoneNumber''' are the concrete implementations of '''ContactInfo'''.
  
 
<source lang="java">
 
<source lang="java">
Line 39: Line 39:
  
 
<source lang="java">
 
<source lang="java">
package blog.inheritance;
 
 
import javax.xml.bind.annotation.XmlRootElement;
 
 
 
@XmlRootElement
 
@XmlRootElement
 
public class Customer {
 
public class Customer {
 
   
 
   
    private ContactInfo contactInfo;
+
  private ContactInfo contactInfo;
+
  ...  
    public ContactInfo getContactInfo() {
+
        return contactInfo;
+
    }
+
+
    public void setContactInfo(ContactInfo contactInfo) {
+
        this.contactInfo = contactInfo;
+
    }
+
 
   
 
   
 
}
 
}
Line 60: Line 49:
  
  
 +
Marshalling an example '''Customer''' would produce the following XML:
  
In this example, the '''xsi:type''' attribute represents inheritance.
 
 
<source lang="java">
 
package blog.inheritance;
 
 
import javax.xml.bind.JAXBContext;
 
import javax.xml.bind.Marshaller;
 
 
public class Demo {
 
 
    public static void main(String[] args) throws Exception {
 
        Customer customer = new Customer();
 
        Address address = new Address();
 
        address.setStreet("1 A Street");
 
        customer.setContactInfo(address);
 
 
        JAXBContext jc = JAXBContext.newInstance(Customer.class, Address.class, PhoneNumber.class);
 
 
        Marshaller marshaller = jc.createMarshaller();
 
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
        marshaller.marshal(customer, System.out);
 
    }
 
 
}
 
</source>
 
 
The above sample code produces the following XML.
 
 
<source lang="xml">
 
<source lang="xml">
 
 
<customer>
 
<customer>
    <contactInfo  
+
  <contactInfo  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
+
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:type="address">
+
      xsi:type="address">
        <street>1 A Street</street>
+
      <street>323 Main Street</street>
    </contactInfo>
+
  </contactInfo>
 
</customer>
 
</customer>
 
</source>
 
</source>
 +
 
Note the '''xsi:type''' attribute on the '''contactInfo''' element.
 
Note the '''xsi:type''' attribute on the '''contactInfo''' element.
  
  
<span id="substitution"></span>
 
 
==Using Substitution Groups==
 
==Using Substitution Groups==
 
You can represent inheritance by using the element name with XML schema ''substitution groups''.
 
You can represent inheritance by using the element name with XML schema ''substitution groups''.

Revision as of 15:59, 19 April 2011

EclipseLink MOXy

Eclipselink-logo.gif
EclipseLink
Website
Download
Community
Mailing ListForumsIRCmattermost
Issues
OpenHelp WantedBug Day
Contribute
Browse Source

Handling 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.

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

You can represent inheritance by using the element name with XML schema substitution groups.

In this example, the Java model contains an abstract superclass, ContactInfo for all types of contact information. Address and PhoneNumber are the concrete implementations of ContactInfo.

 
package blog.inheritance;
 
import javax.xml.bind.annotation.XmlRootElement;
 
public abstract class ContactInfo {
 
}
 
@XmlRootElement
public class Address extends ContactInfo {
 
    private String street;
 
    public String getStreet() {
        return street;
    }
 
    public void setStreet(String street) {
        this.street = street;
    }
 
}
 
@XmlRootElement
public class PhoneNumber extends ContactInfo {
 
}

Both Address and PhoneNumber use the @XmlRootElement annotation because the element name is used as the inheritance indicator.


Because the Customer object can have different types of contact information, its property refers to the superclass. The contactInfo property includes the @XmlElementRef annotation to indicate the value type will be derived from the element name (and namespace URI).

 
package blog.inheritance;
 
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement
public class Customer {
 
    private ContactInfo contactInfo;
 
    @XmlElementRef
    public ContactInfo getContactInfo() {
        return contactInfo;
    }
 
    public void setContactInfo(ContactInfo contactInfo) {
        this.contactInfo = contactInfo;
    }
 
}

In the following example, the xsi:type attribute represents inheritance.

 
package blog.inheritance;
 
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
 
public class Demo {
 
    public static void main(String[] args) throws Exception {
        Customer customer = new Customer();
        Address address = new Address();
        address.setStreet("1 A Street");
        customer.setContactInfo(address);
 
        JAXBContext jc = JAXBContext.newInstance(Customer.class, Address.class, PhoneNumber.class);
 
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);
    }
 
}

The above sample code produces the following XML.

<customer>
    <address>
        <street>1 A Street</street>
    </address>
</customer>

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







Using MOXy Exentions: @XmlDescriminatorNode/@XmlDescrimintatorValue

You can use the @XmlDescriminatorNode and @XmlDescrimintatorValue MOXy extensions avaialable in EclipseLink 2.2 JAXB to represent inheritance. With these extensions, you can select the attribute to represent the subtype.

In this example an abstract super class ('ContactInfo) contains all types of contact information. The ContactInfo uses the @XmlDescriminatorNode annotation to specify the XML attribute (classifier) to indicate the subtype.

Address and PhoneNumber are the concrete implementations of ContactInfo. The @XmlDescriminatorValue is used to override the default type name.

package blog.inheritance;
 
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
 
@XmlDiscriminatorNode("@classifier")
public abstract class ContactInfo {
 
}
 
@XmlDiscriminatorValue("address-classifier")
public class Address extends ContactInfo {
 
    private String street;
 
    public String getStreet() {
        return street;
    }
 
    public void setStreet(String street) {
        this.street = street;
    }
 
}
 
@XmlDiscriminatorValue("phone-number-classifier")
public class PhoneNumber extends ContactInfo {
 
}


The Customer object can have different types of contact info set on it, so the property will refer to the super class.

jaxb.properties

To use the MOXy JAXB implementation, use a jaxb.properties file with the Address class that contains the following: javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

In the following example, the descriminator represents inheritance.

 
package blog.inheritance;
 
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
 
public class Demo {
 
    public static void main(String[] args) throws Exception {
        Customer customer = new Customer();
        Address address = new Address();
        address.setStreet("1 A Street");
        customer.setContactInfo(address);
 
        JAXBContext jc = JAXBContext.newInstance(Customer.class, Address.class, PhoneNumber.class);
 
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);
    }
 
}

The above sample produces the following XML.

<customer>
   <contactInfo classifier="address-classifier">
      <street>1 A Street</street>
   </contactInfo>
</customer>

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


Eclipselink-logo.gif
Version: 2.2.0 DRAFT
Other versions...

Back to the top