1 Reply Latest reply on Jul 21, 2005 6:27 AM by aloubyansky

    Java object vs xml parse stack

    starksm64

      So in going through the some debugging of the attribute defaults issue, I have a problem understanding the current relationship between the java object stack and the xml document parse stack. Let's start with the xsd for the element that is causing me trouble:

      ...
      <xs:element name="binding" minOccurs="1"
       maxOccurs="unbounded">
       <xs:annotation>
       <xs:appinfo>
       <jbxb:class impl="org.jboss.naming.JNDIBinding"/>
       <jbxb:property name="Bindings" />
       </xs:appinfo>
       </xs:annotation>
       <xs:complexType>
       <xs:choice minOccurs="1" maxOccurs="1">
       <xs:element name="value">
       <xs:annotation>
       <xs:appinfo>
       <jbxb:property name="text"/>
       </xs:appinfo>
       </xs:annotation>
       <xs:complexType>
       <xs:simpleContent>
       <xs:extension base="xs:string">
       <xs:attribute name="type" type="xs:string" use="optional" default="java.lang.String">
       </xs:attribute>
       <xs:attribute name="editor" type="xs:string" use="optional">
       </xs:attribute>
       <xs:attribute name="replace" type="xs:boolean" default="true">
       </xs:attribute>
       <xs:attribute name="trim" type="xs:boolean" default="true">
       </xs:attribute>
       </xs:extension>
       </xs:simpleContent>
       </xs:complexType>
       </xs:element>
       <xs:any namespace="##other">
       <xs:annotation>
       <xs:documentation>An extension point for arbitrary xml value fragments</xs:documentation>
       </xs:annotation>
       </xs:any>
       </xs:choice>
       <xs:attribute name="name" type="xs:string" use="required">
       <xs:annotation>
       <xs:documentation>The JNDI name of the binding</xs:documentation>
       </xs:annotation>
       </xs:attribute>
       </xs:complexType>
      </xs:element>
      ...
      


      A binding element maps to a org.jboss.naming.JNDIBinding object, and the collection of binding elements maps to the Bindings property of the associated parent element java object.

      A binding is either a value element with text content and 4 attributes, or an arbitrary xml fragment from another namespace. The text of the value element maps to the "text" property of the JNDIBinding class. The any extension point would map to the "value" Object property of the JNDIBinding class.

      So one disconnect I have is that in the default parse mode, the value element has no associated class specified, and there is no org.jboss.naming.Value class that can be selected automatically. When I look at this schema I'm expecting that in the absence of an explicit or automatic mapping of the value element to an object, it will simply inherit its parent element's object. Is this a meaningful mode of behavior in general? To achieve this affect, Alexey corrected the above schema fragment to:

      <xs:element name="binding" minOccurs="1"
       maxOccurs="unbounded">
       <xs:annotation>
       <xs:appinfo>
       <jbxb:class impl="org.jboss.naming.JNDIBinding"/>
       <jbxb:property name="Bindings" />
       </xs:appinfo>
       </xs:annotation>
       <xs:complexType>
       <xs:choice minOccurs="1" maxOccurs="1">
       <xs:element name="value">
       <xs:annotation>
       <xs:appinfo>
       <jbxb:skip/>
       </xs:appinfo>
       </xs:annotation>
       <xs:complexType>
       <xs:annotation>
       <xs:appinfo>
       <jbxb:characters>
       <jbxb:property name="text"/>
       </jbxb:characters>
       </xs:appinfo>
       </xs:annotation>
       <xs:simpleContent>
       <xs:extension base="xs:string">
       <xs:attribute name="type" type="xs:string" use="optional" default="java.lang.String">
       </xs:attribute>
       <xs:attribute name="editor" type="xs:string" use="optional">
       </xs:attribute>
       <xs:attribute name="replace" type="xs:boolean" default="true">
       </xs:attribute>
       <xs:attribute name="trim" type="xs:boolean" default="true">
       </xs:attribute>
       </xs:extension>
       </xs:simpleContent>
       </xs:complexType>
       </xs:element>
       <xs:any namespace="##other">
       <xs:annotation>
       <xs:documentation>An extension point for arbitrary xml value fragments</xs:documentation>
       </xs:annotation>
       </xs:any>
       </xs:choice>
       <xs:attribute name="name" type="xs:string" use="required">
       <xs:annotation>
       <xs:documentation>The JNDI name of the binding</xs:documentation>
       </xs:annotation>
       </xs:attribute>
       </xs:complexType>
      </xs:element>
      


      The jbxb:skip essentially removes the value element and merges the content into the binding element along with the attributes. I can understand this mapping fine. I guess my issue is why this was not the natural choice for me. I think the problem is that we don't have an overview of xml to java mapping that clearly shows how elements in a xml tree map to elements in a java object model tree.

      This should be done from the default jaxb rules as well as from how the various jaxb/jbxb annotations can be used to manipulate the element mapping to a java object model that is increasingly removed from the expected default. The point is we start with the defaults to show the fine-grained object model that is expected, and then illustrate how customizations can be used to map the same xml document onto a much more compact, preexisting object model graph. I'll work with the documentation team to get this fleshed out.

      In terms of the default behavior, the question is whether or not it makes sense for the jbxb:skip to be implicitly present for any element that does not have an explicit or automatic class specification? This could be another jbxb:schemaBindings setting.


        • 1. Re: Java object vs xml parse stack
          aloubyansky

          Currently, default rules imply that for each XML element a Java object will be created.

          For user-defined XML types that are not bound with annotations, the default algorithm will be used to derive a fully-qualified class name from the XML type/element QName.
          If the class cannot be loaded, a warning will be logged and this element and all its attributes, text and child elements will be ignored. Or, if ignoreNotFoundFieldOrClass property is false (default is true), an unchecked exception will be thrown halting unmarshalling immediately.

          If for an element of a complex type a user doesn't want to create an object but wants to set its attributes, text and child elements on the object created for the parent element, jbxb:skip should be placed on the element.

          "scott.stark@jboss.org" wrote:
          The text of the value element maps to the "text" property of the JNDIBinding class.


          This is not how it works.
          jbxb:property binds the result of unmarshalling of an element to a property.
          If element is of a simple type, the result is unmarshalled text content. If element is of a complex type, the result is an object that contains unmarshalled attrs, text and child elements. You have to nest jbxb:property in jbxb:characters to bind text content to a specific property.

          In your case, you there is no object specific to the value element. And still, I think, it's better to nest jbxb:property in jbxb:characters in this case for consistency. Otherwise, it looks confusing to me.

          "scott.stark@jboss.org" wrote:
          In terms of the default behavior, the question is whether or not it makes sense for the jbxb:skip to be implicitly present for any element that does not have an explicit or automatic class specification?


          There could be a case, in which I would like to ignore the whole branch of XML elements and their contents. In this case, it's not jbxb:skip.
          I don't know which case is going to be more common. I would stick to the current behaviour for now. If your opinion is different, let's discuss.

          "scott.stark@jboss.org" wrote:
          This could be another jbxb:schemaBindings setting.


          Yes. Then we will also need a jbxb:ignore or something like that to switch the behaviour that is currently the default.