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

From Eclipsepedia

Jump to: navigation, search
m (Handling Inheritance)
m (Replacing page with 'Please see http://www.eclipse.org/eclipselink/documentation/2.4/moxy/type_level003.htm')
 
(15 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{EclipseLink_UserGuide
+
Please see http://www.eclipse.org/eclipselink/documentation/2.4/moxy/type_level003.htm
|info=y
+
|eclipselink=y
+
|eclipselinktype=MOXy
+
}}
+
= Handling Inheritance =
+
With EclipseLink JAXB MOXy, you can demonstrate inheritance in multiple ways:
+
* [[#xsitype|xsi:Type Attribute]]
+
* [[#substitution|Substitution Groups]]
+
* [[#moxyextensions|MOXy Extension @XmlDescriminatorNode/@XmlDescrimintatorValue]]
+
 
+
 
+
<span id="xsitype"></span>
+
== Using xsi:type Attribute ==
+
 
+
You can use the '''xsi:type''' attribute to represent inheritance in JAXB.
+
 
+
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">
+
package blog.inheritance;
+
+
public abstract class ContactInfo {
+
+
}
+
 
+
public class Address extends ContactInfo {
+
+
    private String street;
+
+
    public String getStreet() {
+
        return street;
+
    }
+
+
    public void setStreet(String street) {
+
        this.street = street;
+
    }
+
+
}
+
 
+
public class PhoneNumber extends ContactInfo {
+
+
}
+
 
+
</source>
+
 
+
 
+
Because the '''Customer''' object can have different types of contact information, its property refers to the superclass.
+
 
+
<source lang="java">
+
package blog.inheritance;
+
+
import javax.xml.bind.annotation.XmlRootElement;
+
+
@XmlRootElement
+
public class Customer {
+
+
    private ContactInfo contactInfo;
+
+
    public ContactInfo getContactInfo() {
+
        return contactInfo;
+
    }
+
+
    public void setContactInfo(ContactInfo contactInfo) {
+
        this.contactInfo = contactInfo;
+
    }
+
+
}
+
</source>
+
 
+
 
+
 
+
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">
+
+
<customer>
+
    <contactInfo
+
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
    xsi:type="address">
+
        <street>1 A Street</street>
+
    </contactInfo>
+
</customer>
+
</source>
+
Note the '''xsi:type''' attribute on the '''contactInfo''' element.
+
 
+
 
+
<span id="substitution"></span>
+
==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'''. 
+
 
+
<source lang="java">
+
+
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 {
+
+
}
+
 
+
</source>
+
+
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).
+
 
+
<source lang="java">
+
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;
+
    }
+
+
}
+
 
+
</source>
+
 
+
In the following 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">
+
 
+
<customer>
+
    <address>
+
        <street>1 A Street</street>
+
    </address>
+
</customer>
+
 
+
</source>
+
 
+
Note that the '''Address''' object is marshalled to the '''address''' element.
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
<span id="moxyextensions"></span>
+
==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.
+
 
+
<source lang="java">
+
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 {
+
+
}
+
 
+
</source>
+
+
 
+
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:
+
<code>
+
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
+
</code>
+
 
+
In the following example, the descriminator 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 produces the following XML.
+
 
+
<source lang="xml">
+
 
+
<customer>
+
  <contactInfo classifier="address-classifier">
+
      <street>1 A Street</street>
+
  </contactInfo>
+
</customer>
+
 
+
</source>
+
 
+
Notice that '''Address''''is marshalled to the '''contactInfo''' element. Its '''classifier''' attribute contains the discriminator node value '''address-classifier'''.
+

Latest revision as of 09:50, 8 November 2012

Please see http://www.eclipse.org/eclipselink/documentation/2.4/moxy/type_level003.htm