'''[gkubu] - 2012-06-22 19:08:46''' This page contains examples of how to use the „[http://core.tcl.tk/tclws/index%|%Web services for Tcl]“ client side package. The package was created and is maintained by Gerald Lester, who also patiently provides support for ignorant users. The client parses so-called [wsdl] files [http://en.wikipedia.org/wiki/Wsdl]. From this file you get most of the information you need: * name of the web service * names of the operations it provides * parameters of the operations You may also get the information from the documentation of the service, or by a tool like soapUI, or by the CreateStubs command of the package (see below). The wsdl file contains the information in tags like ======none ====== (The style here is "document/literal", refered to as "document/literal wrapped" in [http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/]). Even those not familiar with wsdl can certainly identify the elements in this example (from the wsdl file "http://www.webservicex.net/country.asmx?WSDL") * the web service name is „country“ * the operation name is „GetCountryByCountryCode“ * the operation parameter is „CountryCode“ of type „string“ **Example 1: simple synchronous information retrieval** ====== package require Tcl 8.5 package require WS::Client ::WS::Client::GetAndParseWsdl "http://www.webservicex.net/MortgageIndex.asmx?WSDL" # DoCall: yields result as a nested dict set monthlyIndex [ ::WS::Client::DoCall MortgageIndex GetCurrentMortgageIndexMonthly {} ] set key [ dict keys $monthlyIndex ] flush stdout puts "Key: $key" foreach { i v } [ dict get $monthlyIndex $key ] { puts "$i $v" } ====== should return something like ====== Key: GetCurrentMortgageIndexMonthlyResult IndexDate 7/1/2004 OneYearConstantMaturityTreasury 2.1 ThreeYearConstantMaturityTreasury 3.05 FiveYearConstantMaturityTreasury 3.69 ThreeMonthTreasuryBill 1.36 SixMonthTreasuryBill 1.69 ThreeMonthSecondaryMarketCD 1.4625 SixMonthSecondaryMarketCD - EleventhDistrictCOFI 1.4929 CostOfSavingsIndex 1.6945 OneMonthLIBOR 1.9857 ThreeMonthLIBOR 2.4632 SixMonthLIBOR 1.1617 OneYearLIBOR 1.91 CostOfDepositsIndex 1.57 TwelveMonthTreasuryAverage 1.85 ====== ***Variants*** '''DoRawCall''' returns the xml response of the web service ====== ::WS::Client::DoRawCall MortgageIndex GetCurrentMortgageIndexMonthly {} 7/1/2004 2.1 3.05 3.69 1.36 1.69 1.4625 - 1.4929 1.6945 1.9857 2.4632 1.1617 1.91 1.57 1.85 ====== If you don't want to look up the name of the web service, you can provide your own. However, if you want to discuss the service, it might be advantageous to use its proper name. ====== package require WS::Client ::WS::Client::GetAndParseWsdl "http://www.webservicex.net/MortgageIndex.asmx?WSDL" {} mogaIxAlias set monthlyIndex [ ::WS::Client::DoCall mogaIxAlias GetCurrentMortgageIndexMonthly {} ] puts [ dict get $monthlyIndex GetCurrentMortgageIndexMonthlyResult TwelveMonthTreasuryAverage ] 1.85 ====== As mentioned above, the CreateStubs command returns operations and parameters ====== package require WS::Client ::WS::Client::CreateStubs MortgageIndex ;# || ::WS::Client::CreateStubs mogaIxAlias ::MortgageIndex::GetCurrentMortgageIndexMonthly {} ::MortgageIndex::GetCurrentMortgageIndexByWeekly {} ::MortgageIndex::GetMortgageIndexByMonth {Month Year} ::MortgageIndex::GetMortgageIndexByWeek {Day Month Year} ====== The stubs are actually commands, which can be used instead of DoCall (a stub is a wrapper for DoCall), but they are missing the flexibility of the latter. ====== ::MortgageIndex::GetMortgageIndexByMonth 5 2004 ====== **Example 2: http headers** Some web services require additional information in http headers, e.g. for authentification. This is shown for a call to a simple eBay web service. You will need an eBay developer account, if you want to reproduce the example [https://www.x.com/developers/ebay/documentation-tools/quickstartguide]. Information on eBay web services is available on [https://www.x.com/developers/ebay/web-services-overview]. The eBay web service GeteBayTime requires an application ID, an API call name, a site ID and the API version as http header fields. WS::Client takes them as a key-value list. The http headers are supplied as the fourth parameter to the DoCall and DoRawCall commands. Stubs cannot take such a parameter. ====== package require Tcl 8.5 package require WS::Client 2.2.7 dict set httpParm X-EBAY-API-APP-ID abcdefgh-1a23-45b6-789c-d012345ef6a7 ;# invalid ID - for demonstration only dict set httpParm X-EBAY-API-SITE-ID 77 dict set httpParm X-EBAY-API-CALL-NAME GeteBayTime dict set httpParm X-EBAY-API-VERSION 775 ::WS::Client::GetAndParseWsdl "http://developer.ebay.com/webservices/latest/ShoppingService.wsdl" ::WS::Client::DoRawCall Shopping GeteBayTime {} $httpParm ====== DoCall needs another option, as will be demonstrated below. DoRawCall yields ====== 2012-06-23T18:02:51.683Z Success E777_CORE_BUNDLED_14948543_R1 775 ====== **Example 3: Configuration** The wsdl includes the URI of the web service. You may want to change it, e.g. for test purposes. The ::WS::Client::Config command provides for that: ====== ::WS::Client::GetAndParseWsdl "file://localhost:P:/edv/programmierung/tcl.tk/div/ebayShopping.wsdl" ::WS::Client::Config Shopping location http://open.api.sandbox.ebay.com/shopping dict set httpParm X-EBAY-API-APP-ID abcdefgh-1a23-45b6-789c-d012345ef6a7 dict set httpParm X-EBAY-API-SITE-ID 77 dict set httpParm X-EBAY-API-CALL-NAME GeteBayTime dict set httpParm X-EBAY-API-VERSION 775 ::WS::Client::DoRawCall Shopping GeteBayTime {} $httpParm ====== Now let's try DoCall: ====== ::WS::Client::DoCall Shopping GeteBayTime {} $httpParm # no response, therefore ... ::WS::Client::Config Shopping skipLevelWhenActionPresent 1 ::WS::Client::DoCall Shopping GeteBayTime {} $httpParm GeteBayTimeResponse {Ack Failure Errors {{ShortMessage {Ungültige Eingabedaten.} LongMessage {Die Eingabedaten für diesen Tag sind ungültig oder fehlen. Bitte lesen Sie die API-Dokumentation.} ErrorCode 1.22 SeverityCode Error ErrorParameters {{Value {Body not found.}}} ErrorClassification RequestError}} Build E777_CORE_BUNDLED_14948543_R1 Version 777} ====== We got a response, but this is not what we wanted. The error message says "Value {Body not found.}". There are two ways to overcome this: ====== # supply the SOAP body dict set body GeteBayTimeRequest "" # note the parameter "$body" ::WS::Client::DoCall Shopping GeteBayTime $body $httpParm GeteBayTimeResponse {Timestamp 2012-06-24T14:19:08.092Z Ack Success Errors {{} {} {} {}} Build E777_CORE_BUNDLED_14948543_R1 Version 777} # Alternative (WS::Client version 2.2.8 required) ::WS::Client::Config Shopping skipLevelWhenActionPresent 0 ::WS::Client::Config Shopping skipLevelOnReply 1 ::WS::Client::DoCall Shopping GeteBayTime {} $httpParm GeteBayTimeResponse {Timestamp 2012-06-24T14:24:46.699Z Ack Success Errors {{} {} {} {}} Build E777_CORE_BUNDLED_14948543_R1 Version 777} ====== When creating the dictionary for the result from the part of the SOAP response, skipLevelonReply causes the routine to skip one level of the DOM tree hierarchy, skipLevelWhenActionPresent does so if the result of the first level is empty. A look at proc ::WS::Client::parseResults in ClientSide.tcl should make this clear. Should you want to use stubs, you will have to prepare your environment because of the need for http header fields. ====== package require WS::Client 2.2.8 set preparsed [ ::WS::Client::GetAndParseWsdl "http://developer.ebay.com/webservices/latest/ShoppingService.wsdl" ] flush stdout dict set httpParm X-EBAY-API-APP-ID abcdefgh-1a23-45b6-789c-d012345ef6a7 dict set httpParm X-EBAY-API-SITE-ID 77 dict set httpParm X-EBAY-API-CALL-NAME GeteBayTime dict set httpParm X-EBAY-API-VERSION 775 WS::Client::LoadParsedWsdl $preparsed $httpParm ::WS::Client::Config Shopping location "http://open.api.sandbox.ebay.com/shopping" ::WS::Client::Config Shopping skipLevelOnReply 1 ::WS::Client::CreateStubs Shopping ::Shopping::GeteBayTime GeteBayTimeRequest GeteBayTimeResponse {Timestamp 2012-06-27T20:52:19.092Z Ack Success Errors {{} {} {} {}} Build E779_CORE_BUNDLED_14991381_R1 Version 779} ====== **Example 4: submitting parameters** While for the stub the parameters were submitted by position (see example 1), for DoCall we need a list or a dict. ====== package require Tcl 8.5 package require WS::Client ::WS::Client::GetAndParseWsdl "http://www.webservicex.net/MortgageIndex.asmx?WSDL" # remember the definition: GetMortgageIndexByMonth {Month Year} dict set monthYear Month 4 dict set monthYear Year 2004 ::WS::Client::DoCall MortgageIndex GetMortgageIndexByMonth $monthYear # Alternative ::WS::Client::DoCall MortgageIndex GetMortgageIndexByMonth {Month 4 Year 2004} # also ::WS::Client::DoCall MortgageIndex GetMortgageIndexByMonth {Year 2004 Month 4 } ====== **Example 5: Local wsdl file** ====== package require WS::Client set secrets "somewhereOnYourSystem" ::WS::Client::GetAndParseWsdl "file://$secrets/mortgageIndex.wsdl" # Alternative package require WS::Client set secrets "somewhereOnYourSystem" set fdWsdl [ open [ file join $secrets MortgageIndex.wsdl ] r ] set wsdl [ read $fdWsdl ] close $fdWsdl ::WS::Client::ParseWsdl $wsdl ====== **See also** [Webservices] http://core.tcl.tk/tclws/wiki?name=WSClient+Client+Side ***Other techniques*** [TclSOAP] (note the comment of [Pat Thoyts] regarding maintenance for this package) [NOAA Weather Forecast] <> Example | Internet | CostOfDepositsIndex