Feb 20: SOAP Kills
So I am working on a new assignment at work yesterday, should be a pretty simple task I think. I am consuming a SOAP service to get some simple data. Little did I know that it was such a pain to work with .Net when you are using the PHP SOAP extension. I started out with the following WSDL (just a portion that I wanted to work with is listed).
So I write up a quick test script to grab that WSDL and try to run a method on it. It looked something like this:
Easy-peasy, I have working with PHP driven SOAP services a bunch of times before so I could pretty much write that off the top of my head. So I run the code and I get a SoapFault saying that the Content-type is text/xml when it was expecting application/soap+xml. So I Google around and find that I have to specify the soap version 1.2 in order to get the correct Content-type. So I make the following change to $clientOptions:
Nice, that error is fixed. But Now I have another SoapFault: "The SOAP action specified on the message, '', does not match the HTTP SOAP Action. Google again. This time it looks like the PHP soap client is not able to deal with WSHTTP binding and must use the basicHTTP binding. I am not authenticating for this SOAP service, so I am not sure why it even matters. Luckily, the WSDL tells me that I have basicHTTP bindings available. When I try to use the basic data source though, I get another SoapFault "Action /basic is not defined". So then I email the provider of the feed to make sure their basic binding is configured correctly and working. They make some changes and end up dropping the WSHTTP binding completely from the WSDL. Sweet, that error is fixed.
Except that I am getting another SoapFault, fortunately for me I have run across it aready in my little adventure. It is now complaining that the Content-type application/soap+xml is incorrect as it was expecting text/xml. Seriously! So I go and remove the soap_version element from the $clientOptions array. Awesome, that was an easy one to fix!
But now I have another SoapFault: "Object reference not set to an instance of an object.". Google again. This is where things get really annoying. First of all, the SoapFault error message is ridiculously cryptic. I find all kinds of forum posts and comments in the PHP manual about how you are supposed to pass parameters into the action method on your client. Here are some of the different versions that I tried:
No good.
No good.
No good.
No good. Then I tried adding 'classmap' => array('ListByCode', 'ListByCodeRequest') to the $clientOptions array. That didn't work either. Please bear in mind that these changes may appear to be the flapping around of a dying fish, but I assure you that they each involved several minutes of Google research. I will admit though that by this point I was feeling fairly desperate. I decided to go get a copy of soapUI to see if maybe the feed itself wasn't working. I import the WSDL click on LIST and hit run. Bam! Results are returned immediately. I calmly stand up and leave my office before I bring violence upon my computer.
15 minutes pass
Okay, so I return to me desk and decide to look ONLY at the requests I was making and try to get them to match the ones created by soapUI. Here's what soapUI was doing:
And here is what I was producing:
So obviously my parameters where not being passed in. I tried making the following change:
Which results in this request:
Snap! I am getting a different SoapFault saying that param1 is basically an unknown parameter. I proceed to try several versions of nested arrays and finally give up after this one:
You see I am back to the whole "Object reference not set to an instance of an object." SoapFault. It is then that lightening comes down and strikes my brain. This is the final (and working) version of the script:
So, hopefully this little saga will help others that are in danger of having a very long day as I had escape their fate. On a side note, whenever I am doing this kind of research on Google I always wish that there was an option to specify how old the results should be. I have the option Search: [ ] the web [ ] page from Canada, but I'd really like to see [ ] from this month [ ] from this year [ ] any time as options as well. A blog post mentioning PHP and SOAP from 2003 is probably not going to be helpful. Although sometimes I can see the date it was written before I click, not seeing the entry at all would be great.
So I write up a quick test script to grab that WSDL and try to run a method on it. It looked something like this:
Easy-peasy, I have working with PHP driven SOAP services a bunch of times before so I could pretty much write that off the top of my head. So I run the code and I get a SoapFault saying that the Content-type is text/xml when it was expecting application/soap+xml. So I Google around and find that I have to specify the soap version 1.2 in order to get the correct Content-type. So I make the following change to $clientOptions:
Nice, that error is fixed. But Now I have another SoapFault: "The SOAP action specified on the message, '', does not match the HTTP SOAP Action. Google again. This time it looks like the PHP soap client is not able to deal with WSHTTP binding and must use the basicHTTP binding. I am not authenticating for this SOAP service, so I am not sure why it even matters. Luckily, the WSDL tells me that I have basicHTTP bindings available. When I try to use the basic data source though, I get another SoapFault "Action /basic is not defined". So then I email the provider of the feed to make sure their basic binding is configured correctly and working. They make some changes and end up dropping the WSHTTP binding completely from the WSDL. Sweet, that error is fixed.
Except that I am getting another SoapFault, fortunately for me I have run across it aready in my little adventure. It is now complaining that the Content-type application/soap+xml is incorrect as it was expecting text/xml. Seriously! So I go and remove the soap_version element from the $clientOptions array. Awesome, that was an easy one to fix!
But now I have another SoapFault: "Object reference not set to an instance of an object.". Google again. This is where things get really annoying. First of all, the SoapFault error message is ridiculously cryptic. I find all kinds of forum posts and comments in the PHP manual about how you are supposed to pass parameters into the action method on your client. Here are some of the different versions that I tried:
No good.
No good.
No good.
No good. Then I tried adding 'classmap' => array('ListByCode', 'ListByCodeRequest') to the $clientOptions array. That didn't work either. Please bear in mind that these changes may appear to be the flapping around of a dying fish, but I assure you that they each involved several minutes of Google research. I will admit though that by this point I was feeling fairly desperate. I decided to go get a copy of soapUI to see if maybe the feed itself wasn't working. I import the WSDL click on LIST and hit run. Bam! Results are returned immediately. I calmly stand up and leave my office before I bring violence upon my computer.
15 minutes pass
Okay, so I return to me desk and decide to look ONLY at the requests I was making and try to get them to match the ones created by soapUI. Here's what soapUI was doing:
And here is what I was producing:
So obviously my parameters where not being passed in. I tried making the following change:
Which results in this request:
Snap! I am getting a different SoapFault saying that param1 is basically an unknown parameter. I proceed to try several versions of nested arrays and finally give up after this one:
You see I am back to the whole "Object reference not set to an instance of an object." SoapFault. It is then that lightening comes down and strikes my brain. This is the final (and working) version of the script:
So, hopefully this little saga will help others that are in danger of having a very long day as I had escape their fate. On a side note, whenever I am doing this kind of research on Google I always wish that there was an option to specify how old the results should be. I have the option Search: [ ] the web [ ] page from Canada, but I'd really like to see [ ] from this month [ ] from this year [ ] any time as options as well. A blog post mentioning PHP and SOAP from 2003 is probably not going to be helpful. Although sometimes I can see the date it was written before I click, not seeing the entry at all would be great.
Trackbacks
Trackback specific URI for this entry
No Trackbacks
Comments
Display comments as
(Linear | Threaded)
#1 - Andy said:
2009-03-02 15:04 - (Reply)
well .. now I know why REST is becoming much more popular than SOAP.
#2 - Paul Allen said:
2009-07-28 08:55 - (Reply)
here's what you needed to make the php soap extension work:
$params = array();
$params['yourparamname'] = 'paramvalue';
$params['param2'] = 2; //next value
$results = $client->ListByCode(array('parameters'=>$params));
you could also try the other way to call the methods:
$client->__call('ListByCode',array('parameters'=>$params));