You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by "Glanville, Jay Dickon (JIRA)" <ax...@ws.apache.org> on 2005/11/01 14:46:55 UTC
[jira] Created: (AXIS-2279) Doc/Wrapped service turns a non-null, empty array into a null object
Doc/Wrapped service turns a non-null, empty array into a null object
--------------------------------------------------------------------
Key: AXIS-2279
URL: http://issues.apache.org/jira/browse/AXIS-2279
Project: Apache Axis
Type: Bug
Components: Serialization/Deserialization
Versions: 1.3
Reporter: Glanville, Jay Dickon
I have a service in which a non-null, empty array is returned:
public XYZ[] getArray() throws AxisFault {
return new XYZ[ 0 ];
}
I then allow Axis to automatically generate the WSDL. With this WSDL, I use the WSDL2Java tool to generate the client side libraries.
When my client calls the getArray() operation, it doesn't receive a non-null, empty array. Instead, it receives a null object.
For example, if the client code was:
XYZ[] ret = binding.getArray()
if ( ret == null ) {
System.out.println( "null" );
} else {
System.out.println( ret.length );
}
then the output would be
null
The client should be receiving what the service gave it.
The service is a document/literal-wrapped encoded service. If I change the service to an RPC/encoded service, then everything works as expected (i.e.: the output of the client program would be "0").
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira
[jira] Commented: (AXIS-2279) Doc/Wrapped service turns a non-null, empty array into a null object
Posted by "Maurizio Mlt (JIRA)" <ax...@ws.apache.org>.
[ http://issues.apache.org/jira/browse/AXIS-2279?page=comments#action_12357132 ]
Maurizio Mlt commented on AXIS-2279:
------------------------------------
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 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...
> Doc/Wrapped service turns a non-null, empty array into a null object
> --------------------------------------------------------------------
>
> Key: AXIS-2279
> URL: http://issues.apache.org/jira/browse/AXIS-2279
> Project: Apache Axis
> Type: Bug
> Components: Serialization/Deserialization
> Versions: 1.3
> Reporter: Glanville, Jay Dickon
>
> I have a service in which a non-null, empty array is returned:
> public XYZ[] getArray() throws AxisFault {
> return new XYZ[ 0 ];
> }
> I then allow Axis to automatically generate the WSDL. With this WSDL, I use the WSDL2Java tool to generate the client side libraries.
> When my client calls the getArray() operation, it doesn't receive a non-null, empty array. Instead, it receives a null object.
> For example, if the client code was:
> XYZ[] ret = binding.getArray()
> if ( ret == null ) {
> System.out.println( "null" );
> } else {
> System.out.println( ret.length );
> }
> then the output would be
> null
> The client should be receiving what the service gave it.
> The service is a document/literal-wrapped encoded service. If I change the service to an RPC/encoded service, then everything works as expected (i.e.: the output of the client program would be "0").
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira