users@jaxb.java.net

Erroneous unmarshalling of complex types within complex content derived by restriction

From: Thomas Portmann <thomas.portmann_at_db.com>
Date: Fri, 04 Apr 2003 18:50:23 +0200

Joe Fialli wrote:

> Both attribute
> and model group definitions are the closest that XML Schema comes to
> formally modeling the java concept that a class implements multiple
> interfaces.
> ...
> I believe it is best first to identify the automated schema bindings to
> java that result in
> the behavior you are seeking.
> ... the hope is that
> schema designers in the future will use schema features that capture
> that commonality.
> The benefit is that the names of the model and attribute group
> definitions can be mapped
> to interfaces automatically by the databinding, with no customizations
> needed.
> The more commonality in semantically meaningful names between the schema
> and the schema-derived code, the easier to relate the two.

Life with JAXB could go on if at least those above praised, but in reality very limited possibilities of inheritance, which are provided by the XML Schema concept and - if in addition you have a lot of luck - are allowed by the JAXB compiler, would actually work in the spirit of object oriented design.

But those facilities are almost needless, because the unmarshaller is apparently not aware of the schema context, or instance context, resp., which is - under certain circumstances - necessary to determine the type of an element, if this type is derived by restriction within that context.

Consider the following example: Given a complex type, say, "superRootType", with the following complex content:

  <xs:complexType name="superRootType">
    <xs:all>
      <xs:element name="property-to-be-restricted" type="xs:NCName"/>
      <xs:element name="container" type="comlexChildType"/>
    </xs:all>
  </xs:complexType>
  <xs:complexType name="comlexChildType">
    <xs:all>
      <xs:element name="sub-property-to-be-restricted" type="xs:int"/>
    </xs:all>
  </xs:complexType>

Now, we want to restrict the whole model, perhaps because we have a sub-project of our calculation kernel dedicated to a certain separated business unit, and in this business unit, certain simple but essential constraints apply, but apart from this, the model is the same. So in the spirit of XML Schema and object oriented design blah blah, one would like to derive some special complex types by restriction, e.g.

  <xs:complexType name="subRootType">
    <xs:complexContent>
      <xs:restriction base="superRootType">
        <xs:all>
          <xs:element name="property-to-be-restricted">
            <xs:simpleType>
              <xs:restriction base="xs:NCName">
                <xs:maxLength value="5"/>
              </xs:restriction>
            </xs:simpleType>
          </xs:element>
          <xs:element name="container" type="subComplexChildType"/>
        </xs:all>
      </xs:restriction>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="subComplexChildType">
    <xs:complexContent>
      <xs:restriction base="comlexChildType">
        <xs:all>
          <xs:element name="sub-property-to-be-restricted">
            <xs:simpleType>
              <xs:restriction base="xs:int">
                <xs:minInclusive value="0"/>
                <xs:maxInclusive value="7"/>
              </xs:restriction>
            </xs:simpleType>
          </xs:element>
        </xs:all>
      </xs:restriction>
    </xs:complexContent>
  </xs:complexType>

The inner type "comlexChildType" is restricted, too.

Now, if you look at this, you feel, this is o.k. It is simple enough. But if you have experience in trying to make inheritance and JAXB getting friends, you already know, that this means nothing. - O.k., now, XML Spy says, it's o.k., too. But if you have experience in trying to make inheritance and JAXB getting friends, you already know, that this means nothing. - - O.k., now, the xjc compiler throws no error. - Wow! Great! - With a lot of caution, you are beginning to believe that it is really o.k. (Sorry for this, but since two weeks I'm trying to generate a suitable class model with no success. I didn't ever experience such a situation...)

Now, you simply add

  <xs:element name="superRoot" type="superRootType"/>
  <xs:element name="subRoot" type="subRootType"/>

write a sample XML document which is quite obviously very valid

<?xml version="1.0" encoding="UTF-8"?>
<subRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="myVerySimple.xsd">
  <property-to-be-restricted>NCNam</property-to-be-restricted>
  <container>
    <sub-property-to-be-restricted>7</sub-property-to-be-restricted>
  </container>
</subRoot>

- but, because you are a bad guy, you instantiate the sub type element, not the super type one, to check the use of inheritance - then write a simple program, which unmarshals this sample XML first and validates it after this ("on demand") - which should definitely result in no errors, like

import some stuff ...;

public class Main {

    public static class MyValidationEventHandler
        implements ValidationEventHandler
    {
        public MyValidationEventHandler () {}

        public boolean handleEvent (ValidationEvent event) {
            System.out.print ("Severity = " + event.getSeverity () + " (");
            boolean ret = true;
            switch (event.getSeverity ()) {
                case ValidationEvent.WARNING:
                    System.out.print ("warning");
                    break;
                case ValidationEvent.ERROR:
                    System.out.print ("error");
                    break;
                case ValidationEvent.FATAL_ERROR:
                    System.out.print ("fatal error");
                    ret = false;
                    break;
                default:
                    System.out.print ("unknown");
                    break;
            }
            System.out.println ("), message = " + event.getMessage ());
            return ret;
        }
    }

    public static void main( String[] args ) {
        try {
            JAXBContext jc = JAXBContext.newInstance( "myPackageName" );

            Unmarshaller u = jc.createUnmarshaller();
            SuperRootType s = (SuperRootType) u.unmarshal (new FileInputStream ("myVerySimple.xml"));
            ComlexChildType c = s.getContainer ();

            Validator v = jc.createValidator ();
            v.setEventHandler (new MyValidationEventHandler ());
            boolean ok = v.validateRoot (s);
            System.out.println ("Document is " + (ok ? "" : "not ") + "valid.");
            System.out.println ("class of child = " + c.getClass ());

        } catch( JAXBException je ) {
            je.printStackTrace();
        } catch( IOException ioe ) {
            ioe.printStackTrace();
        }
    }
}

call ant, and get

      [xjc] Compiling file:myVerySimple.xsd
     [echo] Compiling the java source files...
    [javac] Compiling 14 source files to D:\jwsdp1.1\jaxb-1.0\examples\bug
run:
     [echo] Running the sample application...
     [java] Severity = 1 (error), message = tag name "myPackageName.ComlexChildType" is not allowed. Possible tag names are: <myPackageName.SubComplexChildType>
     [java] Document is not valid.
     [java] class of child = class myPackageName.impl.ComlexChildTypeImpl

BUILD SUCCESSFUL
Total time: 19 seconds



:-(



Do you see what happened? - The Unmarshaller encountered the element "container"-----and used the super class "myPackageName.ComlexChildType" for unmarshalling-----although it may not, because its actual context is "subRootType". Apparently, it is driven by the element name only, not by the context.

The validator seems to be smarter - it complains about the result of the unmarshaller.

But, you see, it is really needless to make this derivation: The unmarshaller ignores the context of the element, so the only way to work around this would be to give the container element another element name. But this way, you are not able any more to restrict the model, because this would be an extension. And - its a pity of its own - the xjc compiler is not willing to accept a chained derivation where a restriction is followed by an extension or vice versa.

And I'm not willing to write a program which serves the task of repairing the unmarshalled objects to fit into the correct model again. Now, I have a problem with my project leader...



Best regards
Thomas




--
Diese E-Mail enth?lt vertrauliche und/oder rechtlich gesch?tzte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrt?mlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.
This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden.