jaxb
  1. jaxb
  2. JAXB-793

Multiple element definition not read correctly

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 2.2.1
    • Fix Version/s: not determined
    • Component/s: runtime
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

      Description

      Hi all,

      I have the following schema complex type:

      <complexType name="PolicyType">
      <complexContent>
      <restriction base="

      {http://www.w3.org/2001/XMLSchema}

      anyType">
      <sequence>
      <element ref="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      Description" minOccurs="0"/>
      <element ref="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      PolicyDefaults" minOccurs="0"/>
      <element ref="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      CombinerParameters" minOccurs="0"/>
      <element ref="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      Target"/>
      <choice maxOccurs="unbounded">
      <element ref="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      CombinerParameters" minOccurs="0"/>
      <element ref="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      RuleCombinerParameters" minOccurs="0"/>
      <element ref="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      VariableDefinition"/>
      <element ref="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      Rule"/>
      </choice>
      <element ref="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      Obligations" minOccurs="0"/>
      </sequence>
      <attribute name="PolicyId" use="required" type="

      {http://www.w3.org/2001/XMLSchema}

      anyURI" />
      <attribute name="Version" type="

      {urn:oasis:names:tc:xacml:2.0:policy:schema:os}

      VersionType" default="1.0" />
      <attribute name="RuleCombiningAlgId" use="required" type="

      {http://www.w3.org/2001/XMLSchema}

      anyURI" />
      </restriction>
      </complexContent>
      </complexType>

      The corresponding JAXB class looks like:

      @XmlType(name = "PolicyType", propOrder =

      { "description", "policyDefaults", "combinerParameters", "target", "additionalInformation", "obligations" }

      )
      public class PolicyType implements Evaluatable, Serializable {
      private static final long serialVersionUID = 1L;
      @XmlElement(name = "Description")
      private String description;
      @XmlElement(name = "PolicyDefaults")
      private DefaultsType policyDefaults;
      @XmlElement(name = "combinerParameters")
      private CombinerParametersType combinerParameters;
      @XmlElement(name = "Target", required = true)
      private TargetType target;
      @XmlElements(

      { @XmlElement(name = "Rule", type = RuleType.class), @XmlElement(name = "VariableDefinition", type = VariableDefinitionType.class), @XmlElement(name = "RuleCombinerParameters", type = RuleCombinerParametersType.class), @XmlElement(name = "CombinerParameters", type = CombinerParametersType.class) }

      )
      private List<Object> additionalInformation;
      @XmlElement(name = "Obligations")
      private ObligationsType obligations;
      @XmlAttribute(name = "PolicyId", required = true)
      @XmlSchemaType(name = "anyURI")
      private String policyId;
      @XmlAttribute(name = "Version")
      private String version;
      @XmlAttribute(name = "RuleCombiningAlgId", required = true)
      @XmlJavaTypeAdapter(RuleCombiningAlgorithmJAXBTypeAdapter.class)
      @XmlSchemaType(name = "anyURI")
      private AbstractRuleCombiningAlgorithm ruleCombiningAlg;

      ...

      The thing I want to talk about is the CombinerParameters element. This element is defined twice at different places.
      Now when I unmarshal an XML that contains two CombinerParameters elements at the two places the unmarshalling is incorrect.
      The second CombinerParameters element is saved into the CombinerParameters element and the first one disappears.
      I think the unmarshalling saves both elements into this element and the second overrides the first.
      I think the behavior should be that the first is saved into the CombinerParameters field and the second into the
      additionalInformation (Choice).

        Activity

        Hide
        kelvin-low added a comment -

        I having this issue as well. Daveboden, are you able to provide a workaround?

        Show
        kelvin-low added a comment - I having this issue as well. Daveboden, are you able to provide a workaround?
        Hide
        Iaroslav Savytskyi added a comment -

        Nice, thanks a lot.

        Show
        Iaroslav Savytskyi added a comment - Nice, thanks a lot.
        Hide
        daveboden added a comment -

        By the time the Unmarshaller is using a SAX parser to look at the <tradeId/> element, the handler has a map keyed on XML tag Name (namespace + element name) to use:

        StructureLoader.childElement(UnmarshallingContext$State, TagName) line: 248
        ChildLoader child = childUnmarshallers.get(arg.uri,arg.local);

        This only contains a single entry for <tradeId/>

        The map is built up when the JAXB context is created here:

        SingleElementLeafProperty.buildChildElementUnmarshallers line: 191
        handlers.put(tagName, new ChildLoader(l, null));

        This overwrites one tag name with another without warning. This line of code should probably check for the existence of the key in the map before overwriting it and at least log something at WARN level.

        I don't have any ideas at the moment on how to make an improvement to rectify this issue. Because it's a SAX parser (rather than a more complex grammar parser) and everything is keyed just tag Name, it's not going to be a small change. I'll post my test case and workaround.

        Show
        daveboden added a comment - By the time the Unmarshaller is using a SAX parser to look at the <tradeId/> element, the handler has a map keyed on XML tag Name (namespace + element name) to use: StructureLoader.childElement(UnmarshallingContext$State, TagName) line: 248 ChildLoader child = childUnmarshallers.get(arg.uri,arg.local); This only contains a single entry for <tradeId/> The map is built up when the JAXB context is created here: SingleElementLeafProperty.buildChildElementUnmarshallers line: 191 handlers.put(tagName, new ChildLoader(l, null)); This overwrites one tag name with another without warning. This line of code should probably check for the existence of the key in the map before overwriting it and at least log something at WARN level. I don't have any ideas at the moment on how to make an improvement to rectify this issue. Because it's a SAX parser (rather than a more complex grammar parser) and everything is keyed just tag Name, it's not going to be a small change. I'll post my test case and workaround.
        Hide
        daveboden added a comment - - edited

        I'm seeing a very similar, if not identical, issue with the FPML 5.4 schema. Please note that I'm using the latest (at time of writing) version of jaxb-impl, 2.2.7-b41, both to compile the bindings and at runtime. Here's the relevant extract from fpml-doc-5.4.xsd :

        <xsd:complexType name="TradeIdentifier">
          <xsd:annotation>
            <xsd:documentation xml:lang="en">
            A type defining a trade identifier issued
            by the indicated party.
            </xsd:documentation>
          </xsd:annotation>
          <xsd:sequence>
            <xsd:choice>
              <xsd:sequence>
                <xsd:element name="issuer" type="IssuerId"></xsd:element>
                <xsd:element name="tradeId" type="TradeId"></xsd:element>
              </xsd:sequence>
              <xsd:sequence>
                <xsd:group ref="PartyAndAccountReferences.model">
                  <xsd:annotation>
                    <xsd:documentation xml:lang="en">
                    A pointer style reference to a party identifier and optionally
                    an account identifier defined elsewhere in the document.
                    The party referenced has allocated the trade identifier.
                    </xsd:documentation>
                  </xsd:annotation>
                </xsd:group>
                <xsd:choice maxOccurs="unbounded">
                  <xsd:element name="tradeId" type="TradeId"></xsd:element>
                  <xsd:element name="versionedTradeId" type="VersionedTradeId">
                    <xsd:annotation>
                      <xsd:documentation xml:lang="en">
                      A trade identifier accompanied by a version number.
                      In regulatory reporting views, this should be avoided
                      except for internal mnessaging.
                      </xsd:documentation>
                    </xsd:annotation>
                  </xsd:element>
                </xsd:choice>
              </xsd:sequence>
            </xsd:choice>
          </xsd:sequence>
          <xsd:attribute name="id" type="xsd:ID" />
        </xsd:complexType>
        

        There are essentially two totally separate definitions of elements that have the same name. <tradeId/>. However, when JAXB parses the corresponding XML it treats all <tradeId/> values as they're the first definition. This results in multiple <tradeId/> values that are part of the second definition (that allows multiple instances of the element) being overwritten as the attribute. The JAXB parse loses the values of all but the last element in the incoming XML.

        In this example, <partyTradeIdentifier> is of type TradeIdentifier (well, actually it's a subclass called PartyTradeIdentifier but that is not relevant at this stage):

        <tradeReferenceInformation>
            <partyTradeIdentifier>
                <partyReference href="MSERV_BANK123"/>
                <tradeId tradeIdScheme="TradeRefNbr">1212H88885</tradeId>
                <tradeId tradeIdScheme="MatchID">MSE21212.026</tradeId>
                <tradeId tradeIdScheme="ClearerID">667789</tradeId>
            </partyTradeIdentifier>
            <partyTradeIdentifier>
                <issuer issuerIdScheme="http://www.fpml.org/coding-scheme/external/cftc/issuer-identifier">178921368077</issuer>
                <tradeId tradeIdScheme="http://www.fpml.org/coding-scheme/external/unique-transaction-identifier">AAB152121</tradeId>
            </partyTradeIdentifier>
        </tradeReferenceInformation>
        

        The result of the JAXB parse is two TradeIdentifier beans. The second one has the tradeId correctly filled in as "AAB152121". Unfortunately the first one doesn't have all 3 values in a list, it just retains the "667789" 3rd and final value as the tradeId. The object that represents the choice maxOccurs="unbounded", which is List<Object> getTradeIdOrVersionedTradeId contains NULL.

        I'll work on a simplified test case.

        Show
        daveboden added a comment - - edited I'm seeing a very similar, if not identical, issue with the FPML 5.4 schema. Please note that I'm using the latest (at time of writing) version of jaxb-impl, 2.2.7-b41, both to compile the bindings and at runtime. Here's the relevant extract from fpml-doc-5.4.xsd : <xsd:complexType name= "TradeIdentifier" > <xsd:annotation> <xsd:documentation xml:lang= "en" > A type defining a trade identifier issued by the indicated party. </xsd:documentation> </xsd:annotation> <xsd:sequence> <xsd:choice> <xsd:sequence> <xsd:element name= "issuer" type= "IssuerId" > </xsd:element> <xsd:element name= "tradeId" type= "TradeId" > </xsd:element> </xsd:sequence> <xsd:sequence> <xsd:group ref= "PartyAndAccountReferences.model" > <xsd:annotation> <xsd:documentation xml:lang= "en" > A pointer style reference to a party identifier and optionally an account identifier defined elsewhere in the document. The party referenced has allocated the trade identifier. </xsd:documentation> </xsd:annotation> </xsd:group> <xsd:choice maxOccurs= "unbounded" > <xsd:element name= "tradeId" type= "TradeId" > </xsd:element> <xsd:element name= "versionedTradeId" type= "VersionedTradeId" > <xsd:annotation> <xsd:documentation xml:lang= "en" > A trade identifier accompanied by a version number. In regulatory reporting views, this should be avoided except for internal mnessaging. </xsd:documentation> </xsd:annotation> </xsd:element> </xsd:choice> </xsd:sequence> </xsd:choice> </xsd:sequence> <xsd:attribute name= "id" type= "xsd:ID" /> </xsd:complexType> There are essentially two totally separate definitions of elements that have the same name. <tradeId/>. However, when JAXB parses the corresponding XML it treats all <tradeId/> values as they're the first definition. This results in multiple <tradeId/> values that are part of the second definition (that allows multiple instances of the element) being overwritten as the attribute. The JAXB parse loses the values of all but the last element in the incoming XML. In this example, <partyTradeIdentifier> is of type TradeIdentifier (well, actually it's a subclass called PartyTradeIdentifier but that is not relevant at this stage): <tradeReferenceInformation> <partyTradeIdentifier> <partyReference href= "MSERV_BANK123" /> <tradeId tradeIdScheme= "TradeRefNbr" > 1212H88885 </tradeId> <tradeId tradeIdScheme= "MatchID" > MSE21212.026 </tradeId> <tradeId tradeIdScheme= "ClearerID" > 667789 </tradeId> </partyTradeIdentifier> <partyTradeIdentifier> <issuer issuerIdScheme= "http://www.fpml.org/coding-scheme/external/cftc/issuer-identifier" > 178921368077 </issuer> <tradeId tradeIdScheme= "http://www.fpml.org/coding-scheme/external/unique-transaction-identifier" > AAB152121 </tradeId> </partyTradeIdentifier> </tradeReferenceInformation> The result of the JAXB parse is two TradeIdentifier beans. The second one has the tradeId correctly filled in as "AAB152121". Unfortunately the first one doesn't have all 3 values in a list, it just retains the "667789" 3rd and final value as the tradeId. The object that represents the choice maxOccurs="unbounded", which is List<Object> getTradeIdOrVersionedTradeId contains NULL. I'll work on a simplified test case.
        Hide
        Pavel Bucek added a comment -

        thanks for reporting; too late for 2.2.2

        metro2.1-waived

        Show
        Pavel Bucek added a comment - thanks for reporting; too late for 2.2.2 metro2.1-waived

          People

          • Assignee:
            Iaroslav Savytskyi
            Reporter:
            fhuonder
          • Votes:
            2 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: