I was reviewing a pull request which integrates an existing app with an external SOAP payment gateway. the gateway looks very simple, given a request like:

<collectMoney>
    <fromAccount>111</fromAccount>
    <amount>999<amount>
</collectMoney>
<more-details>...</more-details>

the payment gateway returns:

<result>
    <status>success</status>
</result>

it works fine when I test it with my HTTP client.

by the WSDL shared by the payment gateway, fromAccount and amount must keep in sequence. however, I found an template inside the pull request: (sequence is different)

<collectMoney>
    <amount><amount>
    <fromAccount></fromAccount>
</collectMoney>
<more-details>...</more-details>

this means the app actually is generating an invalid XML request? How does this work?

it’s good to see that an app just works, but why??

I digged into the source code, and this is how it works: create CollectMoney(the class generated by XSD) -> render a XML using the template -> JAXB unmashaller -> CollectMoney instance -> Send to payment gateway via Apache CXF

I enabled apache CXF loggers to print the outbound/inbound messages, the log shows that the app managed to send out correct sequence! what kind of magic is this?

it’s the JAXB unmarshaller:

// copied from JAXB Unmarshaller.java
 * Since unmarshalling invalid XML content is defined in JAXB 2.0,
 * the Unmarshaller default validation event handler was made more lenient
 * than in JAXB 1.0.  When schema-derived code generated
 * by JAXB 1.0 binding compiler is registered with {@link JAXBContext},
 * the default unmarshal validation handler is
 * {@link javax.xml.bind.helpers.DefaultValidationEventHandler} and it
 * terminates the marshal  operation after encountering either a fatal error or an error.
 * For a JAXB 2.0 client application, there is no explicitly defined default
 * validation handler and the default event handling only
 * terminates the unmarshal operation after encountering a fatal error.

what is an error by the definition of W3C?

//copied from org.xml.ErrorHandler.java
This corresponds to the definition of "error" in section 1.2
 * of the W3C XML 1.0 Recommendation.  For example, a validating
 * parser would use this callback to report the violation of a
 * validity constraint.  The default behaviour is to take no
 * action.

https://www.w3.org/TR/xml/#sec-terminology show the error:

[Definition: A violation of the rules of this specification; results are undefined. Unless otherwise specified, failure to observe a prescription of this specification indicated by one of the keywords must, required, must not, shall and shall not is an error. Conforming software may detect and report an error and may recover from it.]

and it also mentions that a seq:

content particles occurring in a sequence list must each appear in the element content in the order given in the list.

so incorrect sequence is an error and by default JAXB 2.0 will continue to process it.

in my app’s case, an invalid XML request get unmarshalled to java instance, and then the instance gets ‘marshalled’ to an valid XML and then send to the payment gateway.

Conclusion

by definition, sequence in a ‘sequence’ does matter. however in the context of unmarshalling, it depends on how does an XML document get unmarshalled.

Abstraction leaks, the unmarshalling layer doesn’t add much value, but brings unnecessary confusion by leaking incorrect info, the app could directly use the classes generated by the WSDL/XSD.