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

EclipseLink/DesignDocs/317962/Phase3

< EclipseLink‎ | DesignDocs‎ | 317962
Revision as of 12:09, 20 August 2010 by David.mccann.oracle.com (Talk | contribs) (XML Schema)

Phase 3 - MOXy Equivalents of Relevant JPA Annotations

This phase of development involves providing additional MOXy annotations and XML metadata support equivalent to that of any relevant JPA annotations.

Annotations/XML Metadata

The following MOXy annotations/XML metadata will be targeted in this phase:

JPA Annotation MOXy Annotation XML Metadata Tag Package Type Field Method
DiscriminatorColumn XmlDiscriminatorNode xml-discriminator-node X
DiscriminatorValue XmlDiscriminatorValue xml-discriminator-value X
JoinColumn XmlJoinNode xml-join-node X X
JoinColumns XmlJoinNodes xml-join-nodes X X
N/A XmlAfterUnmarshal xml-after-unmarshal
N/A XmlBeforeUnmarshal xml-before-unmarshal
N/A XmlAfterMarshal xml-after-marshal
N/A XmlBeforeMarshal xml-before-marshal

Inheritance Support

XmlDiscriminatorNode

Purpose

Provide a means to set the class indicator field name when using inheritance.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
@Target({TYPE}) 
@Retention(RUNTIME)
public @interface XmlDiscriminatorNode {
    String value();
}

XML Metadata

xml-discriminator-node

The xml-discriminator-node metadata tag will be used to set the class indicator field name when using inheritance. The value will be in the form of an XPath to an attribute, i.e. @xsi:type.

eclipselink-oxm.xml snippet

<java-type name="org.example.Vehicle" xml-discriminator-node="@vtype">

XmlDiscriminatorValue

Purpose

Provide a means to set a class indicator when using inheritance.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
@Target({TYPE}) 
@Retention(RUNTIME)
public @interface XmlDiscriminatorValue {
    String value();
}

XML Metadata

xml-discriminator-value

The xml-discriminator-value metadata tag will be used to set a class indicator when using inheritance.

eclipselink-oxm.xml snippet

<java-type name="org.example.Car" xml-discriminator-value="car">

XML Schema

Following is the proposed XSD change necessary to provide support for inheritance:

<xs:element name="java-type">
    <xs:complexType>
        <xs:all>
            <xs:element ref="xml-type" minOccurs="0"/>
            <xs:element ref="xml-root-element" minOccurs="0"/>
            <xs:element ref="xml-see-also" minOccurs="0"/>
            <xs:element ref="xml-java-type-adapter" minOccurs="0"/>
            <xs:element ref="xml-class-extractor" minOccurs="0"/>
            <xs:element ref="xml-properties" minOccurs="0" />
            <xs:element name="java-attributes" minOccurs="0">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="java-attribute" minOccurs="0" maxOccurs="unbounded" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:all>
        <xs:attribute name="name" type="xs:string" />
        <xs:attribute name="xml-accessor-order" type="xml-access-order" default="UNDEFINED" />
        <xs:attribute name="xml-accessor-type" type="xml-access-type" default="PUBLIC_MEMBER" />
        <xs:attribute name="xml-customizer" type="xs:string" />
        <xs:attribute name="xml-discriminator-node" type="xs:string" />
        <xs:attribute name="xml-discriminator-value" type="xs:string" />
        <xs:attribute name="xml-inline-binary-data" type="xs:boolean" default="false" />
        <xs:attribute name="xml-transient" type="xs:boolean" default="false" />
    </xs:complexType>
</xs:element>

Example

The following example will demonstrate how inheritance can be configured.

Using the xml-discriminator-node and xml-discriminator-value EclipseLink XML metadata tags to set the class indicator field name and class indicator(s) can be accomplished as follows:

<java-types>
    <java-type name="org.example.Vehicle" xml-discriminator-node="@vtype" xml-discriminator-value="vehicle">
        <xml-root-element name="vehicle-data" />
        <java-attributes>
            <xml-element java-attribute="topSpeed" name="top-speed" />
        </java-attributes>
    </java-type>
    <java-type name="org.example.Car" xml-discriminator-value="car">
        <xml-root-element name="car-data" /> 
        <java-attributes>
            <xml-element java-attribute="numberOfDoors" name="number-of-doors" />
            <xml-element java-attribute="milesPerGallon" name="miles-per-gallon" />
        </java-attributes>
    </java-type>
</java-types>

Setting the class indicator field name and class indicator(s) via Annotations would be accomplished as follows:

org.example.Vehicle.java

package org.example;
 
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement("vehicle-data")
@XmlDiscriminatorNode("@vtype")
@XmlDiscriminatorValue("vehicle")
class Vehicle {
    public String model;
    public String manufacturer;
    @XmlElement(name="top-speed")
    public int topSpeed;
}

org.example.Car.java

package org.example;
 
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement("car-data")
@XmlDiscriminatorValue("car")
class Car {
    @XmlElement(name="number-of-doors")
    public int numberOfDoors;
    @XmlElement(name="miles-per-gallon")
    public int milesPerGallon;
}

Sample XML Instance Document

<vehicle-data vtype="car">
    <model>Mustang GT</model>
    <manufacturer>Ford</manufacturer>
    <top-speed>354</top-speed>
    <number-of-doors>2</number-of-doors>
    <miles-per-gallon>26</miles-per-gallon>
</vehicle-data>

Relationship Mapping Support

We currently support relationship mappings through @ID/@IDREF annotations, and xml-id/xml-idref metadata tags. There are a number of limitations when using these:

  • ID property must be of type String
  • Target class of an IDREF must have an ID property
  • JAXB expects that a given class can have at most one ID property, so composite keys cannot be configured w/o violating the JAXB spec.

Use of XmlJoinNode(s) will allow one or more properties in the target class to be used as the key for a relationship mapping.

XmlKey

Purpose

One or more XmlKey annotations can be used to declare the primary keys in a given class. For a single key, either XmlID or XmlKey can be used. For composite primary keys, multiple XmlKey annotations can be used, or a single XmlID can be combined with one or more XmlKey annotations.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public @interface XmlKey {
    String value();
}

XML Metadata

xml-key

xml-key will be used to identify one or more primary keys on a given type. Any XmlKey annotations will be combined with those set via xml metadata. To unset a property annotated with XmlKey, the property must be present in XML without xml-key="true".

eclipselink-oxm.xml snippet (org.example.Address type)

<xml-element java-attribute="empId" xml-key="true" />
<xml-element java-attribute="type" xml-key="true" />

XML Schema

Following is the proposed XSD change necessary to provide additional relationship mapping support. The following attribute will be added to xml-attribute and xml-element:

  • <xs:attribute name="xml-key" type="xs:boolean" default="false" />

XmlJoinNodes

Purpose

XmlJoinNodes is used to group one or more XmlJoinNode entries. Please see XmlJoinNode below for examples of use.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public @interface XmlJoinNodes {
    XmlJoinNode[] value();
}

XML Metadata

xml-join-nodes

xml-join-nodes will be used to group one or more xml-join-node entries. Please see xml-join-node below for additional information and examples of use.

XmlJoinNode

Purpose

XmlJoinNode is used to identify a source to target primary key field association. For composite keys, XmlJoinNodes can be used. To unset a property annotated with XmlJoinNodes, the property must be present in XML without an xml-join-nodes element.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface XmlJoinNode {
    String xmlPath();
    String referencedXmlPath();
}

XML Metadata

xml-join-node is used to identify a source to target primary key field association. For composite keys, xml-join-nodes can be used. To unset a property annotated with XmlJoinNode, the property must be present in XML without any xml-join-node elements.

eclipselink-oxm.xml snippet (org.example.Employee type)

