blob: c060efb9459fcb25e3e72788199f8c8d98962814 [file] [log] [blame]
//
// Copyright (c) 2020, 2021 Contributors to the Eclipse Foundation
//
[appendix]
== Runtime Processing
=== Introduction
Two of the important goals of Jakarta XML Binding specification are
portability and handling of invalid XML content
(for e.g. schema evolution). These goals imply that a Jakarta XML Binding Provider must
be capable of marshalling and unmarshalling XML instances using Jakarta XML Binding
annotated classes derived using another Jakarta XML Binding Provider. To ensure
portable behavior of Jakarta XML Binding mapped classes across JAXB Providers requires
a specification of runtime processing model of the Jakarta XML Binding binding
framework.
This appendix specifies the runtime
processing model of XML instances and requirements on Jakarta XML Binding
Provider's runtime. It differs from the documentation found elsewhere in
the specification/javadocs. Chapter 4,"Binding Framework" and the
javadocs for the package jakarta.xml.bind do describe the Jakarta XML Binding binding
framework. But these are written from a Jakarta XML Binding developer perspective
rather than from a Jakarta XML Binding Provider perspective and thus do not
describe requirements on Jakarta XML Binding Provider runtime. This was sufficient
for JAXB 1.0 since portability was not a goal for JAXB 1.0 and schema
derived implementation classes were coupled to the JAXB 1.0 Provider
runtime. However, this is insufficient for Jakarta XML Binding, where portability
and handling invalid XML content are goals.
=== Scope and Conventions
==== Scope
This appendix describes marshalling and unmarshalling.
==== Format
The specification uses the following for
specifying runtime behavior:
* XML Infoset, Second Edition,
http://www.w3.org/TR/xml-infoset augmented with attributes xsi:type and
xsi:nil that can be used by a document author.
* XML Schema abstract schema component model.
* JAXB defined annotations as needed
==== Notations
The following notations/conventions are used:
* For brevity, property is used but is used
to mean JavaBean property or a field.
* XML Infoset properties that are associated
with an information item are enclosed in [...], for e.g. AII.[local
name]. And program elements the constitute the Java representation to
which an information item are identified as for e.g. AII.valuetype.
* *AII: Attribute Information Item in XML Infoset*
* AII.[local name] : local name property in infoset for AII
* AII.[namespace] : namespace property in infoset for AII
* AII.[owner element] : owner element in infoset for AII
* AII.[normalized value]: normalized value in inforset for AII
* AII.property : JAXB property to which AII
is mapped. The property in in the java type to which AII.[owner element]
is mapped.
* AII.valuetype: Java type representing the XML serialized for AII.
* AII.boundtype: Java type that is bound;
this differs from AII.valuetype only if JAXB property is associated with
a @XmlJavaTypeAdapter.
* AII.schematype : schema type to which AII
is bound statically using Java -> XML schema mapping rules.
* *EII: Element Information Item in infoset*
* EII.[local name] : local name property in XML infoset for EII
* EII.[namespace] : namespace property in XML infoset for EII
* EII.[children]: children property in XML infoset for EII
* EII.[parent]: parent property in XML infoset for EII
* EII.property : JAXB property to which EII
is mapped. The property is in the javatype to which EII.[parent] is
mapped.
* EII.valuetype : java type representing the XML serialized for EII
* EII.boundtype : java type that is bound;
this differs from EII.valuetype only if JAXB property is associated with
a @XmlJavaTypeAdapter.
* EII.schematype : schema type to which EII
is bound statically using java -> XML schema mapping rules.
* EII.xsitype : the xsi:type specified in the
XML instance by a document author. null if no xsi:type was specified.
* EII.xsinil : the xsi:nil specified in the
XML instance by a document author. null if no xsi:nil was specified.
=== Unmarshalling
This section specifies the runtime behavior
and JAXB provider requirements related to unmarshalling. The
specification includes unmarshalling of invalid XML content in an XML
instance.
This section specifies only flexible, standard unmarshalling (flexible
because unmarshalling deals with invalid XML content). Other
unmarshalling modes will not be specified. Flexible unmarshalling
specified here must be supported by all JAXB Providers.
The unmarshalling methods in the binding
framework fall into the following categories:
. Unmarshal methods that do not take a declaredType as parameter:
+
[source,java,indent="4"]
----
jakarta.xml.bind.Unmarshaller.unmarshal(...)
jakarta.xml.bind.Binder.unmarshal(...)
----
. Unmarshal methods that take a declaredType as a parameter:
+
[source,java,indent="4"]
----
jakarta.xml.bind.Unmarshaller.unmarshal(..., java.lang.Class<T> declaredType)
jakarta.xml.bind.Binder.unmashal(..., java.lang.Class<T> declaredType)
----
The unmarshal methods that do not take
declaredType as parameter must be unmarshalled as specified in
<<globally-declared-root-element>>.
The unmarshal methods that take a
`declaredType` as a parameter must be unmarshalled as specified in
<<declared-type>>.
==== Globally Declared Root Element
There are two ways that a root element can be
represented in Java representation:
* as an element instance factory method that
is generated in the public ObjectFactory class of a package when a
schema is compiled. An element instance factory method is annotated with
a @XmlElementDecl annotation. For e.g.
+
[source,java,indent="4"]
----
public class ObjectFactory {
@XmlElementDecl(...)
public JAXBElement<T> createFoo(T elementValue);
...
}
----
* as a type (either an enum type or a class)
that has been annotated with @XmlRootElement. For e.g.
+
[source,java,indent="4"]
----
@XmlRootElement(...)
public class Foo {...}
----
The unmarshalling of XML content results in a
content tree with a root that is an instance of either a `JAXBElement`
instance or a type that is annotated with `@XmlRootElement`. The
content tree must be created as follows:
. lookup an element factory method in the ObjectFactory class matching on:
+
EII.[namespace] == @XmlElementDecl.namespace() && EII.[local name] == @XmlElementDecl.name()
or for a type annotated with @XmlRootElement matching on:
EII.[namespace] == @XmlRootElement.namespace() && EII.[local name] == @XmlRootElement.name()
+
[NOTE]
.Note
====
The lookup will only find one of the
above not both. If both a type as well as an element factory method were
found, it would be flagged as an error when JAXBContext is created.
====
. if an element factory method in the
ObjectFactory class or a type annotated with @XmlRootElement is found,
then determine the _valueType_.
.. if an element factory method is found,
there is no @XmlJavaTypeAdapter associated with the value parameter to
the element factory method, then the valueType is the java type of the
value parameter to the element factory method. For e.g.
+
[source,java,indent="4"]
----
@XmlElementDecl(name = "bar", namespace = "")
public JAXBElement<Foo> createBar(Foo value) {
return new JAXBElement<Foo>(
_Bar_QNAME, ((Class) Foo.class), null, value);
}
----
the _valueType_ type is Foo.
+
[NOTE]
.Note
====
For ease of understanding the code generated by the Sun JAXB RI implementation
has been shown above. But the implementation could be JAXB Provider dependent.
====
+
if the parameter is associated with @XmlJavaTypeAdapter, then the _valueType_
is the java type specified in @XmlJavaTypeAdapter.value().
.. if a type annotated with @XmlRootElement is
found then _valueType_ is the type. For e.g.
+
[source,java,indent="4"]
----
@XmlRootElement(...)
public class Foo {...}
----
+
[NOTE]
.Note
====
@XmlRootElement and @XmlJavaTypeAdapter are mutually exclusive.
====
+
Go to step 4, "Check for type substitution"
. If neither the element factory method nor a
type annotated with @XmlRootElement is found, then the element is
unknown. Set _valueType_ of the element to null.
+
Even though the element is unknown, a
document author can still perform type substitution. This case can arise
if the XML schema contains only schema types and no global elements. For
e.g a document author could have specified a xsi:type that has been
mapped by JAXB. For e.g.
+
[source,xml,indent="4"]
----
<unknownElement xsi:type="PurchaseOrder"/>
----
So goto step 4, "Check for type substitution"
. "Check for type substitution"
.. if `xsi:type` is not specified, and the
_valueType_ is null (i.e. the root element is unknown and we got to this
step from step 3), throw a `jakarta.xml.bind.UnmarshalException` and
terminate processing.
.. otherwise, if `xsi:type` is specified, but
is not mapped to a JAXB mapped type (e.g. class is not marked with
@XmlType declaration), then throw a `jakarta.xml.bind.UnmarshalException`
and terminate processing.
.. otherwise, if `xsi:type` is specified, and is
mapped to a JAXB mapped type set the _valueType_ to the javatype to which
xsi:type is mapped.
.. otherwise, `xsi:type` is not specified; _valueType_ is unchanged.
. Unmarshal _valueType_ as specified in <<value-type>>.
. If the element factory method is annotated
with @XmlJavaTypeAdapter, then convert the _valueType_ into a _boundType_
+
[source,java]
----
boundType = @XmlJavaTypeAdapter.value().unmarshal(valueType)
----
. Determine the content root type to be returned by unmarshal() method.
.. if the element lookup returned an element
instance factory method, then create a JAXBElement instance using the
_boundType_. The content root type is the JAXBElement instance.
.. otherwise, if the element lookup returned a
type annotated with @XmlRootElement, then the content root type is the
_boundType_.
.. otherwise, the element is an unknown
element. Wrap the _boundType_ using JAXBElement with an element name in
the XML instance document (e.g. "unknown Element"). The content root
type is the JAXBElement instance.
. return the content root type.
==== Declared Type
The unmarshalling process described in this
section must be followed for the unmarshal methods that take a
`declaredType` as a parameter.
. Determine the _valueType_ to be unmarshalled
as follows:
.. if `xsi:type` is specified, but is not
mapped to a JAXB mapped type, then throw a
`jakarta.xml.bind.UnmarshalException` and terminate processing.
.. otherwise if `xsi:type` is specified and is
mapped to JAXB mapped type, then _valueType_ is the JAXB mapped type.
.. otherwise _valueType_ is the argument passed
to `declaredType` parameter in the
`unmarshal(..., java.lang.Class<T>declaredType)` call.
. Unmarshal _valueType_ as specified in <<value-type>>.
==== Value Type
The following steps unmarshal either
EII.valuetype or AII.valuetype, depending upon whether an EII or AII is
being unmarshalled.
[NOTE]
.Note
====
Whether an EII or AII is being
unmarshalled is determined by the "caller" of this section.
AII.valuetype and EII.valuetype are assumed to be set by the time this
section entered.
====
. If an instance of _valueType_ does not exist,
create an instance of _valueType_ as follows (for e.g. if a value of a
property with type `java.util.List` is non null, then unmarshal the
value into that `java.util.List` instance rather than creating a new
instance of `java.util.List` and assigning that to the property):
.. if _valueType_ is a class and is the type
parameter specified in the element factory method, then instantiate the
class using element factory method; otherwise instantiate the class
using factory method if specified by `@XmlType.factoryClass()` and
`@XmlType.factoryMethod()` or if there is no factory method, using the
no-arg constructor.
.. if _valueType_ is an enum type, then obtain
an instance of the enum type for the enum constant annotated with
`@XmlEnumValue` and `@XmlEnumValue.value()` matches the lexical
representation of the EII.
. Invoke any event callbacks in the following order as follows:
.. If _valueType_ implements an unmarshal event
callback `beforeUnmarshal(..)` as specified in Section 4.4.1,"Unmarshal
Event Callback", then invoke `beforeUnmarshal(..)`.
.. If `Unmarshaller.getListener()` returns
`Unmarshaller.Listener` that is not `null`, then invoke
`Unmarshaller.Listener.beforeUnmarshal(..)`.
. If an EII.valuetype is being unmarshalled,
unmarshal into this instance the following. Note: The following steps
can be done in any order; the steps are just broken down and listed
separately for clarity:
+
If EII.valueType being unmarshalled
.. unmarshal each child element information
item in EII.[children] as specified in <<element-information-item>>.
.. unmarshal each attribute information item
in EII.[attributes] as specified in <<attribute-information-item>>.
. Unmarshal the value of EII.schematype or
AII.schematype following the Java to XML Schema rules defined in Chapter
8, "Java Types to XML". If the value in XML instance is unparseable,
then it must be handled as specified in <<Unparseable Data for Simple types>>.
. Invoke any event callbacks in the following order as follows:
.. If _valueType_ implements an unmarshal event
callback `afterUnmarshal(..)` as specified in Section 4.4.1,"Unmarshal
Event Callback, then invoke `afterUnmarshal(..)`.
.. If `Unmarshaller.getListener()` returns
`Unmarshaller.Listener` that is not `null`, then invoke
`Unmarshaller.Listener.afterUnmarshal(..)`.
. return // either AII.valuetype or
EII.valuetype.
==== Element Information Item
An EII must be unmarshalled as follows:
. infer EII.property as specified in <<property-inference-element-information-item>>.
. if EII.property is null, then there is no
property to hold the value of the element. If validation is on (i.e.
Unmarshaller.getSchema() is not null), then report a
jakarta.xml.bind.ValidationEvent. Otherwise, this will cause any unknown
elements to be ignored.
+
If EII.property is not null and there is no
setter method as specified in section <<getterssetters>>
then report a jakarta.xml.bind.ValidationEvent.
+
Goto step 8.
. infer the EII.valuetype as described in <<type-inference-element-information-item>>.
. if EII.valuetype is null, then go to step 8.
+
[NOTE]
.Note
====
EII.valuetype = null implies that there
was problem. so don't attempt to unmarshal the element.
====
. Unmarshal EII.valuetype as specified in <<value-type>>.
. if there is a @XmlJavaTypeAdapter
associated with EII.property, then adapt the EII.valuetype as follows:
+
--
[source,java]
----
EII.boundtype = @XmlJavaTypeAdapter.value().unmarshal(EII.valuetype)
----
otherwise
[source,java]
----
EII.boundtype = EII.valuetype
----
--
. set the value of EII.property to EII.boundtype as follows:
+
--
Wrap EII.boundtype into a jakarta.xml.bind.JAXBElement instance if:
.. the property is not a collection type and
its type is jakarta.xml.bind.JAXBElement
.. the property is a collection type and is a
collection of JAXBElement instances (annotated with @XmlElementRef or
@XmlElementRefs)
--
+
--
If EII.property is not a collection type:
.. set the value of EII.property to EII.boundtype.
--
+
If EII.property is collection type:
.. add EII.boundtype to the end of the collection.
+
[NOTE]
.Note
====
Adding JAXBElement instance or a type
to the end of the collection preserves document order. And document
order could be different from the order in XML Schema if the instance
contains invalid XML content.
====
. return
==== Attribute Information Item
An attribute information item must be unmarshalled as follows:
. infer AII.property as described in section
<<property-inference-attribute-information-item>>.
. if AII.property is null, then the attribute
is invalid with respect to the XML schema. This is possible if for e.g.
schema has evolved. If validation is on (i.e. Unmarshaller.getSchema()
is not null), then report a jakarta.xml.bind.ValidationEvent. Otherwise,
this will cause any unknown elements to be ignored.
+
If AII.property is not null and there is no
setter method as specified in section <<getterssetters>>
then report a jakarta.xml.bind.ValidationEvent.
+
Goto step 8.
. infer the AII.valuetype as described in
<<type-inference-attribute-information-item>>.
. if AII.valuetype is null, then go to step 8.
+
[NOTE]
.Note
====
AII.valuetype = null implies that there
was problem. so don't attempt to unmarshal the attribute.
====
. Unmarshal AII.valuetype as specified in <<value-type>>.
. If AII.property is associated with a
`@XmlJavaTypeAdapter`, adapt AII.valuetype as follows:
+
[source,java]
----
AII.boundtype = @XmlJavaTypeAdapter.value().unmarshal(AII.valuetype)
----
otherwise
+
[source,java]
----
AII.boundtype = AII.valuetype
----
. If AII.property is single valued:
.. set the value of AII.property to AII.boundtype.
+
If AII.property is a collection type (e.g.
List<Integer> was mapped to a Xml Schema list simple type using @XmlList
annotation):
+
add EII.boundtype to the end of the collection.
. return
==== Property Inference
Unmarshalling requires the inference of a
property or a field that contains the value of EII and AII being
unmarshalled.
===== Property Inference - Element Information Item
The property to which an EII is mapped is
inferred based on name.
[NOTE]
.Note
====
Inferring the property to which the EII is mapped by name rather than
it’s position in the content model within the schema is key to
dealing with invalid XML content.
====
Infer EII.property by matching constraints described below:
. initialize EII.property to null
. if property is mapped to XML Schema element
declaration, elem, in the content model of EII.[parent].schematype &&
EII.[local name] == elem.{name} && EII.[namespace] == elem.{namespace}
set EII.property to property.
+
Goto step 4.
. If there is a JAXB property mapped to XML
Schema wildcard (`xs:any`) (as determined by `@XmlAnyElement`), set
this JAXB property to EII.property. This property will hold wildcard
content (e.g. invalid XML content caused by schema evolution).
. return EII.property
===== Property Inference - Attribute Information Item
Infer the property for the AII by matching
constraints described below:
. initialize AII.property to null
. if property mapped to XML Schema attribute
declaration, attr, in the content model of AII.[owner].schematype &&
AII.[local name] == attr.{name} && AII.[namespace] == attr.{namespace}
set AII.property to property
+
Goto step 4.
. if there is a property mapped to a XML
Schema `xs:anyAttribute` (i.e. annotated with `@XmlAnyAttribute`), then
set this property to AII.property. This property holds XML content
matching wildcard attribute (`xs:anyAttribute`) or unknown attributes
(which can occur for e.g. if schema has evolved).
. return AII.property
==== Type Inference
Unmarshalling requires the inference of the
type of a property or a field that to contain the value of EII and AII
being unmarshalled.
===== Type Inference - Element Information Item
This section describes how to infer EII.valuetype;
this holds the value of the element (content model + attributes).
EII.valuetype must be inferred as described below:
. initialize EII.valuetype to null.
. if EII.xsitype is set, document author has
performed type substitution.
+
Goto step 4 to handle type substitution.
. if EII.schematype is not mapped to a java type, then
.. report a validation event.
.. Go to step 7.
+
otherwise
.. set EII.valuetype to the javatype to which
EII.schematype is mapped.
.. Go to step 7.
+
[NOTE]
.Note
====
This case can arise for example, when
EII.schematype is compiled into a java type at schema compilation time,
but the javatype was not registered with `JAXBContext.newInstance(..)`.
====
+
. check if EII.xsitype is mapped to a JAXB
mapped type. It is possible that EII.xsitype is compiled to a javatype
at schema compilation time, but the javatype was not registered with
`JAXBContext.newInstance(..)`
+
If EII.xsitype is not mapped, then report a
validation event.
+
Goto step 7.
. check if the java type to which EII.xsitype
is mapped is assignment comparable with the static type of the
property/field if no `@XmlJavaTypeAdapter` is associated with the
property/field or with the `valueType` specified in
`XmlAdapter<valueType, boundType>` if a `@XmlJavaTypeAdapter` is
associated with the property/field.
+
The above check can fail for e.g when a
document author attempts to substitute a complex type that derives from
simple type but customization to enable simple type substitution was not
used. For e.g.
.. {nbsp}
+
[source,xml,indent="2"]
----
<!-- local element with simple type -->
<xs:element name="foo" type="xs:int"/>
<!-- complex type for substituting the simple type -->
<xs:complexType name="MyInt">
<xs:extension xs:int>
...add attributes
</xs:extends>
</xs:complexType>
----
.. customization to handle type substitution
of simple types is not used. So the property is
+
[source,java,indent="4"]
----
public int getFoo();
public void setFoo(int);
public class MyInt {...}
----
.. the document author attempts to substitute complexType MyInt.
+
[source,xml,indent="2"]
----
<foo xsi:type="MyInt"/>
----
.. The type MyInt is not assignment comparable with int.
. set EII.valuetype to javatype to which EII.xsitype is mapped.
+
[NOTE]
.Note
====
If we got to this step, this implies that type substitution is valid.
====
. return EII.valuetype
===== Type Inference - Attribute Information Item
Infer the AII.valuetype as follows:
. initialize AII.valuetype to null.
. if AII.schematype is not mapped to a java
type, then report a validation event. Otherwise, set AII.valuetype to
the java type to which AII.schematype is mapped.
+
[NOTE]
.Note
====
This case can arise for example, when
AII.schematype is compiled into a java type at schema compilation time,
but the java type is not registered with the `JAXBContext.newInstance(..)`
====
. return AII.valuetype
==== Invalid XML Content
===== Unparseable Data for Simple types
If simple type data cannot be parsed into a
java datatype, then the value of the java datatype must not change the
current set value. An access to the datatype must return the value as
specified in <<missing-element-information-item>>.
If the conversion of lexical representation into a
value results in an exception, then the exception must be caught and a
validation event reported. This is to ensure that such conversion errors
do not terminate unmarshalling.
[source,xml,indent="2"]
----
<!-- Example: XML Schema fragment -->
<xs:element name="foo" type="xs:int"/>
----
[source,xml,indent="2"]
----
<!-- Example: XML instance.
Data is not parseable into type xs:int;
however unmarshal will still succeed. -->
<foo> SUN </foo>
----
===== Missing element information item
This case arises when an element declaration
required by a XML schema is missing from the XML instance.
Property or field access must return the
value specified in <<value-for-missing-elementsattributes>>.
===== Missing Attribute
This case arises when a property or a field
is mapped to an XML attribute but the attribute is missing from the XML
instance.
Property or field access must return the
value specified in <<value-for-missing-elementsattributes>>.
===== Value for missing elements/attributes
If an attribute or an element is missing from
an XML instance, then unmarshal will not change the current set value.
An access to the property will return the set value or if unset, the
uninitialized value. The uninitialized value of the property or field
depends upon it's type. If the type is
. int - value is 0
. boolean - value is false
. a reference (must be mapped to a simple type) - value is null.
. float - the value is +0.0f
. double - the value is 0.0d
. short - the value is (short) 0
. long - the value is 0L
[NOTE]
.Note
====
The uninitialized values are returned
only if the value is not set. A value could be set for example in a
validation handler that catches the validation event.
====
===== Unknown Element
In this case, XML instance contains EII for
which there is no corresponding element declaration in the XML schema.
If the valuetype to which the EII.parent maps contains a property/field
annotated with `@XmlAnyElement`, this EII can be unmarshalled into the
property/field.
Unknown attribute handling during
unmarshalling is specified in <<property-inference-element-information-item>>.
===== Unknown attribute
In this case, XML instance contains AII for
which there is no corresponding attribute declaration in the XML schema.
If the valuetype to which the AII.parent maps contains a property/field
annotated with `@XmlAnyAttribute`, the AII can be unmarshalled into the
property/field.
Unknown attribute handling during
unmarshalling is specified in <<property-inference-attribute-information-item>>.
=== Marshalling
To marshal a content tree, a JAXB application invokes one of the following marshal methods:
[source,java,indent="4"]
----
Marshaller.marshal(Object jaxbElement, ...) throws JAXBException;
Binder.marshal(Object jaxbObject, ...) throws JAXBException;
----
A JAXB Provider must marshal the content tree as follows:
* marshal the XML root element tag as
specified in <<xml-root-element-tag>>
* marshal `obj` as specified in section
<<type>>.
==== XML Root Element Tag
. If `obj` is an instance of
`jakarta.xml.bind.JAXBElement` then marshal `obj` as specified in
<<jaxbelement>>
+
Goto step 4
. If `obj.getClass()` is annotated with
`@XmlRootElement`, then set {EII.[local name], EII.[namespace]} by
deriving them from the @XmlRootElement annotation following the Java to
Schema mapping rules in chapter 8. Marshal obj instance as specified in
<<type>>.
+
Goto step 4
. If obj has neither an @XmlRootElement nor
is a JAXBElement instance, then throw a `JAXBException` and terminate
processing.
. done
==== Type
The type must be marshalled as follows. If the type is an instance of
* JAXBElement, then marshal as specified in <<jaxbelement>>.
* Otherwise, marshal the type as follows. If
the type is a:
** class, then marshal as specified in
<<class-2>>.
** primitive type or standard class, then
marshal as specified in <<primitives-and-standard-classes>>
** enum type then marshal following the schema
to which it is mapped.
===== JAXBElement
An `obj`, that is an instance of
`jakarta.xml.bind.JAXBElement` must be marshalled as specified here:
. `JAXBElement jaxbelem = (JAXBElement) obj;`
. set {EII.[local name] , EII.[namespace]} to `jaxbelem.getName()`
. if `jaxbelem.isNil()`, add `xsi:nil` to EII.[attributes]
+
[NOTE]
.Note
====
It is valid for a content model that is nil to have attributes. For e.g.
[source,xml,indent="2"]
----
<foo xsi:nil attr1="1"/>
----
The attributes will be marshalled when the value that the JAXBElement wraps is marshalled.
====
. if `jaxbelem.isTypeSubstituted()` is true,
then type substitution has occurred i.e. `jaxbelem.getDeclaredType()`
(static type) is different from `jaxbelem.getValue()` (the type of the
value for this instance). So,
.. EII.[local name] = "type"
.. EII.[prefix] = "xsi"
.. EII.[normalized value] = QName of the
schema type to which `jaxbelem.getValue()` is mapped following
Java -> Schema mapping rules in Chapter 8. For e.g.
+
[source,xml,indent="2"]
----
<foo xsi:type="MyAddrType"/>
----
. set _boundType_ to jaxbelem.getValue() if
jaxbelem.isTypeSubstituted() is true otherwise
jaxbelem.getDeclaredType()
. determine the _valueType_ to be marshalled.
If the program element being processed is associated with
@XmlJavaTypeAdapter then _boundType_ is
+
[source,java,indent="2"]
----
valueType = @XmlJavaTypeAdapter.value().marshal(boundType)
----
otherwise _valueType_ is _boundType_
. map _valueType_ to XML infoset information
items as specified in <<type>> and add
them to EII.
. marshal EII.
===== class
A class must be mapped to XML infoset items as follows:
. If a class mapped to a value as specified <<xmlvalue>>,
then map the value to an XML infoset and add it to EII.[children]
+
return
. For each property that is mapped to XML
attribute as specified in <<xmlattribute>>:
.. derive {AII.[local name], AII.[prefix],
AII.[namespace] } from {name} {target namespace}.
.. AII.[normalized value] = value of property
as specified in <<property-type>>
.. add AII to EII.[attributes]
+
[NOTE]
.Note
====
There order in which the properties are
marshalled is not specified (XML attributes are unordered by XML
Schema).
====
. For each property that is mapped to an XML
element declaration, elem:
.. derive {childEII.[local name],
childEII.[prefix], childEII.[namespace]} from elem.{name}
elem.{target namespace}
.. map property type to XML infoset items into
childEII as specified in <<property-type>>.
.. add childEII to EII.[children]
===== property type
The value of a property with type , _boundType_,
must be marshalled into childEII (set by "caller of this
section") as follows:
. If property does not have a getter method
as specified in section <<getterssetters>>
then report a jakarta.xml.bind.ValidationEvent.
+
Goto step 4.
. If the value of the property being marshalled is a subtype _boundType_, then
.. EII.[local name] = "type"
.. EII.[prefix] = "xsi"
.. EII.[normalized value] = QName of the
schema type to which `jaxbelem.getValue()` is mapped following
Java -> Schema mapping rules in Chapter 8. For e.g.
+
[source,xml,indent="2"]
----
<foo xsi:type="MyAddrType"/>
----
.. add EII to childEII
. Marshal the value as specified in <<type>>.
. Return
===== Primitives and Standard classes
Primitive values and standard classes
described in this section map to XML schema simple types.
The value of a primitive type or a standard
class must be marshalled to a lexical representation or unmarshalled
from a lexical representation as specified in the below:
* using a print or parse method in
jakarta.xml.bind.DatatypeConverter interface:
+
Many of the types have a corresponding print
and parse method in jakarta.xml.bind.DatatypeConverter interface for
converting a value to a lexical representation in XML and vice versa.
The implementation of DatatypeConverter is JAXB Provider specific.
+
A XML Schema simple type can have more than
lexical representation (e.g. "true" "false" "0" "1"). Since the
DatatypeConverter implementation is JAXB Provider specific, the exact
lexical representation that a value is marshalled to can vary from one
JAXB Provider to another. However, the lexical representation must be
valid with respect to the XML Schema.
* some data types such as
XMLGregorianCalendar contain methods on the class that return or consume
their XML lexical representation. For such datatypes, the method
indicated in the table is used.
* A wrapper class (e.g. java.lang.Integer)
must be converted to its non wrapper counterpart (e.g. int) and then
marshalled.
.Lexical Representation of Standard Classes
[cols=",,",options="header"]
|===
| Java Standard Classes | printMethod | parseMethod
| `java.lang.String` | `printString` | `parseString`
| `java.util.Calendar` | `printDateTime` | `parseDateTime`
| `java.util.Date` | `printDateTime` | `parseDateTime`
| `java.net.URI` | `URI.toString()` | `URI(String str)`
| `javax.xml.datatype.XMLGregorianCalendar` | `XMLGregorianCalendar
.toXMLFormat()`
| `DatatypeFactory.
newXMLGregorianCalendar(String lexicalRepresentation)`
| `javax.xml.datatype.Duration` | `Duration.toString()`
| `DatatypeFactory.newDuration(String lexicalRepresentation)`
| `java.util.UUID` | `UUID.toString()` | `UUID.fromString()`
|===
===== Null Value
A null value in Java representation can be
marshalled either as an absence of an element from an XML instance or as
`xsi:nil`. The marshalled value depends upon the values of
`@XmlElement.required()` and `@XmlElement.nillable()` annotation
elements on the property/field and must be marshalled as shown below.
For clarity, example schema fragments (as determined by the mapping
rules specified in Chapter 8) for the following field
[source,java,indent="4"]
----
@XmlElement(required="...", nillable="...")
foo;
----
are reproduced here along with the XML representation for null value produced by marshalling.
* `@XmlElement(required=true, nillable=false)`
+
The value of the property/field cannot be null.
+
[source,xml,indent="2"]
----
<!-- Example: Generated schema -->
<xs:element name="foo" minOccurs="1" ...>
...
</xs:element>
----
* `@XmlElement(required=true, nillable=true)`
+
null is marshalled as `xsi:nil="true"`
+
[source,xml,indent="2"]
----
<!-- Example: Generated schema -->
<xs:element name="foo" minOccurs="1" nillable="true" ...>
...
</xs:element>
<!-- marshalled XML representation for null value -->
<foo xsi:nil="true" .../>
----
* `@XmlElement(required=false, nillable=true)`
+
null is marshalled as `xsi:nil="true"`
+
[source,xml,indent="2"]
----
<!-- Example: Generated schema -->
<xs:element name="foo" minOccurs="0" ...>
...
</xs:element>
<!-- Example: marshalled XML representation for null value -->
<foo xsi:nil="true" .../>
----
* `@XmlElement(required=false, nillable=false)`
+
null is not marshalled i.e it maps to absence
of an element from XML instance.
+
[source,xml,indent="2"]
----
<!-- Example: Generated schema -->
<xs:element name="foo" minOccurs="0" ...>
...
</xs:element>
<!-- Example: null value for foo not marshalled -->
----
=== Getters/Setters
When `@XmlAccessType.PUBLIC_MEMBER` or
`@XmlAccessType.PROPERTY` is in effect for a class, then the instance of
the class is marshalled using getter/setter methods as opposed to
fields. This section outlines the constraints the must be checked at
runtime. A constraint failure is handled as specified elsewhere in the
chapter from where this section is referenced.
*_Unmarshalling:_* A property must have a setter method if
* `@XmlAccessorType.PUBLIC_MEMBER` or
`@XmlAccessorType.PROPERTY` applies to the property.
* or if the property’s getter/setter method
is annotated with a mapping annotation.
The one exception to the above constraint is:
if property type is `java.util.List` then only a getter method is
required.
[NOTE]
.Design Note
====
For a JavaBean property with getter/setter methods, a setter method is required for
unmarshalling when public API (as opposed to fields) is used
i.e. either `@XmlAccessorType.PUBLIC_MEMBER` or `@XmlAccessorType.PROPERTY`
is in effect. If `@XmlAccessorType.FIELD` is in effect, then unmarshalling is
based on fields and hence a setter method is not required.
There is however one exception.
When starting from schema, a schema component (e.g. a repeating occurrence of an element)
can be bound to a `java.util.List` property (so modifications to `java.util.List`
can be intercepted, a design decision from JAXB 1.0). Thus only in this case
a setter method is not required. E.g.
[source,java,indent="4"]
----
public java.util.List getFoo();
// public void setFoo(..) not required
----
====
*_Marshalling:_* A property must have a getter method if
* `@XmlAccessType.PUBLIC_MEMBER` or
`@XmlAccessType.PROPERTY` applies to the class
* or if the property’s getter/setter method
is annotated with a mapping annotation.