jaxb
  1. jaxb
  2. JAXB-890

JAXB Unmarshaller tries to instantiate abstract class ignoring xsi:type if nillable="true"

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 2.2.5
    • Fix Version/s: 2.2.6
    • Component/s: None
    • Labels:
      None

      Description

      The problem that JAXB tries to instantiate an abstract class (leading to a InstantiationException) ignoring the concrete type provided with xsi:type is well known since 2006 (or earlier), see "Why doesn't JAXB find my subclass?"
      http://weblogs.java.net/blog/kohsuke/archive/2006/04/why_doesnt_jaxb.html

      In
      http://stackoverflow.com/questions/9157484/jaxb-unmarshaller-tries-to-instantiate-abstract-class-ignoring-xsitype
      a detailled example for the industry standard BiPRO is given. We use this very important insurance standard, too.

      Its reported that this problem no longer exists in JDK 1.7. But this does not help us, we are tied to a JDK 1.5 by our application server.

      The problem was addressed in bug JAXB-620, partially solved and the bug was closed.

      But the problem still exists if in the XSD nillable="true" is set.

      In com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.buildChildElementUnmarshallers() you can find the following:
      // LeafPropertyXsiLoader doesn't work well with nillable elements
      if (improvedXsiTypeHandling && !nillable)
      ...

      By the way the property
      JAXBRIContext.IMPROVED_XSI_TYPE_HANDLING = "com.sun.xml.bind.improvedXsiTypeHandling" (mentioned in JAXB-620)
      is not taken into account in com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.setProperty().
      This leads to a PropertyException if you configure this property via org.springframework.oxm.jaxb.Jaxb2Marshaller.setUnmarshallerProperties()

      We use com.sun.xml.bind:jaxb-impl:2.2.5 and javax.xml.bind:jaxb-api:2.2.6.

      Reading the comment "LeafPropertyXsiLoader doesn't work well with nillable elements" I suspect that this problem is not considered as relevant.
      But it is definitely an important problem. The attribute nillable="true" is a standard XSD feature not forbidden (believe me I really hate this feature because the generated JAXB classes blow up with all this JAXBElement<> stuff) and JAXB should be able to deal with it correctly.

      If you are not convinced of the relevance, think about the following: if you want to define an industry standard (for example insurance as BiPRO does)
      with a data model defined by XSDs you certainly will define sequences containing elements of abstract types to allow for an extension to special classes of business or even companies. An element of concrete type has to be provided via xsi:type, but if JAXB does not understand it this concept fails.

      Please fix this bug. Otherwise we might be forced to use an ugly message oriented processing with XPATH instead of a beautiful object oriented processing with JAXB.

      As long as the bug is not fixed: is a work around available via globalBindings ?

      Sample:

      Sequence containing element of abstract type[xmlns:tar="http://www.bipro.net/namespace/tarifierung"]:
      <xsd:complexType name="CT_VersicherungssummeOderLeistung">
      <xsd:complexContent>
      <xsd:extension base="allgemein:CT_Objekt">
      <xsd:sequence>
      <xsd:element name="ArtID" type="daten:STE_VersicherungssummeOderLeistung"
      minOccurs="0" maxOccurs="1" nillable="true" />
      ...
      </xsd:sequence>
      </xsd:extension>
      </xsd:complexContent>
      </xsd:complexType>

      Abstract type[xmlns:daten="http://www.bipro.net/namespace/datentypen"]:
      <xsd:complexType name="STE_VersicherungssummeOderLeistung" abstract="true">
      <xsd:simpleContent>
      <xsd:extension base="xsd:string" />
      </xsd:simpleContent>
      </xsd:complexType>

      Concrete type[xmlns:daten="http://www.bipro.net/namespace/datentypen"]:
      <xsd:complexType name="STE_VersicherungssummeOderLeistungBasis"
      final="#all">
      <xsd:simpleContent>
      <xsd:restriction base="daten:STE_VersicherungssummeOderLeistung">
      ...
      <xsd:enumeration value="Krankentagegeld">
      <xsd:annotation>
      <xsd:documentation>Krankentagegeld</xsd:documentation>
      </xsd:annotation>
      </xsd:enumeration>
      ...
      </xsd:restriction>
      </xsd:simpleContent>
      </xsd:complexType>

      XML-Request:
      ...
      <tar:VersicherungssummeOderLeistung>
      <tar:ArtID xsi:type="daten:STE_VersicherungssummeOderLeistungBasis" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Krankentagegeld</tar:ArtID>
      ...
      </tar:VersicherungssummeOderLeistung>
      ...

      leads to
      INFO: failed to create a new instance of class net.bipro.namespace.datentypen.STEVersicherungssummeOderLeistung
      java.lang.InstantiationException
      at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
      at java.lang.reflect.Constructor.newInstance(Constructor.java:501)
      at com.sun.xml.bind.v2.ClassFactory.create0(ClassFactory.java:133)
      ...

      On the other hand marshalling leads to non valid XML omitting xsi:type declaration:
      <tar:ArtID>Krankentagegeld</tar:ArtID>
      if one uses the generated method in the ObjectFactory:
      public JAXBElement<STEVersicherungssummeOderLeistung> createCTVersicherungssummeOderLeistungArtID(STEVersicherungssummeOderLeistung value)

      { return new JAXBElement<STEVersicherungssummeOderLeistung>(_CTDynamikArtID_QNAME, STEVersicherungssummeOderLeistung.class, CTVersicherungssummeOderLeistung.class, value); }

      This would be correct:
      <tar:ArtID xsi:type="daten:STE_VersicherungssummeOderLeistungBasis" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Krankentagegeld</tar:ArtID>

        Activity

        Hide
        Robert Reinberger added a comment -

        Hi Iaroslav,

        is there already any solution based on Java 1.5? Thanks.

        Show
        Robert Reinberger added a comment - Hi Iaroslav, is there already any solution based on Java 1.5? Thanks.
        Hide
        Iaroslav Savytskyi added a comment -

        Hi, Robert,

        In a few days I will create 2.2.4u4 branch which will contain this fix. So you'll be able to get it. Officially if will be included into the nearest jdk1.7 maintenance update.

        Show
        Iaroslav Savytskyi added a comment - Hi, Robert, In a few days I will create 2.2.4u4 branch which will contain this fix. So you'll be able to get it. Officially if will be included into the nearest jdk1.7 maintenance update.
        Hide
        Iaroslav Savytskyi added a comment -

        Hi,

        I've patched 2.2.4u4 branch with patch for this bug. So you can try to checkout and build it.

        https://svn.java.net/svn/jaxb~version2/branches/jaxb-2_2_4u4

        Show
        Iaroslav Savytskyi added a comment - Hi, I've patched 2.2.4u4 branch with patch for this bug. So you can try to checkout and build it. https://svn.java.net/svn/jaxb~version2/branches/jaxb-2_2_4u4
        Hide
        Robert Reinberger added a comment -

        Hi Iaroslav,

        all is working well, I have no more problems with JAXB. You helped us really very much, thank you!
        Please let us know the version number as soon as the patch is released officially.

        Best regards
        Robert

        Show
        Robert Reinberger added a comment - Hi Iaroslav, all is working well, I have no more problems with JAXB. You helped us really very much, thank you! Please let us know the version number as soon as the patch is released officially. Best regards Robert
        Hide
        dennislundberg added a comment -

        The docs for 2.2.6 says
        "This release of the JAXB Reference Implementation requires J2SE 5.0 or higher."
        http://jaxb.java.net/nonav/2.2.6/docs/ch02.html#section-2232462900667844

        I'm confused, what are the minimum run time requirements for jaxb-api and jaxb-impl?
        The docs says 1.5, but in this thread it is said that 1.6 is required.

        Show
        dennislundberg added a comment - The docs for 2.2.6 says "This release of the JAXB Reference Implementation requires J2SE 5.0 or higher." http://jaxb.java.net/nonav/2.2.6/docs/ch02.html#section-2232462900667844 I'm confused, what are the minimum run time requirements for jaxb-api and jaxb-impl? The docs says 1.5, but in this thread it is said that 1.6 is required.

          People

          • Assignee:
            Iaroslav Savytskyi
            Reporter:
            Robert Reinberger
          • Votes:
            6 Vote for this issue
            Watchers:
            8 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: