{"id":267,"date":"2007-02-24T09:18:14","date_gmt":"2007-02-24T13:18:14","guid":{"rendered":"http:\/\/www.dr-chuck.com\/wordpress\/?p=267"},"modified":"2011-12-17T12:22:05","modified_gmt":"2011-12-17T16:22:05","slug":"nusoap-chucks-experience","status":"publish","type":"post","link":"https:\/\/www.dr-chuck.com\/csev-blog\/2007\/02\/nusoap-chucks-experience\/","title":{"rendered":"NUSOAP &#8211; Chuck&#8217;s Experience"},"content":{"rendered":"<p>In my quest to produce an IMS Tool Interoperability Endpoint which requires a SOAP Server in PHP that handles the complex WSDL for IMS Tool Interoperability &#8211; I encountered NUSOAP.  I must point out that I have never used nusoap until the last seven days &#8211; so I am *not an* expert.<br \/>\nBut my general opinion is that nusoap is an awsome product &#8211; but poorly documented and not able to handle complex WSDL very well.  It is like they did a superb job (I like the coding style of nusoap &#8211; the debugging feature is AWESOME) and built until it supported the WSDL that the nusoap folks had to work with and then stopped.<br \/>\nSo most of my experience is getting nusoap to handle things that it did not handle out of the box.<br \/>\nI am happy to provide patches to the nusoap folks &#8211; but I am guessing that my inexperience with nusoap means that my patches would be architecturally &#8220;inelegant&#8221; and not good with the philosophy of nusoap &#8211; who knows.  I may post a message to the nusoap dev list and watch the beatings begin.<br \/>\nThe source is here (warning &#8211; this has lots of extra debugging code that I added to figure out the internals of nusoap operation &#8211; which I left in):<br \/>\nhttp:\/\/www-personal.umich.edu\/~csev\/sakai\/imsti\/<br \/>\nYou can see the stuff online at:<br \/>\nhttp:\/\/www.sakaiproject.org\/imsti-test<br \/>\nAt the end of the day, it is no wonder that PHP folks really prefer REST.  I was told that perl is better at handling SOAP &#8211; I would be curious.  Paricularly because I would *love* to have a sample IMS TI tool in perl &#8211; but since I HATE the perl language this is not likely to be something that I would do.<br \/>\nMaybe my next foray will be trying to see if Ruby is better than PHP on SOAP parsing of complex and abstract types.<\/p>\n<p><!--more--><br \/>\nWorking with complex SOAP is a pain in PHP &#8211; I used nusoap because it seemed to be a good place to start. My verison of nusoap is modified in two ways.  I am not exactly sure if these modifications are right so folks should feel free to disagree with my mods or tell me that I am confused w.r.t SOAP.<br \/>\nSupport for Multi-Part Messages<br \/>\nIt does not appear that nusoap client handles SOAP of the following form:<br \/>\n&lt;SOAP-ENV:Body><br \/>\n&lt;ProxyToolLaunchResponse><br \/>\n&lt;LaunchDirective><br \/>\n&lt;PerformRedirectAction><br \/>\nhttp:\/\/127.0.0.1:80\/~csev\/nusoap\/samples\/LMSTool.php?session=6<br \/>\n&lt;\/PerformRedirectAction><br \/>\n&lt;\/LaunchDirective><br \/>\n&lt;\/ProxyToolLaunchResponse><br \/>\n&lt;imsx_syncResponseHeaderInfo><br \/>\n&lt;imsx_version>1.0&lt;\/imsx_version><br \/>\n&lt;\/imsx_syncResponseHeaderInfo><br \/>\n&lt;\/SOAP-ENV:Body><br \/>\nThe nusoap client parses it all and gets it all right and then only returns the first part.  I added code to lib\/nusoap.php at line 5953 to detect if there were multiple root documents after parsing and return an array of all of the root parts rather than just the first one.<br \/>\nLook for the string &#8220;theMessage&#8221;.<br \/>\nSupport for Abstract Types<br \/>\nThe IMS Tool Interoperability uses derived types and abstract classes.  The nusoap outbound serialization seems to have NO support for this.  Here is some sample WSDL:<br \/>\n&lt;xs:complexType name=&#8221;OutcomeProfile.Type&#8221; abstract=&#8221;true&#8221;><br \/>\n&lt;xs:annotation><br \/>\n&lt;xs:documentation><br \/>\n&lt;\/xs:documentation><br \/>\n&lt;\/xs:annotation><br \/>\n&lt;xs:sequence><br \/>\n&lt;\/xs:sequence><br \/>\n&lt;\/xs:complexType><br \/>\n&lt;xs:complexType name=&#8221;MinimalOutcomeProfile.Type&#8221;><br \/>\n&lt;xs:annotation><br \/>\n&lt;xs:documentation><br \/>\n&lt;\/xs:documentation><br \/>\n&lt;xs:annotation><br \/>\n&lt;xs:complexContent><br \/>\n&lt;xs:extension base=&#8221;tns:OutcomeProfile.Type&#8221;><br \/>\n&lt;xs:sequence><br \/>\n&lt;xs:element ref=&#8221;tns:LaunchProfile&#8221; minOccurs = &#8220;1&#8221; maxOccurs = &#8220;1&#8221;\/><br \/>\n&lt;xs:element ref=&#8221;tns:Grade&#8221; minOccurs = &#8220;1&#8221; maxOccurs = &#8220;1&#8221;\/><br \/>\n&lt;\/xs:sequence><br \/>\n&lt;\/xs:extension><br \/>\n&lt;\/xs:complexContent><br \/>\n&lt;\/xs:complexType><br \/>\n&lt;xs:element name=&#8221;OutcomeMessageRequest&#8221;><br \/>\n&lt;xs:complexType><br \/>\n&lt;xs:sequence><br \/>\n&lt;xs:element ref=&#8221;tns:OutcomeProfile&#8221;\/><br \/>\n&lt;\/xs:sequence><br \/>\n&lt;\/xs:complexType><br \/>\n&lt;\/xs:element><br \/>\nThe nusoap serializer wanted to serialize <b>OutcomeMessageRequest<\/b> so it went looking for <b>OutcomeProfile<\/b> &#8211; if you put this in your array labelled &#8220;OutcomeProfile&#8221; it would see the definition of the abstract class (OutcomeProfile.Type) and conclude there was nothing to serialize. If you labeled things as &#8220;MinimalOutcomeProfile.Type&#8221; then nusoap would not see any relationship between OutcomeMessage and MinimalOutcomeProfile.Type and again refuse to serialize.<br \/>\nThe solution is a new feature I added to nusoap.  The ideas is that you make an entry for &#8220;OutcomeProfile&#8221; and then within that, you point to the actual implementation of the type.  Here is the syntax<br \/>\nI used:<br \/>\n&#8216;SecurityProfile&#8217; => array (<br \/>\n&#8220;SOAP:Implementation&#8221; => &#8220;SharedSecretSecurityProfile.Type&#8221;,<br \/>\n&#8216;SharedSecretSecurityProfile.Type&#8217; => array (<br \/>\n&#8220;MAC&#8221; => &#8220;00:ff:ff:ff:00:00&#8221;<br \/>\n)<br \/>\n)<br \/>\nYou add a &#8220;SOAP:Implementation&#8221; tag within the entry for the abstract type and tell it the real implementation type &#8211; it is basically like a redirect &#8211; &#8220;Hey you are typing to serialize  a SecurityProfile &#8211; but really the schema for this is actually a SharedSecretSecurityProfile.Type&#8221;. It works pretty well &#8211; I am not sure if I am generating good WSDL or not &#8211; I will have to validate this with Axis (have I ever told you how much I despise it when WSDL hackers go crazy and do elegant stuff?).<br \/>\nIt serializes like this:<br \/>\n&lt;SecurityProfile><br \/>\n&lt;MAC&#8221;>00:ff:ff:ff:00:00&lt;\/MAC><br \/>\n&lt;\/SecurityProfile><br \/>\nI don&#8217;t think this is quite right because there is no real indication of the implementing type for the consuming folks.  But I was happy just to get this to work at all.  If someone who is a SOAP\/WSDL expert can tell me how to fix this let me know.  nusoap is a big hog\/monster but I  think I have a handle on it.  The code is around line 5569 of lib\/nusoap.php. Look for the string &#8220;Redirecting&#8221;.<br \/>\nWhat about PHP5?<br \/>\nThis is all PHP4 because it comes shipped on my Mac :).  So I use nusoap.  In PHP5 some of this is built in and so either it is magically fixed or &#8211; it is broken and not easily fixed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my quest to produce an IMS Tool Interoperability Endpoint which requires a SOAP Server in PHP that handles the complex WSDL for IMS Tool Interoperability &#8211; I encountered NUSOAP. I must point out that I have never used nusoap until the last seven days &#8211; so I am *not an* expert. But my general [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-267","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/posts\/267","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/comments?post=267"}],"version-history":[{"count":1,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/posts\/267\/revisions"}],"predecessor-version":[{"id":2370,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/posts\/267\/revisions\/2370"}],"wp:attachment":[{"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/media?parent=267"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/categories?post=267"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dr-chuck.com\/csev-blog\/wp-json\/wp\/v2\/tags?post=267"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}