axis-java-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Maurizio Melato <mauri...@nice-italy.com>
Subject RE: Different behaviour for empty arrays between RPC and Doc/Wrapped?
Date Wed, 09 Nov 2005 13:07:11 GMT
This is due to the  WSDLs Axis generates when using RPC or Doc/Wrapped
styles.

In the RPC case arrays are wrapped in XMLschema complexType while
in the Doc/Wrapped case they are used  as simple repeated element  in
the method response message declaration

RPC)
  <wsdl:types>
    ...
    <complexType name="ArrayOf_tns2_XYZ">
     <sequence>
      <element maxOccurs="unbounded" minOccurs="0" name="item"
type="tns2:XYZ"/>
     </sequence>
    </complexType>
  </wsdl:types>
...
    <wsdl:message name="getArrayResponse">
       <wsdl:part name="getArrayReturn" type="impl:ArrayOf_tns2_XYZ"/>
    </wsdl:message>

Wrapped)
  <wsdl:types>
...
    <element name="getArrayResponse">
     <complexType>
      <sequence>
       <element maxOccurs="unbounded" name="getArrayReturn"
type="tns2:XYZ"/>
      </sequence>
     </complexType>
    </element>
  </wsdl:types>
...
    <wsdl:message name="getArrayResponse">
       <wsdl:part element="impl:getArrayResponse" name="parameters"/>
    </wsdl:message>


*** Unzipping my comment

I've expaned a little bit more your example:

------ class MyWebService.java - XYZ..java
public class MyWebService{
    public XYZ[] getArray(){
            return new XYZ[0];
    }
}
public class XYZ {
    private String name;
    private int value;

    public XYZ(){
            name="";
            value=0;
    }
    public void setName(String name){  this.name=name;  }
    public void setValue(int value){ this.value=value;}
    public String getName(){ return name; }
    public int getValue(){ return value; }
}
------

I've then generated RPC/literal  WSDL:  java -cp $AXISCLASSPATH:.
org.apache.axis.wsdl.Java2WSDL -o MyWebService.wsdl -l
http://127.0.0.1:8080/MyWebService -n urn:MyWebService
-pexample=urn:MyWebService -y RPC -u LITERAL MyWebService

------- MyWebService.wsdl.RPC-literal
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="urn:MyWebService"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="urn:MyWebService"
  xmlns:intf="urn:MyWebService" xmlns:tns2="http://DefaultNamespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="ht
tp://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--WSDL created by Apache Axis version: 1.3
Built on Oct 05, 2005 (05:23:37 EDT)-->
  <wsdl:types>
   <schema targetNamespace="http://DefaultNamespace"
xmlns="http://www.w3.org/2001/XMLSchema">
    <import namespace="urn:MyWebService"/>
    <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
    <complexType name="XYZ">
     <sequence>
      <element name="name" nillable="true" type="xsd:string"/>
      <element name="value" type="xsd:int"/>
     </sequence>
    </complexType>
   </schema>
   <schema targetNamespace="urn:MyWebService"
xmlns="http://www.w3.org/2001/XMLSchema">
    <import namespace="http://DefaultNamespace"/>
    <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
    <complexType name="ArrayOf_tns2_XYZ">
     <sequence>
      <element maxOccurs="unbounded" minOccurs="0" name="item"
type="tns2:XYZ"/>
     </sequence>
    </complexType>
   </schema>
  </wsdl:types>

    <wsdl:message name="getArrayRequest">
    </wsdl:message>
    <wsdl:message name="getArrayResponse">
       <wsdl:part name="getArrayReturn" type="impl:ArrayOf_tns2_XYZ"/>
    </wsdl:message>

    <wsdl:portType name="MyWebService">
       <wsdl:operation name="getArray">
          <wsdl:input message="impl:getArrayRequest"
name="getArrayRequest"/>
          <wsdl:output message="impl:getArrayResponse"
name="getArrayResponse"/>
       </wsdl:operation>
    </wsdl:portType>

    <wsdl:binding name="MyWebServiceSoapBinding" type="impl:MyWebService">
       <wsdlsoap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
       <wsdl:operation name="getArray">
          <wsdlsoap:operation soapAction=""/>
          <wsdl:input name="getArrayRequest">
             <wsdlsoap:body namespace="urn:MyWebService" use="literal"/>
          </wsdl:input>
          <wsdl:output name="getArrayResponse">
             <wsdlsoap:body namespace="urn:MyWebService" use="literal"/>
          </wsdl:output>
       </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="MyWebServiceService">
       <wsdl:port binding="impl:MyWebServiceSoapBinding"
name="MyWebService">
          <wsdlsoap:address location="http://127.0.0.1:8080/MyWebService"/>
       </wsdl:port>
    </wsdl:service>

</wsdl:definitions>
-------

In this case note that Axis wraps the array of XYZ into an XML-schema
complexType and use it as the return type of the getArray() method.
    <wsdl:message name="getArrayResponse">
       <wsdl:part name="getArrayReturn" type="impl:ArrayOf_tns2_XYZ"/>
    </wsdl:message>

