* The TclSOAP package provides method binding for [Tcl] clients to remote procedures implemented using either [SOAP], [XML-RPC] or [JSON-RPC]. The first two protocols package up a payload as [XML] and use [HTTP] to transport the data to and from the service provider. The last formats the payload as [JSON]. The TclSOAP package provides a means of binding Tcl procedures to the remote method and for creating RPC servers easily under [tclhttpd]. The project is hosted on [SourceForge] at http://sourceforge.net/projects/tclsoap and the documentation is at http://tclsoap.sourceforge.net/ ---- Can someone replace this line with a statement regarding what version of SOAP tclsoap supports? Any references to plans for supporting SOAP 1.2 would also be appreciated. [PT] 26Jun2003: As of version 1.6.6 TclSOAP supports SOAP1.1 and makes some attempts towards supporting SOAP1.2. The SOAP methods have a -version option which can be set to SOAP1.1 or SOAP1.2 or explicitly to the xml namespace required. You can also set the encoding in use using the -encoding option. Currently I'm not planning much work towards full 1.2 compliance. TclSOAP also supports [XML-RPC]. [APN] 2008-07-05: TclSOAP now includes client side support for [JSON-RPC]. ---- * [[old]] A mirror for the distribution is at http://oss.software.ibm.com/staging/soaptcl/http//TclSOAP-1.3.tar.Z , or, more generally, through http://oss.software.ibm.com/developerworks/opensource/soap4tcl/ . * TclSOAP 1.6.6 [http://sourceforge.net/project/showfiles.php?group_id=25970&release_id=136092] released 25 January 2003. * [Scott Gamon] explains how to expose SOAP and XMLRPC methods from [tclhttpd] at: [http://www.gamon.org/Profession/TCL/TCL-TclHttpdWebServices.html]. Also, exposing those same methods through [REpresentational State Transfer, REST]: [http://www.gamon.org/Profession/TCL/TCL-TclHttpdWebServices-REST.html]. This package is part of the [ActiveTcl] Batteries Included distribution. ---- '''Dependencies''' TclSOAP requires the packages [http], dom ([TclDOM]) and [tcllib]. For versions greater than 1.6.1 you'll need [tcllib] 1.2. If you want to use other transports then you'll need the relevant package (smtp and ftp from [tcllib] or [beep]core-tcl). ---- '''Examples''' Q: Anyone have any practical applications showing the use of TclSOAP in a way that others could not only read and understand, but perhaps make use of the application? A: Does [http://www-106.ibm.com/developerworks/education/r-ws-wspt.html?n-671] address your question? Also the documentation at http://tclsoap.sf.net/ gives pretty extensive examples for using the package as a SOAP client. * A simple SOAP call to a Perl implemented service using http. % package require SOAP 1.6 % SOAP::create c2f -uri http://www.soaplite.com/Temperatures \ -proxy http://services.soaplite.com/temper.cgi \ -params { "temp" "float" } ::c2f % c2f -40.0 24.8 Fixed above example to http://www.soaplite.com/Temperatures. Scott Nichols 9-22-2003 * SOAP over SMTP (sends the request to the proxy url). % package require SOAP::smtp 1.0 % SOAP::configure -transport mailto -servers smtp.localdomain.org % SOAP::create POSSale -uri urn:tclsoap::POS \ -proxy mailto:soap-pos@soap.localdomain.org \ -params { productid string amount float operator string } ::POSSale % POSSale "0123232-0912" 10.00 "Sally" % * SOAP over FTP % package require SOAP::ftp 1.0 % SOAP::create POSSale -uri urn:tclsoap:POS \ -proxy ftp://anonymous:guest@soap.localdomain.org/soap/POS \ -params { productid string amount float operator string } ::POSSale % POSSale "0123232-0912" 10.00 "Sally" ---- [Cameron Laird] brought this example (temperature retrieval by zip code) in [http://www.oetrends.com/cgi-bin/page_display.cgi?89]: # Declare required libraries. package require SOAP package require Tk # Create a simple GUI display. Bind the entry display # to "zipcode". entry .my_entry -textvariable zipcode label .my_label pack .my_entry .my_label # # describes this service. set URI urn:xmethods-Temperature set URL http://services.xmethods.net/soap/servlet/rpcrouter # Bind a local command to the remote service. SOAP::create getTemp -uri $URI -proxy $URL -params {zipcode string} # Invoke the SOAP-mediated local command when the user # pushes the "Return" key. Display the return value. bind .my_entry { .my_label configure -text \ "The temperature at $zipcode is [getTemp $zipcode]." } [snichols] Note: The above SOAP method is in place, but always returns -999 no matter what zip code is passed in. ---- [Michael Jacobson] adds this example used in [Play Chess With a WebService]. Using the interface specification from http://www.danmarinescu.com/webservices.htm and shown below... * '''Position''': char[[64]], starting from upper left, ending to upper right, empty squares are spaces, universal chess notation (whites are capitals), whites are always down. You will have to send the position every single time you access the interface. For example, the initial position will be: "rnbqkbnrpppppppp {insert 4*8=32 spaces in here!} PPPPPPPPRNBQKBNR" (the spaces for empty squares are mandatory). * '''WhiteMovesNext''': bool, defaulted to true. * '''SearchDepth''': int, defaulted to 3, this would be the search depth of the Chess algorithm (please do not abuse the server, do not send values bigger than 5). The default value (3) stands for about 2100 elo... The thinking time growth is an exponential of the search depth We can come up with a simple example of the white opening move in a chess game. package require SOAP set uri "urn:BorlandChess-IBorlandChess#XML_GetNextMove" set proxy "http://www.danmarinescu.com/WebServices/ChessCGIServer.exe/soap/IBorlandChess" SOAP::create XML_GetNextMove \ -uri $uri -proxy $proxy \ -params {"Position" "string" "WhiteMovesNext" "boolean" "SearchDepth" "integer"} XML_GetNextMove "rnbqkbnrpppppppp[string repeat { } 32]PPPPPPPPRNBQKBNR" true 3 # returns "e2e4 OK" ---- [Michael Jacobson] also adds and example to view the current price of a auction item on ebay with tclSOAP. package require SOAP set uri "urn:xmethods-EbayWatcher" set proxy "http://services.xmethods.net:80/soap/servlet/rpcrouter" SOAP::create getCurrentPrice -uri $uri -proxy $proxy \ -params {"auction_id" "string"} #getCurrentPrice 3218123285 ;# use a valid auction item number from ebay ---- '''Discussion''' A fairly large number of people have trouble finding a suitable [TclDOM] package to use with the SOAP package. I have therefore placed the versions of TclDOM 2.0 that I use for development at http://tclsoap.sourceforge.net/dom-packages.html You can still get the canonical TclDOM code from http://sourceforge.net/projects/tclxml [PT] An alternative is to get a binary distribution like [ActiveTcl], which contains all the necessary packages. ---- In the course of answering a question [http://groups.google.com/groups?ic=1&selm=m2ithzriuo.fsf%40porky.home.net] about how to transmit content which is itself an XML document, TclSOAP author [Pat Thoyts] makes these points: "You should be fine passing in XML data. It will need to be quoted properly as per XML specs ie: < as < etc. [DAF] notes that some servers are not expecting this xml to be escaped, and throw their toys out of the cot when you send escaped xml. I've made a patch which makes the behabiour of TCLSoap more like that of Perl's SOAP::Lite in this regard. It basically introduces a parameter type ''xml'' which is treated differently from a standard string -- a dom document object is created, and the root node inserted under the named parameter in the SOAP envelope's body, for example: # override the SOAP::insert_value command: proc ::SOAP::insert_value {node value} { set type [rpctype $value] set subtype [rpcsubtype $value] set attrs [rpcattributes $value] set headers [rpcheaders $value] set value [rpcvalue $value] set typeinfo [typedef -info $type] set typexmlns [typedef -namespace $type] # Handle any header elements if {$headers != {}} { insert_headers $node $headers } # If the rpcvar namespace is a URI then assign it a tag and ensure we # have our colon only when required. if {$typexmlns != {} && [regexp : $typexmlns]} { dom::element setAttribute $node "xmlns:t" $typexmlns set typexmlns t } if {$typexmlns != {}} { append typexmlns : } # If there are any attributes assigned, apply them. if {$attrs != {}} { foreach {aname avalue} $attrs { dom::element setAttribute $node $aname $avalue } } if {[string match {*()} $typeinfo] || [string match {*()} $type] || [string match array $type]} { # array type: arrays are indicated by one or more () suffixes or # the word 'array' (depreciated) if {[string length $typeinfo] == 0} { set dimensions [regexp -all -- {\(\)} $type] set itemtype [string trimright $type ()] if {$itemtype == "array"} { set itemtype ur-type set dimensions 1 } } else { set dimensions [regexp -all -- {\(\)} $typeinfo] set itemtype [string trimright $typeinfo ()] } # Look up the typedef info of the item type set itemxmlns [typedef -namespace $itemtype] if {$itemxmlns != {} && [regexp : $itemxmlns]} { dom::element setAttribute $node "xmlns:i" $itemxmlns set itemxmlns i } # Currently we do not support non-0 offsets into the array. # This is because I don;t know how I should present this to the # user. It's got to be a dynamic attribute on the value. dom::element setAttribute $node \ "xmlns:SOAP-ENC" "http://schemas.xmlsoap.org/soap/encoding/" dom::element setAttribute $node "xsi:type" "SOAP-ENC:Array" dom::element setAttribute $node "SOAP-ENC:offset" "\[0\]" # we need to break a multi-dim array into r0c0,r0c1,r1c0,r1c1 # so list0 followed by list1 etc. # FIX ME set arrayType "$itemxmlns:$itemtype" #for {set cn 0} {$cn < $dimensions} {incr cn} append arrayType "\[[llength $value]\]" dom::element setAttribute $node "SOAP-ENC:arrayType" $arrayType foreach elt $value { set d_elt [dom::document createElement $node "item"] if {[string match "ur-type" $itemtype]} { insert_value $d_elt $elt } else { insert_value $d_elt [rpcvar $itemtype $elt] } } } elseif {[llength $typeinfo] > 1} { # a typedef'd struct. if {$typexmlns != {}} { dom::element setAttribute $node "xsi:type" "${typexmlns}${type}" } array set ti $typeinfo # Bounds checking - if {[llength $typeinfo] != [llength $value]} { return -code error "wrong # args:\ type $type contains \"$typeinfo\"" } foreach {eltname eltvalue} $value { set d_elt [dom::document createElement $node $eltname] if {![info exists ti($eltname)]} { return -code error "invalid member name:\ \"$eltname\" is not a member of the $type type." } insert_value $d_elt [rpcvar $ti($eltname) $eltvalue] } } elseif {$type == "struct"} { # an unspecified struct foreach {eltname eltvalue} $value { set d_elt [dom::document createElement $node $eltname] insert_value $d_elt $eltvalue } } elseif {$type == "xml"} { # straight xml that needs to be inline'd set subdoc [dom::parse $value] set newnode [dom::node appendChild $node\ [dom::document cget $subdoc -documentElement]] dom::element setAttribute $node "xsi:type" "xsd:string" } else { # simple type or typedef'd enumeration if {$typexmlns != {}} { dom::element setAttribute $node "xsi:type" "${typexmlns}${type}" } dom::document createTextNode $node $value } } # create your SOAP command: SOAP::create foo -proxy http://myfoo.bar.com -uri "urn:foo.bar" -action "urn:foo.bar" -params {name string zipcode integer userdetails xml} # run that command: foo "Mr Foo" "4001" "1337 h4x0r" I hope that my patch will be taken into consideration for the official TCLSoap package -- apart from this patch, the package did exactly what I needed, and was significantly faster than perl's SOAP::Lite. ---- Here is a brief example using TclSOAP and tclhttpd as the server. I run these commands under [TkCon]... source tclhttpd3.3/bin/httpd.tcl ;# start the web server package require SOAP package require SOAP::Domain SOAP::Domain::register -prefix /soap -namespace zsplat::Test # Define a server procedure to return some XML proc xml {} { return {} } SOAP::create zxml -proxy http://localhost:8015/soap/xml -uri zsplat-Test zxml returns and SOAP::dump zxml returns <?xml version="1.0"?><Memo/> If you have problems you could always pack up the XML as [base64] encoded data and send that instead." * The above code will only work for versions prior to 1.6. For newer versions you would create a tcl script file with the method implementation and place it into a directory. Then start tclhttpd, source tclserver.tcl, set the SOAP::CGI::soapdir variable and let rip. Also, newer code needs to be 'exported'. This is so that callers cannot execute arbitrary tcl commands like '''exec'''. [PT] ---- In a comp.lang.tcl posting, Pat explains that TclSOAP 1.6 includes new capabilities for "structure" transmission. He offers package require rpcvar namespace import rpcvar::typedef typedef { intValue int floatValue float stringValue string } SoapStruct SOAP::create someMethod -params {aStruct SoapStruct} someMethod {intValue 2 floatValue 3.5 stringValue "Hello World"} as an example usage. ---- There was a comment regarding problems with TclSOAP and why someone choose the Java SOAP instead recently on comp.lang.tcl . [PT] - So stick in a link then! The reason they made this decision was at my advice. In September 2001 the package was still pretty new and only operated with Tcl-only versions of TclDOM. The relative sluggishness of Tcl for processing DOM trees combined with the CGI process startup for the naive implementation of SOAP services under CGI meant that they were better off using some other system for the server side of their application. You should node that they continued to use TclSOAP for the client side. Since that time - fixes to the TclDOM C module (dom::c) have made it possible to use a significantly faster DOM processor. Changes to the method used to host the SOAP server side should also improve performance. For instance, using mod_dtcl with Apache or using tclhttpd would mean that there will pretty much no startup delay. The TclSOAP site at http://tclsoap.sourceforge.net/ hosts some SOAP services - namely implementations of the SOAP Interoperability Lab Test Suite for round 1 and 2. You can test the relative performance of these services against other similar implementations. The server is Apache and using the C TclDOM but nothing has been done (yet) about improving the CGI handling. If your services are going to be performance intensive I would still recommend using another SOAP toolkit (perl or easysoap++ maybe). However, if you want to generate some protptypes fast and/or flexibly the Tcl is always there. [CL] adds: I'll emphasize again that it's ENTIRELY OK to use a different SOAP toolkit for servers than for clients. Tcl/Tk is way cool on the client side--download [ActiveTcl], and you're completely ready to build nice clients. Tcl is less competitive for SOAP servers, in my opinion. Also, while I'm sharing my sentiments: Pat's done great work. ---- More on server-side SOAP work: even as of version 1.6.1, Pat agrees, "The client code is generally very easy to use but the server side stuff is much less so." Specifically, "To run TclSOAP with tclhttpd there is a tclserver.tcl file in samples/ which can use the SOAP::CGI style setup and code within tclhttpd. It works but the server code could generally use a bit of a redesign to simplify things." In Pat's summary: source tclhttpd/bin/httpd.tcl source tclsoap/samples/tclserver.tcl are the best current documentation for server-side possibilities ''using tclhttpd''. [PT] I'd suggest reading http://tclsoap.sf.net/SOAP-CGI.html for information on providing a SOAP service using TclSOAP. The example above is the current howto for providing SOAP services from within tclhttpd. This is not as pleasant an experience as it might be due to the reworkings I performed to get it working with CGI under Apache. The SOAP::Domain package was a nicer tclhttpd solution. In the near future I'm going to try and construct a better tclhttpd solution. ---- Good reading: [David Bleicher]'s "Can I do SOAP with HTTPS (HTTP over SSL)?" [http://sourceforge.net/docman/display_doc.php?docid=8689&group_id=25970]. [[[Ectoraige]]] This may be out of date, the process Bleicher described didn't work for me anyway - I think for versions past 1.6, then all you should have to do to get https urls working is: package require SOAP::https If not you may find it worthwhile looking at [http://sourceforge.net/docman/display_doc.php?docid=10946&group_id=25970]. [WSDL] is an XML dialect for describing services which are implemented with SOAP. [[[PT]]]: as of 1.6.5 I've got some WSDL support in the development branch. Hopefully this will get merged into the main package before too long (say April 2003?). The basic structure is likely to be that calling SOAP::service http://tclsoap.sf.net/WSDL/silab.wsdl SOAP::service file:///usr/local/etc/WSDL/interop.wsdl will parse the web service description and create a namespace will all the methods defined. For the interop suite that would be ''interopLab::echoString'' and ''interopLab::echoInteger'' etc. As of 22Jan03 the WSDL parsing is done but I have yet to process the type descriptions (which pretty much involves parsing XML Schema language :( ). ''[lexfiend] 13 Feb 2006:'' In the meantime, for Tcl'ers who need to use TclSOAP with complex WSDL files, see my note in [WSDL] for an interim method of dealing with this situation. ---- [http://www-105.ibm.com/developerworks/education.nsf/webservices-onlinecourse-bytitle/19E5B7B7641964C786256A610065361A?open&l=867,t=grws,p=SOAPwTcl] talks about using SOAP with Tcl, by [Cameron Laird]. [[[PT]]] write: This article covers version 1.3 so is a little old. It's still a good introduction but you'll want to check the examples that are part of the TclSOAP distribution. Especially if you intend to send structures or advanced types over SOAP. ---- [DKF]: Does TclSOAP support WS-Security? [[[PT]]]: Not at the moment and perhaps never. I don't have any pressing need to support this extension and it isn't expecially interesting to do. I tend to be interested in communications generally (hence the SOAP and smtpd work). Of course, some sort of financial incentive will guarantee a rapid change of heart and ensure a place at the top of my work pile!! [DKF]: Rats! Might have to do it myself sometime. (I ''hate'' writing security code!) ---- [Pat Thoyts], on the chat, writes: Someone has done a tclsoap wrapper for the google API. it is here http://gondolin.hist.liv.ac.uk/~cheshire/tclgoogle.html There is another here at [Googling with SOAP] ---- [SC] ''24 Sept 03'' I was just looking at how to add an XMLRPC interface to [giggle] so that I could implement the blogger API for posting new messages. Currently giggle is a single library called via a simple main script, it handles all uris below it (eg. ../giggle.tcl/foo/bar) through simple CGI and packs nicely into a starkit. It seems from the SOAP::CGI docs that to add an XMLRPC interface I need to supply multiple files to implement the interface (of course these could be inside the starkit). What would be neater would be to be able to get the posted XML and pass it to a proc for interpretation having registered some ''already loaded'' procs as being available via XMLRPC. It looks like ::SOAP::CGI::xmlrpc_invocation almost does this -- except it does the sourcing of tcl files too. Would it be easy to provide this kind of entry point into the server side of tclSOAP? [PT] 25-Sep-2003: The reason we have the re-sourcing all the time is to support CGI based services, where the whole lot is being loaded into a new interpreter for each call. What you are after is the tclhttpd support which is in the SOAP::Domain subpackage. At this time support for XMLRPC is missing, but either I'll get around to it or you could use the code in the SOAP::Domain package to fix the XMLRPC::Domain code. The tclhttpd-style support is a much better solution than CGI-based -- but it just so happens that I have to use CGI for my services, hence we support CGI better than tclhttpd. ---- There is a tDOM based package called tsoap which implements the same api as TclSOAP, but uses tDom instead of TclDom. [schlenk] A link to tsoap would be nice. [Jochen loewer] 2005-08-04: I found tDOM based SOAP on openacs CVS: http://cvs.openacs.org/cvs/openacs-4/packages/tsoap/ ---- [Byron Whitlock] has a nice WSDL generator for Tclsoap and [tclhttpd] here: http://www.geocities.com/blackboy9692002/tclsoap/ ---- !!!!!! %| [Category Package] | [Category XML] | [Category Internet] |% !!!!!!