javaee / jaxb-v2

Other
211 stars 101 forks source link

Multiple element definition not read correctly #793

Open glassfishrobot opened 13 years ago

glassfishrobot commented 13 years ago

Hi all,

I have the following schema complex type:

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 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).

Environment

Operating System: All Platform: All

Affected Versions

[2.2.1]

glassfishrobot commented 13 years ago

Reported by fhuonder

glassfishrobot commented 13 years ago

@pavelbucek said: thanks for reporting; too late for 2.2.2

metro2.1-waived

glassfishrobot commented 11 years ago

daveboden said: 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. . However, when JAXB parses the corresponding XML it treats all values as they're the first definition. This results in multiple 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, 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 getTradeIdOrVersionedTradeId contains NULL.

I'll work on a simplified test case.

glassfishrobot commented 11 years ago

daveboden said: By the time the Unmarshaller is using a SAX parser to look at the 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

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.

glassfishrobot commented 11 years ago

yaroska said: Nice, thanks a lot.

glassfishrobot commented 10 years ago

kelvin-low said: I having this issue as well. Daveboden, are you able to provide a workaround?

glassfishrobot commented 13 years ago

Was assigned to yaroska

glassfishrobot commented 7 years ago

This issue was imported from java.net JIRA JAXB-793