Java – use of minOccurs=”0″ without nillable=”true” in SOAP

javanetsoapw3cwcf

I have received an XSD from a 3rd party supplier generated from a Java based system; which is to be used to create a SOAP endpoint for us to receive data transfers. Their XSD does not make any use of the nillable attribute defined within the W3C/XSD namespace, for example:

<xs:complexType name="Customer">
    <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="1" name="ID" type="xs:integer"/>
        <xs:element minOccurs="0" maxOccurs="1" name="TitleID" type="xs:integer"/>
        <xs:element minOccurs="0" maxOccurs="1" name="FirstName" type="xs:string"/>
        <xs:element minOccurs="0" maxOccurs="1" name="FamilyName" type="xs:string"/>
        <xs:element minOccurs="0" maxOccurs="1" name="PreviousName" type="xs:string"/>
        <xs:element minOccurs="0" maxOccurs="1" name="DateOfBirth" type="xs:date"/>
    </xs:sequence>
</xs:complexType>

When speaking to the supplier it was mentioned "where minOccurs="0" and their is no value, elements will be omitted".

When we use the XSD Schema Definition Tool to create classes; the classes are generated correctly with 2 exceptions: the DateOfBirth and TitleID properties are not nullable.

Unless nillable="true" is declared within the XSD for simple types, value types or not created as Nullable despite the minOccurs="0" configuration. After some research I feel this interpretation is correct given information in the following articles:

I have concluded from the above that minOccurs="0" is a definition that states the element within the XML is optional, but does not have any particular meaning. It is clear that within a SOAP message; to communicate no value for a particular element nill="true" should be used within an empty element.

When presenting this to our supplier; I have argued the missing nillable attributes leaves the XSD ambiguous and lacks intent when referenced to the standards, given than omitting elements does not state null, its only implied. The W3C states if a message needs to indicate an element is null, it should be explicitly stated. Their representative disagreed and argued that if there is no DateOfBirth (for example) they will remove the element for this in the SOAP message. They believe this is acceptable and conforms to the standards. From what I have read here, minOccurs/nillable have the same behavior in Java (maybe why they feel they don't have to use nillable attribute)

I know I can work around this but ultimately; it (potentially) has a significant increase on the amount of additional code required for the sake of our supplier not wanting to use the nill/nillable attribute in the XSD and SOAP message. I am building our SOAP API in WCF; upon deserialization I will have to check all the Specified properties that are generated to check for missing elements. This is because value types that are not not referenced in the xml message will be assigned their default values. Alternatively, I could go through the XSD and add them myself, which I feel is a bad idea. I will be changing their definitions and any new releases will require the same effort, which is currently every 3-6 months.

My questions are:

  • Do you agree with arguments made by me or the supplier? If so why?
  • Am I correct in my suggestion Java treats these configurations the same?
  • If I am wrong, is there a way I can tell .Net to create nullable types for minOccurs="0"?

Best Answer

Apache CXF uses the following rationale:

MinOccurs and Nillable

The default Aegis mapping is to assume that, since any Java object can be null, that the corresponding schema elements should have minOccurs of 0 and nillable of true. There are properties on the mappings to control this.

<mappings>
  <mapping>
    <property name='everpresentProperty' minOccurs='1' nillable='false'/>
 </mapping>
<mappings>

The W3C rationale is similar:

An [XML Schema 1.0], or other [XML 1.0] document containing an [XML Schema 1.0] element , exhibits the NillableElement pattern identified using the URI [RFC 3986] http://www.w3.org/2002/ws/databinding/patterns/6/09/NillableElement when the following [XPath 2.0] expression applied to a document or element node with a context node of //xs:schema results in an [XPath 2.0] node-set containing at least one node:

.//xs:element[@nillable = 'true' and not(@minOccurs = '0')]/ (@nillable)

The following example [XML Schema 1.0] extract illustrates the use of the NillableElement pattern within an [XML Schema 1.0] document [NillableElement]:

<xs:element name="nillableMiddleName" type="ex:NillableMiddleName" />
<xs:complexType name="NillableMiddleName">
  <xs:sequence>
    <xs:element name="firstName" type="xs:string" />
    <xs:element name="middleName" type="xs:string"  nillable="true" />
    <xs:element name="lastName" type="xs:string" />
  </xs:sequence>
</xs:complexType>

The following example [XML 1.0] element is valid against the above example [XML Schema 1.0] when included inside an instance document [NillableElement01]:

<ex:nillableMiddleName>
  <ex:firstName>Paul</ex:firstName>
  <ex:middleName xsi:nil="true"/>
  <ex:lastName>Downey</ex:lastName>
</ex:nillableMiddleName>

as is the following element when included in an instance document [NillableElement02]:

<ex:nillableMiddleName>
  <ex:firstName>Paul</ex:firstName>
  <ex:middleName>Sumner</ex:middleName>
  <ex:lastName>Downey</ex:lastName>
</ex:nillableMiddleName>

References

Related Topic