You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-user@axis.apache.org by Brian Fitzpatrick <bm...@opentext.com> on 2006/07/10 19:50:09 UTC

Nulls within arrays

I'm working with a complexType that contains various arrays. It appears
that Axis 1.4 is not properly handling null items that occur within the
array. Instead of using the nillable="true/false" setting on the
<element> that defines the Array, it is determining whether to send
xsi:nil based on whether the complexType that contains the arrays, can
be omitted (minOccurs=0).  So, it doesn't seem to matter the settings on
the <element> tag of the arrays, only whether the enclosing complexType
can be omitted.

 

This causes several problems, especially with .NET interoperability:

 

(Axis client to .NET server) .NET will define the parameters of a
service method as omittable (minOccurs=0), so an Axis client will never
send xsi:nil to the .NET server, which throws off the size of the array,
since the null array item is just omitted.

 

(.NET client to .NET server) When the same service is used from a .NET
client, it will correctly use the nillable="true/false" setting of the
array to determine whether to send xsi:nil or omit the array item. So a
single complexType could have multiple arrays, in which some of them are
allowed to be null and others are not

 

(Axis client to Axis server) Axis will define the parameters of a
service method as required (minOccurs=1), so an Axis client will ALWAYS
send xsi:nil when an array item is null.  It does not look at the
<element> declaration for that array to determine if it should be
sending xsi:nil or omitting the item, based on the nillable="true/false"
setting. So an Axis client will sometimes be sending xsi:nil when it
should not be.

 

>From my interpretation, it should be looking at the
nillable="true/false" setting on the <element> tag that defines the
array to determine whether to send the xsi:nil or not.  Is this a known
problem?  Should I submit a bug report?  Thanks.

 

 

Detailed info:

 

I created a very simple .NET web service that defined a complexType
named "TestObject". TestObject contains one string array call
StringItems, which is set for nillable="true". The WSDL snippets that
follow were generated by .NET.

      <s:complexType name="TestObject">

        <s:sequence>

          <s:element minOccurs="0" maxOccurs="1" name="StringItems"
type="tns:ArrayOfString" />

        </s:sequence>

      </s:complexType>

      <s:complexType name="ArrayOfString">

        <s:sequence>

          <s:element minOccurs="0" maxOccurs="unbounded" name="string"
nillable="true" type="s:string" />

        </s:sequence>

      </s:complexType>

 

I created one method to send and receive this type:

      <s:element name="SendObjectWithArray">

        <s:complexType>

          <s:sequence>

            <s:element minOccurs="0" maxOccurs="1" name="test"
type="tns:TestObject" />

          </s:sequence>

        </s:complexType>

      </s:element>

 

I created an Axis client and a .NET client to call this service. I
called the service with the following array:

obj.StringItems = new string[] { "first", "second", null, "fourth (after
null)", "fifth" };

 

The axis client omitted the null parameter in the request.  However,
when a null was sent back from the server, it correctly preserved it in
the return array.

 

The .NET client sent xsi:nil for the null parameter and correctly
preserved the return xsi:nil as a null in the return array.

 

The full WSDL:

<?xml version="1.0" encoding="utf-8"?>

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="urn:test"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
targetNamespace="urn:test"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

  <wsdl:types>

    <s:schema elementFormDefault="qualified" targetNamespace="urn:test">

      <s:element name="SendObjectWithArray">

        <s:complexType>

          <s:sequence>

            <s:element minOccurs="0" maxOccurs="1" name="test"
type="tns:TestObject" />

          </s:sequence>

        </s:complexType>

 

      </s:element>

      <s:complexType name="TestObject">

        <s:sequence>

          <s:element minOccurs="0" maxOccurs="1" name="StringItems"
type="tns:ArrayOfString" />

        </s:sequence>

      </s:complexType>

      <s:complexType name="ArrayOfString">

        <s:sequence>

          <s:element minOccurs="0" maxOccurs="unbounded" name="string"
nillable="true" type="s:string" />

 

        </s:sequence>

      </s:complexType>

      <s:element name="SendObjectWithArrayResponse">

        <s:complexType>

          <s:sequence>

            <s:element minOccurs="0" maxOccurs="1"
name="SendObjectWithArrayResult" type="tns:TestObject" />

          </s:sequence>

        </s:complexType>

      </s:element>

 

    </s:schema>

  </wsdl:types>

  <wsdl:message name="SendObjectWithArraySoapIn">

    <wsdl:part name="parameters" element="tns:SendObjectWithArray" />

  </wsdl:message>

  <wsdl:message name="SendObjectWithArraySoapOut">

    <wsdl:part name="parameters"
element="tns:SendObjectWithArrayResponse" />

  </wsdl:message>

  <wsdl:portType name="ArrayTestSoap">

 

    <wsdl:operation name="SendObjectWithArray">

      <wsdl:input message="tns:SendObjectWithArraySoapIn" />

      <wsdl:output message="tns:SendObjectWithArraySoapOut" />

    </wsdl:operation>

  </wsdl:portType>

  <wsdl:binding name="ArrayTestSoap" type="tns:ArrayTestSoap">

    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />

    <wsdl:operation name="SendObjectWithArray">

      <soap:operation soapAction="urn:test/SendObjectWithArray"
style="document" />

 

      <wsdl:input>

        <soap:body use="literal" />

      </wsdl:input>

      <wsdl:output>

        <soap:body use="literal" />

      </wsdl:output>

    </wsdl:operation>

  </wsdl:binding>

  <wsdl:binding name="ArrayTestSoap12" type="tns:ArrayTestSoap">

 

    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />

    <wsdl:operation name="SendObjectWithArray">

      <soap12:operation soapAction="urn:test/SendObjectWithArray"
style="document" />

      <wsdl:input>

        <soap12:body use="literal" />

      </wsdl:input>

      <wsdl:output>

        <soap12:body use="literal" />

      </wsdl:output>

 

    </wsdl:operation>

  </wsdl:binding>

  <wsdl:service name="ArrayTest">

    <wsdl:port name="ArrayTestSoap" binding="tns:ArrayTestSoap">

      <soap:address
location="http://localhost:1792/arraytest/ArrayTest.asmx" />

    </wsdl:port>

    <wsdl:port name="ArrayTestSoap12" binding="tns:ArrayTestSoap12">

      <soap12:address
location="http://localhost:1792/arraytest/ArrayTest.asmx" />

    </wsdl:port>

 

  </wsdl:service>

</wsdl:definitions>