where ArrayOf_tns2_XYZ is
    <complexType name="ArrayOf_tns2_XYZ">
     <sequence>
      <element maxOccurs="unbounded" minOccurs="0" name="item"
type="tns2:XYZ"/>
     </sequence>
    </complexType>

In this case an array of  0 elements is correctly managed by Axis
Serializer/Deserializer.


****** And there was evening, and there was morning...


I've then generated WRAPPED WSDL:
java -cp $AXISCLASSPATH:. org.apache.axis.wsdl.Java2WSDL -o
MyWebService.wsdl -l http://127.0.0.1:8080/MyWebService -n
urn:MyWebService -pexample=urn:MyWebService -y WRAPPED MyWebService

------ MyWebService.wsdl.WRAPPED
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="urn:MyWebService"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="urn:MyWebService"
  xmlns:intf="urn:MyWebService" xmlns:tns2="http://DefaultNamespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="ht
tp://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--WSDL created by Apache Axis version: 1.3
Built on Oct 05, 2005 (05:23:37 EDT)-->

  <wsdl:types>
   <schema elementFormDefault="qualified"
targetNamespace="urn:MyWebService" xmlns="http://www.w3.org/2001/XMLSchema">
    <import namespace="http://DefaultNamespace"/>
    <element name="getArray">
     <complexType/>
    </element>
    <element name="getArrayResponse">
     <complexType>
      <sequence>
       <element maxOccurs="unbounded" name="getArrayReturn"
type="tns2:XYZ"/>
      </sequence>
     </complexType>
    </element>
   </schema>
   <schema elementFormDefault="qualified"
targetNamespace="http://DefaultNamespace"
xmlns="http://www.w3.org/2001/XMLSchema">
    <complexType name="XYZ">
     <sequence>
      <element name="name" nillable="true" type="xsd:string"/>
      <element name="value" type="xsd:int"/>
     </sequence>
    </complexType>
   </schema>
  </wsdl:types>

    <wsdl:message name="getArrayRequest">
       <wsdl:part element="impl:getArray" name="parameters"/>
    </wsdl:message>
    <wsdl:message name="getArrayResponse">
       <wsdl:part element="impl:getArrayResponse" name="parameters"/>
    </wsdl:message>

    <wsdl:portType name="MyWebService">
       <wsdl:operation name="getArray">
          <wsdl:input message="impl:getArrayRequest"
name="getArrayRequest"/>
          <wsdl:output message="impl:getArrayResponse"
name="getArrayResponse"/>
       </wsdl:operation>
    </wsdl:portType>

    <wsdl:binding name="MyWebServiceSoapBinding" type="impl:MyWebService">
       <wsdlsoap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
       <wsdl:operation name="getArray">
          <wsdlsoap:operation soapAction=""/>
          <wsdl:input name="getArrayRequest">
             <wsdlsoap:body use="literal"/>
          </wsdl:input>
          <wsdl:output name="getArrayResponse">
             <wsdlsoap:body use="literal"/>
          </wsdl:output>
       </wsdl:operation>
    </wsdl:binding>

    <wsdl:service name="MyWebServiceService">
       <wsdl:port binding="impl:MyWebServiceSoapBinding"
name="MyWebService">
          <wsdlsoap:address location="http://127.0.0.1:8080/MyWebService"/>
       </wsdl:port>
    </wsdl:service>
</wsdl:definitions>
-------

As you can see in this case it doesn't wrap the Array in a complexType
as in the RPC literal case (as I'd expect...) but it
leaves it as a repeated element in the getArray response element:
    <element name="getArrayResponse">
     <complexType>
      <sequence>
       <element maxOccurs="unbounded" name="getArrayReturn"
type="tns2:XYZ"/>
      </sequence>
     </complexType>
    </element>

In this case you get a NullPointerException if a 0 elements array is sent.

Note that this happens also if you modify  line <element
maxOccurs="unbounded" name="getArrayReturn" type="tns2:XYZ"/> as
<element maxOccurs="unbounded" minOccurs="0" name="getArrayReturn"
type="tns2:XYZ"/>.


*** My poor solution

What I did in order to obtain a WRAPPED WSDL/SOAP solution working as I
would expect  was to manually edit  the (WRAPPED) WSDL file wrapping the
array in a complexType:
    <element name="getArrayResponse">
     <complexType>
      <sequence>
       <element name="getArrayReturn" type="tns2:ArrayOfXYZ"/>
      </sequence>
     </complexType>
    </element>
...
    <complexType name="ArrayOfXYZ">
     <sequence>
      <element maxOccurs="unbounded" minOccurs="0" name="item"
type="tns2:XYZ"/>
     </sequence>
    </complexType>

-
*** Concluding...

The same problem and solution would apply also to arrays passed  as
arguments of methods.


Is it a bug ?
Is it an error to assume Axis should wrap arrays when used as
return/argument  types  in  methods?
Is there a way to force Axis to wrap arrays anyway?

Personally I choose to work in RPC/literal mode in order to avoid the
burden of  manually editing the WSDL doc for fufure evolution and
re-generations...



Mime
View raw message