|
|
(5 intermediate revisions by 2 users not shown) |
Line 1: |
Line 1: |
− | {{EclipseLink_UserGuide
| + | '''[[Image:Elug_draft_icon.png|Warning]] This page is obsolete. Please see ''[http://www.eclipse.org/eclipselink/documentation/2.4/ Developing JAXB Applications Using EclipseLink MOXy]'' for current information.''' |
− | |info=y
| + | |
− | |api=y
| + | |
− | |apis=* [http://www.eclipse.org/eclipselink/api/latest/org/eclipse/persistence/mappings/XmlElementRef.html XmlElementRef]
| + | |
− | * [http://www.eclipse.org/eclipselink/api/latest/org/eclipse/persistence/mappings/XXmlRootElement.html XXmlRootElement]
| + | |
− | }}
| + | |
− | | + | |
− | ==Substitution Groups ==
| + | |
− | With JAXB, you can use the element ''name'', instead of using the '''xsi:type''' attribute, to represent inheritance by using XML schema '''substitution groups'''.
| + | |
− | | + | |
− | | + | |
− | In this example, the Java model contains an abstract superclass for all types of contact information:
| + | |
− | | + | |
− | <source lang="Java">
| + | |
− | package blog.inheritance;
| + | |
− |
| + | |
− | public abstract class ContactInfo {
| + | |
− |
| + | |
− | }
| + | |
− | | + | |
− | </source>
| + | |
− | | + | |
− | | + | |
− | The '''Address''' and '''PhoneNumber''' classes are the concrete implementations of '''ContactInfo'''. Both classes use the '''@XmlRootElement''' annotation because the element name is used as the inheritance indicator.
| + | |
− | | + | |
− | <source lang="Java">
| + | |
− | package blog.inheritance;
| + | |
− |
| + | |
− | import javax.xml.bind.annotation.XmlRootElement;
| + | |
− |
| + | |
− | @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>
| + | |
− | | + | |
− | | + | |
− | Because the '''Customer'' object can have different types of contact information, the property refers to the superclass. The '''contactInfo''' property contains the '''@XmlElementRef''' annotation to specify that 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>
| + | |
− | | + | |
− | | + | |
− | This schema represents the JAXB view of the object model. The schema type inheritance matches the Java class inheritance.
| + | |
− | <source lang="xml">
| + | |
− | <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
| + | |
− |
| + | |
− | <xs:element name="customer" type="customer"/>
| + | |
− |
| + | |
− | <xs:element name="contactInfo" type="contactInfo"/>
| + | |
− |
| + | |
− | <xs:element name="address" type="address"
| + | |
− | substitutionGroup="contactInfo"/>
| + | |
− |
| + | |
− | <xs:element name="phoneNumber" type="phoneNumber"
| + | |
− | substitutionGroup="contactInfo"/>
| + | |
− |
| + | |
− | <xs:complexType name="customer">
| + | |
− | <xs:sequence>
| + | |
− | <xs:element ref="contactInfo"/>
| + | |
− | </xs:sequence>
| + | |
− | </xs:complexType>
| + | |
− |
| + | |
− | <xs:complexType name="contactInfo" abstract="true">
| + | |
− | <xs:sequence/>
| + | |
− | </xs:complexType>
| + | |
− |
| + | |
− | <xs:complexType name="address">
| + | |
− | <xs:complexContent>
| + | |
− | <xs:extension base="contactInfo">
| + | |
− | <xs:sequence>
| + | |
− | <xs:element name="street" type="xs:string" minOccurs="0"/>
| + | |
− | </xs:sequence>
| + | |
− | </xs:extension>
| + | |
− | </xs:complexContent>
| + | |
− | </xs:complexType>
| + | |
− |
| + | |
− | <xs:complexType name="phoneNumber">
| + | |
− | <xs:complexContent>
| + | |
− | <xs:extension base="contactInfo">
| + | |
− | <xs:sequence/>
| + | |
− | </xs:extension>
| + | |
− | </xs:complexContent>
| + | |
− | </xs:complexType>
| + | |
− |
| + | |
− | </xs:schema>
| + | |
− | | + | |
− | </source>
| + | |
− | | + | |
− | Notice that each '''type''' has a corresponding global element. Additionally, the '''address''' and '''phoneNumber''' elements may be substituted for the '''contactInfo''' element.
| + | |
− | | + | |
− | ==Example ==
| + | |
− | | + | |
− | This example code demonstrates using the '''xsi:type''' attribute to represent 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);
| + | |
− | }
| + | |
− |
| + | |
− | }
| + | |
− | | + | |
− | The example produces the following XML:
| + | |
− | | + | |
− | <source lang="xml">
| + | |
− |
| + | |
− | <customer>
| + | |
− | <address>
| + | |
− | <street>1 A Street</street>
| + | |
− | </address>
| + | |
− | </customer>
| + | |
− | | + | |
− | </source>
| + | |
− | | + | |
− | | + | |
− | Notice that the '''Address''' object is marshalled to the '''address''' element.
| + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | How does this All Work?
| + | |
− | | + | |
− | | + | |
− | Summary
| + | |
− | | + | |
− | Not all XML binding tools support inheritance. The ones that do often use different strategies. Some include the class name of the subclass as the qualifier, this strategy makes it difficult to send the resulting XML document to another tool. JAXB on the other hand leverages existing XML schema concepts to produce very portable XML documents. In a future post I'll discuss a MOXy extension for an alternate means of representing inheritance (check out the following for a sneak peak).
| + | |
− | | + | |
− | | + | |
− | | + | |
− | {{EclipseLink_MOXy
| + | |
− | |previous=[[EclipseLink/UserGuide/MOXy/Advanced_XML_Schema_Concepts/Handling_Null_Values|Handling Null Values]]
| + | |
− | |next =[[EclipseLink/UserGuide/MOXy/Advanced_XML_Schema_Concepts/Wildcard_Content|Wildcard Content]]
| + | |
− | |up =[[EclipseLink/UserGuide/MOXy/Advanced XML Schema Concepts|Advanced XML Schema Concepts]]
| + | |
− | |version=2.2.0 DRAFT
| + | |
− | }}
| + | |