soap.lzx

<library>
    
    <include href="rpc/rpc.lzx"/>
    <include href="rpc/library/soap.js"/>

    <class name="soap" extends="rpc">

        <!--- Required attribute that specifies WSDL to read for the SOAP
              object. The value for wsdl should be an href. -->
        <attribute name="wsdl" type="string"/>

        <!--- The SOAP service to fetch. If not specified, the first service
              encountered in the WSDL is used. -->
        <attribute name="service" value="" type="string"/>

        <!--- The SOAP port to use. If not specified, the first SOAP port
              encountered in the WSDL is used. -->
        <attribute name="port" value="" type="string"/>

        <!--- The SOAP header to pass with each request. This can be either a
              string or a dataset. Default is null. -->
        <attribute name="requestheaders" value="null" type="expression"/>

        <!--- If set, the SOAP response header returned by the last
              call. The value for this must be a dataset. Default is null. -->
        <attribute name="responseheaders" value="null" type="expression"/>

        <!--- The prototypes that can be used to create objects. 
              @keywords readonly -->
        <attribute name="proto" value="null" type="expression"/>

        <!--=================================================================-->
        <!-- public methods                                                  -->
        <!--=================================================================-->

        <!--- Load the object. If successful, this.proxy is set to an object
              with remote APIs. -->
        <method name="load">
            LzSOAPService.loadObject(this._loadDel,
                { wsdl: this.wsdl, service: this.service, port: this.port },
                  this.secure, this.secureport);
        </method>

        <!--=================================================================-->
        <!-- private methods                                                 -->
        <!--=================================================================-->


        <!--- @keywords private -->
        <method name="init">
          if (canvas.runtime == "dhtml") {
              Debug.warn("SOAP RPC only partially implemented in the DHTML runtime.");
          }  

          if (this['wsdl'] == null) {
              Debug.write('soap error: required wsdl attribute not set');
              return;
          }
          super.init();
        </method>

        <!--- @keywords private -->
        <method name="_setup" args="o">
            var ok = super._setup(o);
            if (ok) {
                var stubinfo = o.stubinfo;
                this.service = o.stubinfo.service;
                this.port = o.stubinfo.port;
                if ( o.stubinfo['proto'] ) {
                    this.proto = o.stubinfo.proto;
                }

                for (var k in this.proxy) {
                    var tpka = this.proxy[k]['args'];
                    if (tpka == null) {
                        tpka = this.proxy[k].args = {};
                    }
                    tpka.superclass = this;
                }
            }
            return ok;
        </method>



       <method name="makeProxyStubFunction" args="fn">
                                                        
           var stubinfo = this.proxyinfo[fn];
           //"Multiply": function ()
           //{var args = arguments.callee.args;
           //                return LzSOAPService.invoke(arguments[1],
           //   arguments[0],
           // args.superclass.requestheaders,
           // {"parts": [["tns:Multiply",
           // null]],
           // "opstyle": "document",
           // "operation": "Multiply",
           // "port": "MathServiceSoap",
           // "service": "MathService",
           // "wsdl": "http://www.dotnetjunkies.com/quickstart/aspplus......./mathservice.asmx?WSDL"},
           //                                            args.superclass.secure,
           var stubfunc = function (){
               var args = arguments.callee.args;
               return LzSOAPService.invoke(
                   arguments[1], 
                   arguments[0],
                   args.superclass.requestheaders,
                   stubinfo, false, null);
           }
           
           return stubfunc;
                                                       
       </method>



        <doc>
            <tag name="shortdesc"><text>SOAP (Simple Object Access Prototcol)</text></tag>
            <text>
                <p>SOAP (Simple Object Access Prototcol) is used to exchange information in a
                    distributed environment. A typical scenarion involves a SOAP client invoking a
                    client-side function stub to invoke a SOAP web service operation. The SOAP web
                    service then returns data to the client, like stock information or the result to
                    a math function. The <a href="http://www.w3.org/TR/soap/" shape="rect">SOAP
                        protocol</a> is a work in progress being drafted by the <a href="http://www.w3.org" shape="rect">W3C</a>. For the latest SOAP
                    information.</p>


                <p>The <soap> element creates a client-side representation of a SOAP
                service based on a WSDL. The name and wsdl attributes are required.</p>
                <example>
    <canvas debug="true" height="530">
    
        <debug x="15" y="15" width="415" height="500" />
        
        <soap name="amazon" 
            wsdl="http://soap.amazon.com/schemas3/AmazonWebServices.wsdl">
        
            <handler name="onload">
                Debug.debug('Amazon soap service loaded');
                Debug.debug('Compare proxy stubs with WSDL SOAP operations.');
                Debug.debug('Amazon WSDL at %w', this.wsdl);            
                Debug.debug('proxy:');
                Debug.inspect(this.proxy);
            </handler>
            
            <handler name="onerror" args="error">
                Debug.debug('error: %w', error);
            </handler>
        
        </soap>
        
    </canvas>
                </example>
                    <p>Document style operations use XML (i.e. documents) as paramaters. Document
                    style operations return an array of <sgmltag class="element" role="LzDataElement">LzDataElement</sgmltag>s, 
                    though often only a single
                    <code class="classname">LzDataElement</code> will exist in the array. The XML string (document) parameter
                    passed into the operation must match the XML schema as defined in the WSDL.</p>
                <example>
    <canvas debug="true">
    
        <debug y="30" x="145" width="350" height="300" />
        
        <!-- This SOAP service uses document/literal messages for its
        operations. Each operation is passed a document as a parameter. -->
        <soap name="maths" 
                wsdl="http://www.dotnetjunkies.com/quickstart/aspplus/samples/services/MathService/VB/MathService.asmx?WSDL">
        
            <!-- Method to make a document for SOAP message requests -->
            <method name="makedoc" args="func, av, bv">
                <![CDATA[
                if (func == null) return;
                var s =  '<' + func + ' xmlns="' + 'http://tempuri.org/' + '" >' + 
                    '<A>' + av + '</A>' + 
                    '<B>' + bv + '</B>' + 
                '</' + func + '>';
                Debug.debug("%w", s);
                return s;
                ]]>
            </method>
            
            <handler name="onload">
            // make buttons visible once SOAP object is loaded
                canvas.buttons.setAttribute('visible', true);            
            </handler>
            
            <handler name="onerror" args="error">
                Debug.debug('error: %w', error);
            </handler>
            
            <handler name="ontimeout" args="error">
                Debug.debug('timeout: %w', error);
            </handler>
            
            <handler name="ondata" args="value">
            Debug.debug("%w", value);
                result.setAttribute('text', value);
            </handler>
            
            <remotecall funcname="Add">
                <param value="${ canvas.maths.makedoc(parent.name, a.text, b.text) }" />
            </remotecall>
            <remotecall funcname="Subtract">
                <param value="${ canvas.maths.makedoc(parent.name, a.text, b.text) }" />
            </remotecall>
            <remotecall funcname="Multiply">
                <param value="${ canvas.maths.makedoc(parent.name, a.text, b.text) }" />
            </remotecall>
            <remotecall funcname="Divide">
                <param value="${ canvas.maths.makedoc(parent.name, a.text, b.text) }" />
            </remotecall>
        </soap>
        
        <view name="buttons" x="10" y="10" visible="false" layout="spacing: 10" >
            <text><b>.NET MathService</b></text>
            
            <view layout="axis: x" ><text y="3">a:</text><edittext id="a" text="10"/></view>
            <view layout="axis: x" ><text y="3">b:</text><edittext id="b" text="2" /></view>
            <view layout="axis: x" ><text>result:</text><text id="result"/></view>
            
            <button text="add"      onclick="canvas.maths.Add.invoke()" />
            <button text="subtract" onclick="canvas.maths.Subtract.invoke()" />
            <button text="multiply" onclick="canvas.maths.Multiply.invoke()" />
            <button text="divide"   onclick="canvas.maths.Divide.invoke()" />
        
        </view>
        
    </canvas>
                </example>
                <p>The XML Schema in the WSDL describes how the XML should be structured for
                    each of the operations. The WSDL below describes how what the schema should look
                    like for the <code>Add</code> operation.</p>
                <programlisting>
    <definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:s="http://www.w3.org/2001/XMLSchema"
            xmlns:s0="http://tempuri.org/"
            xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
            xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
            xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
            targetNamespace="http://tempuri.org/"
            xmlns="http://schemas.xmlsoap.org/wsdl/">
    
    <types>
        <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
            <s:element name="Add">
                <s:complexType>
                    <s:sequence>
                        <s:element minOccurs="1" maxOccurs="1" name="A" type="s:float" />
                        <s:element minOccurs="1" maxOccurs="1" name="B" type="s:float" />
                    </s:sequence>
                </s:complexType>
            </s:element>
            
            <s:element name="AddResponse">
                <s:complexType>
                    <s:sequence>
                        <s:element minOccurs="1" maxOccurs="1" name="AddResult" type="s:float" />
                    </s:sequence>
                </s:complexType>
            </s:element>
            
            <!-- MORE SCHEMA DECLARATION (for Subtract, Multiply, Divide) HERE -->
        
        </s:schema>
    </types>
    
    <message name="AddSoapIn">
        <part name="parameters" element="s0:Add" />
    </message>
    <message name="AddSoapOut">
        <part name="parameters" element="s0:AddResponse" />
    </message>
    
    <!-- OTHER MESSAGES (for Subtract, Multiply, Divide) HERE -->
    
    <portType name="MathServiceSoap">
        <operation name="Add">
            <input message="s0:AddSoapIn" />
            <output message="s0:AddSoapOut" />
        </operation>
        <!-- OTHER PORT TYPE OPERATIONS (for Subtract, Multiply, Divide) HERE -->
    </portType>
    
    <binding name="MathServiceSoap" type="s0:MathServiceSoap">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
        <operation name="Add">
            <soap:operation soapAction="http://tempuri.org/Add" style="document" />
            <input>
                <soap:body use="literal" />
            </input>
            <output>
                <soap:body use="literal" />
            </output>
        </operation>
        <!-- OTHER SOAP BINDING OPERATIONS (for Subtract, Multiply, Divide) HERE -->
    </binding>
    
    <service name="MathService">
        <port name="MathServiceSoap" binding="s0:MathServiceSoap">
            <soap:address location="http://www.dotnetjunkies.com/quickstart/aspplus/samples/services/MathService/VB/MathService.asmx" />
        </port>
    </service>
    
    </definitions>
                </programlisting>
                <p>RPC style operations behave just like functions in that, instead of
                    documents, values are passed in as parameters. Parameters can be of simple data
                    type (number, boolean), array, or object. The parameter type for the operation
                    is described in the WSDL's XML schema.</p>
          <example>
      <canvas debug="true" height="400" width="530">
      
          <debug x="10" y="190" width="510" height="200" />
          
          <dataset name="googleDset" />
          
          <soap name="google" wsdl="http://api.google.com/GoogleSearch.wsdl">
              <handler name="onload">
                  Debug.debug('google soap service loaded');
              </handler>
              
              <handler name="onerror" args="error">
                  Debug.debug('error: %w', error);
              </handler>
              
              <!-- See RPC chapter for details on remotecall and how dataobject is
              used to data bind to RPC operation results. --> 
              <remotecall name="search" funcname="doGoogleSearch" 
                      dataobject="googleDset">
              
                  <param value="'2TKUw4ZQFHJ84ByemZK0EXV0Lj+7xGOx'" />
                  <param value="${ s.text }" />
                  <param value="1" />
                  <param value="10" />
                  <param value="true" />
                  <param value="''" />
                  <param value="true" />
                  <param value="''" />
                  <param value="''" />
                  <param value="''" />
                  
                  <handler name="ondata" args="value">
                      Debug.debug('search result: %w\n', value);
                  </handler>
              
              </remotecall>
          </soap>
          
          <view x="10" y="10" layout="spacing: 5" >
              <view layout="axis: x; spacing: 5">
                  <edittext id="s" text="SOAP" />
                  <button text="search" 
                  onclick="Debug.debug('Invoking search...'); google.search.invoke()" />
              </view>
                  
              <view width="505" height="140" bgcolor="silver" layout="axis: y" >
                  <view>
                      <datapath xpath="googleDset:/resultElements/item" pooling="true" />
                      <text width="200" datapath="title/text()" clip="true" />
                      <text x="205" width="300" datapath="URL/text()" clip="true" />
                  </view>
              </view>
          
          </view>
      
      </canvas>
          </example>
                <p>The example demonstrates how a result value, which is actually a JavaScript
                    object, can be data bound through the dataobject attribute in remotecall. For
                    more details, see the remotecall section in the <a href="../developers/rpc-soap.html" target="laszlo-dguide" shape="rect">RPC chapter</a> of the <a href="../developers/" target="laszlo-dguide" shape="rect">Developer's Guide</a>. To read about passing complex type
                    parameters, read the <a href="../developers/rpc-soap.html" target="laszlo-dguide" shape="rect">SOAP chapter</a>.</p>
                
                
                <p><b>See Also:</b></p>

                    <ul>
                        <li>
                            <sgmltag class="element" role="lz.rpc"><rpc></sgmltag>
                        </li>
                        <li>
                            <sgmltag class="element" role="lz.javarpc"><javarpc></sgmltag>
                        </li>
                        <li>
                            <sgmltag class="element" role="lz.xmlrpc"><xmlrpc></sgmltag>
                        </li>
                        <li>
                            <sgmltag class="element" role="lz.remotecall"><remotecall></sgmltag>
                        </li>
                        <li>
                            <a href="../developers/rpc.html" target="laszlo-dguide" shape="rect">Developer's Guide: RPC</a>
                        </li>
                        <li>
                            <a href="../developers/rpc-soap.html" target="laszlo-dguide" shape="rect">Developer's Guide: SOAP</a>
                        </li>
                    </ul>
                    
            </text>
            </doc>
    </class>

</library>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2009 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
<!-- @LZX_VERSION@                                                         -->

Cross References

Includes

Classes