<xml-element java-attribute="address">
    <xml-join-nodes>
        <xml-join-node xml-path="address/@emp-id" referenced-xml-path="empId" />
        <xml-join-node xml-path="address/@type" referenced-xml-path="type" />
    </xml-join-nodes>
</xml-element>

XML Schema

Following is the proposed XSD change necessary to provide additional relationship mapping support:

<xs:element name="xml-join-nodes" type="xml-join-nodes" />
<xs:complexType name="xml-join-nodes">
    <xs:sequence>
        <xs:element name="xml-join-node" minOccurs="0" maxOccurs="unbounded" >
            <xs:complexType>
                <xs:attribute name="xml-path" type="xs:string" use="required" />
                <xs:attribute name="referenced-xml-path" type="xs:string" use="required" />
            </xs:complexType>
        </xs:element>
    </xs:sequence>
</xs:complexType>

Example

The following example will demonstrate how a relationship mapping with composite keys can be configured.

Using the xml-join-nodes and xml-join-node EclipseLink XML metadata tags to configure a relationship mapping can be accomplished as follows:

<java-types>
    <java-type name="org.example.Employee">
        <xml-root-element name="employee-data" />
        <java-attributes>
            <xml-attribute java-attribute="id" />
            <xml-element java-attribute="address">
                <xml-join-nodes>
                    <xml-join-node xml-path="address/@emp-id" referenced-xml-path="empId" />
                    <xml-join-node xml-path="address/@type" referenced-xml-path="type" />
                </xml-join-nodes>
            </xml-element>
        </java-attributes>
    </java-type>
    <java-type name="org.example.Address">
        <xml-root-element name="address-data" /> 
    </java-type>
</java-types>

Setting up a relationship mapping via Annotations would be accomplished as follows:

org.example.Employee.java

package org.example;
 
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement("employee-data")
class Employee {
    @XmlAttribute
    public String id;
 
    @XmlJoinNodes({
        @XmlJoinNode(xmlPath="address/@emp-id" referencedXmlPath="empId"),
        @XmlJoinNode(xmlPath="address/@type" referencedXmlPath="type")
    })
    public Address address;
}

org.example.Address.java

package org.example;
 
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement("address-data")
class Address {
    public String empId;
    public String type;
    public String street;
    public String city;
    public String postal;
}

Sample XML Instance Document

<root>
    <employee-data id="100">
        <address emp-id="100" type="HOME" />
    </employee-data>
    <address-data>
        <empId>100</empId>
        <type>HOME</type>
        <street>99 Some St.</street>
        <city>Kanata</city>
        <postal>K0A3m0</postal>
    </address-data>
    <address-data>
        <empId>100</empId>
        <type>WORK</type>
        <street>45 O'Connor St., Suite 400</street>
        <city>Ottawa</city>
        <postal>K1P1A4</postal>
    </address-data>
    <address-data>
        <empId>200</empId>
        <type>HOME</type>
        <street>1 Anystreet Rd.</street>
        <city>Ottawa</city>
        <postal>K4P1A2</postal>
    </address-data>
</root>

Testing

This section identifies the test package(s) for each feature outlined on this page.

XML Metadata

XML Metadata Package
xml-discriminator-node org.eclipse.persistence.testing.jaxb.externalizedmetadata.inheritance
xml-discriminator-value org.eclipse.persistence.testing.jaxb.externalizedmetadata.inheritance

Annotations

Annotation Package

Open Issues

This section lists open issues.

Issue# Description/Notes
1 Since (according to the JAXB spec.) there can only be one @XmlID per class, we need a way to handle multpile @XmlIDs for composite keys. How should we handle this? One suggestion is to introduce a new annotation called @XmlKey that can be used to define one or more keys in a class. This could also be used with a single @XmlID. Is there another way to support composite keys w/o violating the JAXB spec?

Decisions

This section lists decisions made. These are intended to document the resolution of open issues or constraints added to the project that are important.

Decision# Description/Notes Decision
1

Back to the top