Re: PROV-ISSUE-648: Can schema be made a bit more jaxb friendly? [XML Serialization]

Hi Luc,

I'm using jaxb-ri-2.2.6 against our latest prov*.xsd and seeing slightly
different bindings with JAXBElement:

public class Document {
    @XmlElementRefs({
        @XmlElementRef(name = "hadPrimarySource", namespace =
"http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "agent", namespace =
"http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "activity", namespace =
"http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "organization", namespace =
"http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "softwareAgent", namespace =
"http://www.w3.org/ns/prov#", type = JAXBElement.class, required = false),
....



Some findings:


(1) JAXB's generation of JAXBElement<T> classes seems to be a wrapper
approach to preserve sufficient information in the schema for round-trip
marshaling & unmarshalling of values in XML instances. More specifically,
it wraps the data with a QName and a nillable flag [1].

It appears that the a frequent cause of JAXB producing JAXBElement<T> is
its attempt to preserve elements with both minOccurs=0 and nillable=true.
JAXB needs to distinguish between the two cases where:

  a. element missing, minOccurs=0, then jaxbElement==null
  b. element present, xsi:nil=true, then jaxbElement.isNil()==true

It would not be possible to distinguish between these two states if the
bindings were the raw types.



(2) It would be possible to customize the JAXB bindings [2] to ignore the
full round-trip requirement. The "generateElementProperty=false"
customization option "can be used to generate an alternate developer
friendly but lossy binding" [3].

I tried variations of a "bindings.xjb" customization file:

<jaxb:bindings version="2.1"
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <jaxb:bindings schemaLocation="prov-core.xsd"
    node="//xs:complexType[@name='Document']">
    <jaxb:globalBindings generateElementProperty="false" />
  </jaxb:bindings>
</jaxb:bindings>

$ xjc.sh -d BINDINGS -b bindings.xjb prov.xsd

But none truly eliminated the JAXBElement<T> from the bindings.



(3) Nowhere in our prov-core.xsd do we define minOccurs=0 in conjunction
with nillable=true. In my attempts with JAXB, I'm seeing JAXBElements
appearing in the bindings for the (a) Document class and (b)
BundledConstructor class. Both types leverage the prov:documentElements
grouping.

  <xs:element name="document" type="prov:Document" />
<xs:complexType name="Document">
  <xs:sequence maxOccurs="unbounded">
    <xs:group ref="prov:documentElements" minOccurs="0"/>
    <xs:element name="bundleContent" type="prov:BundleConstructor"
minOccurs="0"/>
    <xs:any namespace="##other" processContents="lax" minOccurs="0" />
  </xs:sequence>
  </xs:complexType>

It's unclear if there is some nillable-like affect that triggers JAXB to
generate the JAXBElements.



(4) On the upside, JAXB does provide an ObjectFactory class as part of the
generated bindings that define creational factory methods to generate the
JAXBElement instances. For example:

  public JAXBElement<Usage> createUsed(Usage value)

Still, I agree that it is not as clean.


--Hook


[1] http://docs.oracle.com/javaee/5/api/javax/xml/bind/JAXBElement.html
[2] 
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.5/tutori
al/doc/JAXBUsing4.html#wp148515
[3] 
http://docs.oracle.com/cd/E17802_01/webservices/webservices/reference/tutor
ials/wsit/doc/DataBinding5.html






On 3/8/13 4:20 AM, "Provenance Working Group Issue Tracker"
<sysbot+tracker@w3.org> wrote:

>PROV-ISSUE-648: Can schema be made a bit more jaxb friendly? [XML
>Serialization]
>
>http://www.w3.org/2011/prov/track/issues/648
>
>Raised by: Luc Moreau
>On product: XML Serialization
>
>
>Hi 
>
>I have ported the ProvToolbox and the ProvValidator to the new XML schema.
>I just wanted to report on my experience with the schema and JAXB.
>Obviously, others may have better experience with JAXB and may be able
>to help on some of the issues I encountered.
>
>Everything worked fine, except:
>- <xs:element ref="prov:internalElement abstract=true/>
>- extensibility <xs:any namespace="##other"/> in Document and Bundle
>
>
>These two constructs, while processable by JAXB, are not JAXB-friendly.
>
>Indeed, JAXB compiles the schema in a list containing all possible
>statements.
>
>    protected List<Object> entityAndActivityAndWasGeneratedBy;
>
>However, the presence on an abstract element and an <any/> element result
>in the
>content of that list to be of type:
>
>
>    @XmlElementRefs({
>        @XmlElementRef(name = "used", namespace =
>"http://www.w3.org/ns/prov#", type = JAXBElement.class),
>        @XmlElementRef(name = "wasAssociatedWith", namespace =
>"http://www.w3.org/ns/prov#", type = JAXBElement.class),
>        @XmlElementRef(name = "person", namespace =
>"http://www.w3.org/ns/prov#", type = JAXBElement.class),
>        @XmlElementRef(name = "entity", namespace =
>"http://www.w3.org/ns/prov#", type = JAXBElement.class),
>        @XmlElementRef(name = "wasInfluencedBy", namespace =
>"http://www.w3.org/ns/prov#"
> ....
>    })
>
>    @XmlAnyElement(lax = true)
>    protected List<Object> entityAndActivityAndWasGeneratedBy;
>
>where all data structures are wrapped up in this unpleasant JAXBElement.
>
>Without these features, we get a much more natural mapping:
>    @XmlElements({
>        @XmlElement(name = "entity", namespace =
>"http://www.w3.org/ns/prov#", type = Entity.class),
>        @XmlElement(name = "activity", namespace =
>"http://www.w3.org/ns/prov#", type = Activity.class),
>        @XmlElement(name = "wasGeneratedBy", namespace =
>"http://www.w3.org/ns/prov#", type = WasGeneratedBy.class),
>        @XmlElement(name = "used", namespace =
>"http://www.w3.org/ns/prov#", type = Used.class),
>        @XmlElement(name = "wasInformedBy", namespace =
>"http://www.w3.org/ns/prov#", type = WasInformedBy.class),
>    ...
>})
>
>So, how I did I solve the problem?  I inserted the extension schemas into
>the schema file, and hence got rid of the abstract element.  I am ok with
>this. We could possible provide the utility to that transformation.
>
>For the extensibility, I used a different definition. It happens to
>parse prov-xml compliant xml. When serializing, it  puts all
>extensibility elements at the end.  This is not a satisfactory
>solution, and is likely to be dependent of the jaxb implementation
>(though I am not entirely sure).
>
>
>   <xs:complexType name="Document">
>     <xs:sequence>
>       <xs:choice maxOccurs="unbounded">
>         <xs:group ref="prov:documentElements"/>
>         <xs:element name="bundleContent" type="prov:NamedBundle"/>
>       </xs:choice>
>       <xs:any namespace="##other" processContents="lax" minOccurs="0"
>maxOccurs="unbounded"/>
>     </xs:sequence>
>   </xs:complexType>
>
>Can something be done to make the XML schema a bit more jaxb friendly,
>while still keeping the same flexibility?  Thoughts welcome.
>
>Cheers,
>Luc
>
>
>
>
>

Received on Thursday, 21 March 2013 11:12:37 UTC