I ran in to a problem today with Flex's SOAP encoding which I think
is a bug in the SOAP encoder.
It seems like whatever I did to call one of my webservice methods,
Flex would give me an error as it was encoding my request. The error
was something like the following:
TypeError: Error #1009: Cannot access a property or method of a null
object reference.
...
at mx.rpc::AbstractService/dispatchEvent()[C:\dev\enterprise_bali
\frameworks\mx\rpc\AbstractService.as:236]
at mx.rpc.soap.mxml::WebService/dispatchEvent()[C:\dev
\enterprise_bali\frameworks\mx\rpc\soap\mxml\WebService.as:226]
at mx.rpc::AbstractOperation/http://www.adobe.com/2006/flex/mx/
internal::dispatchRpcEvent()[C:\dev\enterprise_bali\frameworks\mx\rpc
\AbstractOperation.as:183]
at mx.rpc.soap::Operation/http://www.adobe.com/2006/flex/mx/
internal::invokePendingCall()[C:\dev\enterprise_bali\frameworks\mx\rpc
\soap\Operation.as:584]
at mx.rpc.soap::Operation/send()[C:\dev\enterprise_bali\frameworks\mx
\rpc\soap\Operation.as:492]
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.rpc.soap.mxml::Operation/send()[C:\dev\enterprise_bali
\frameworks\mx\rpc\soap\mxml\Operation.as:140]
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.rpc::AbstractService/http://www.adobe.com/2006/actionscript/
flash/proxy::callProperty()[C:\dev\enterprise_bali\frameworks\mx\rpc
\AbstractService.as:287]
My program would always stop right at the encoding process. The trace
stopped with these last lines:
...
19:41:19.740 [DEBUG] mx.rpc.soap.SOAPEncoder Encoding SOAP request
envelope
19:41:19.745 [DEBUG] mx.rpc.soap.SOAPEncoder Encoding SOAP request body
After many attempts to try to get my very simple 1-string request
encoded, I started looking in to the WSDL. Luckily I could control
the WSDL - in many webservice use cases, you can not.
From what I have been able to deduce, Flex's SOAP encoder will throw
the above error if the name of the webservice Operation - i.e.
"ListInterviews" - is not the same as the name of the message part
element, i.e. "ListInterviewsRequest".
As a more thorough example, consider this WSDL, which should be fully
valid (Oxygenxml and XmlSpy are both ok with it, and can generate
SOAP for it):
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://
schemas.xmlsoap.org/wsdl/" xmlns:tns="http://www.yourURI.com/
OfficeService" targetNamespace="http://www.yourURI.com/OfficeService">
<wsdl:types>
<s:schema targetNamespace="http://www.yourURI.com/OfficeService"
elementFormDefault="qualified">
<s:element name="ListInterviewsRequest">
<s:complexType>
<s:sequence>
<s:element name="Token" type="s:string"
minOccurs="1"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="ListInterviewsResponse">
<s:complexType>
<s:sequence>
<s:element name="InterviewList"
type="s:string" minOccurs="0"/>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="ListInterviewsSoapIn">
<wsdl:part name="parameters"
element="tns:ListInterviewsRequest"/>
</wsdl:message>
<wsdl:message name="ListInterviewsSoapOut">
<wsdl:part name="parameters"
element="tns:ListInterviewsResponse"/>
</wsdl:message>
<wsdl:portType name="OfficeServiceSoap">
<wsdl:operation name="ListInterviews">
<wsdl:input message="tns:ListInterviewsSoapIn"/>
<wsdl:output message="tns:ListInterviewsSoapOut"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="OfficeServiceSoap" type="tns:OfficeServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="ListInterviews">
<soap:operation soapAction="http://www.yourURI.com/OfficeService/
ListInterviews" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="OfficeService">
<wsdl:port name="OfficeServiceSoap"
binding="tns:OfficeServiceSoap">
<soap:address location="http://www.yourURI.com/OfficeService/
Implementation.page"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
A consumer of that webservice should be able to form a SOAP request
as follows:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/
envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ListInterviewsRequest
xmlns="http://www.yourURI.com/OfficeService">
<Token>STRING</Token>
</ListInterviewsRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
So when Flex tries to generate that response, it throws the above
error. As far as I can tell, it throws the error no matter how you
call the webservice operation (and I called it every which way I
could with Flex!).
However, when the wsdl is modified so:
<s:element name="ListInterviewsRequest"> becomes <s:element
name="ListInterviews">
and
<wsdl:part name="parameters" element="tns:ListInterviewsRequest"/>
becomes <wsdl:part name="parameters" element="tns:ListInterviews"/>
Flex can encode the SOAP.
Hopefully Adobe can get that fixed up, and people who are banging
their head against a wall can change their WSDL (hopefully it is
their own WSDL they're using) so the body element is the same as the
operation name.
-graphex