Compare Revisions

Accessing Web Services in Mozilla Using WSDL Proxying

Revision 70327:

Revision 70327 by Sheppy on

Revision 70328:

Revision 70328 by rawand on

Title:
Accessing Web Services in Mozilla Using WSDL Proxying
Accessing Web Services in Mozilla Using WSDL Proxying
Slug:
XML_Web_Services/Accessing_Web_Services_in_Mozilla_Using_WSDL_Proxying
XML_Web_Services/Accessing_Web_Services_in_Mozilla_Using_WSDL_Proxying
Tags:
"XML Web Services"
"XML Web Services"
Content:

Revision 70327
Revision 70328
t7    <p>t7    <h6>
8      {{ Obsolete_header() }} {{ Fx_minversion_note("3") }}8      add
9    </p>
10    <p>
11      The <a href="en/SOAP_in_Gecko-based_Browsers">SOAP in Gecko
>-based Browsers</a> (Simple Object Access Protocol) article cover 
>ed how to access web services using the low-level SOAP API in Moz 
>illa-based browsers. SOAP is an XML language that forms the basis 
> upon which web services are built. Using SOAP has been somewhat  
>tedious, requiring manual construction and delivery of the SOAP e 
>nvelope the web service expects. SOAP-based response also has nee 
>d to be parsed manually for the information required. 
12    </p>
13    <p>
14      Relief is in sight: As of Netscape 7.1/Mozilla 1.4, Gecko s
>upports WSDL 1.1 (<a class="external" href="http://www.w3.org/TR/ 
>wsdl">Web Services Description Language</a>) proxying. A WSDL fil 
>e describes the interfaces that a web service provides, similar t 
>o a header file in C or IDL. Using the WSDL file, Gecko can offer 
> developers a way to "script" web services as if it were a native 
> object, hiding the SOAP and XML aspect. For example, after creat 
>ing a proxy instance of a web service using WSDL, one can call me 
>thods on the proxy object like one would on any JavaScript object 
> (proxy.getTranslation("en_fr", "Hello World") for example). 
15    </p>
16    <p>
17      This article covers WSDL support in Mozilla 1.7-based brows
>ers. It also addresses the cross-domain issue and new security mo 
>del that Netscape is proposing that would allow web services to d 
>etermine if the client can access the service from any domain or  
>only specific domains. 
18    </p>
19    <p>
20      This article draws upon the <a class="external" href="http:
>//xmethods.net/ve2/ViewListing.po?key=uuid:E00104D5-2AC8-9DEA-EF4 
>C-8BD920E1B4DD">Babelfish</a> web service provided by <a class="e 
>xternal" href="http://www.xmethods.net/">XMethods</a>, which was  
>the first site to implement the new Gecko web services security m 
>odel, allowing Gecko browsers to directly access web services fro 
>m other domains. 
21    </p>
22    <h3 name="Creating_a_WSDL_Proxy">
23      Creating a WSDL Proxy
24    </h3>9    </h6>
25    <p>
26      A web service proxy can be created from JavaScript by creat
>ing an instance of <tt>WebServiceProxyFactory</tt>. The actual WS 
>DL file is loaded by calling the <tt>createProxyAsync</tt> method 
> on the <tt>WebServiceProxyFactory</tt> object. 
27    </p>
28    <p>
29      <tt>createProxyAsync</tt> takes in five parameters:
30    </p>
31    <ol>
32      <li>The first one is the location of the WSDL file. For the
> BabelFish web service, it is <a class=" external" href="http://w 
>ww.xmethods.net/sd/2001/BabelFishService.wsdl" rel="freelink">htt 
>p://www.xmethods.net/sd/2001/BabelFishService.wsdl</a>. 
33      </li>
34      <li>The second parameter is the port name. The port name ca
>n be found in the WSDL file itself, under the service element as  
>shown in figure 1. 
35      </li>
36      <li>The third argument is an optional qualifier, which one 
>doesn't have to worry about. 
37      </li>
38      <li>The fourth parameter is a boolean indicating if the pro
>xy should be loaded asynchronous or not. Netscape 7.1/Mozilla 1.4 
> doesn't support synchronous proxy creation. Since the method nam 
>e itself contains "Async", this parameter is somewhat redundant a 
>nd should always be set to true. 
39      </li>
40      <li>The final parameter is the callback function (the creat
>ion listener) that gets called once the proxy is generated, which 
> is discussed in detail in the next section. 
41      </li>
42    </ol>
43    <div class="figure">
44      <p>
45        <strong>JavaScript:</strong><br>
46        var factory = new WebServiceProxyFactory();<br>
47        factory.createProxyAsync("<a class=" external" href="http
>://www.xmethods.net/sd/2001/BabelFishService.wsdl" rel="freelink" 
>>http://www.xmethods.net/sd/2001/BabelFishService.wsdl</a>", <spa 
>n style="color:green">"BabelFishPort"</span>, "", true, aCreation 
>Listener);<br> 
48        <br>
49        <strong>WSDL:</strong><br>
50        &lt;?xml version="1.0"?&gt;<br>
51        &lt;definitions name="BabelFishService" ...&gt;<br>
52        &nbsp;&nbsp;...<br>
53        &nbsp;&nbsp;&lt;service name="BabelFishService"&gt;<br>
54        &nbsp;&nbsp;&nbsp;&nbsp;&lt;documentation&gt;Translates t
>ext of up to 5k in length, between a variety of languages.&lt;/do 
>cumentation&gt;<br> 
55      </p>
56      <p>
57        &nbsp;&nbsp;&nbsp;&nbsp;&lt;port <span style="color:green
>">name="BabelFishPort"</span> binding="tns:BabelFishBinding"&gt;< 
>br> 
58        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;soap:address loca
>tion="<a class=" external" href="http://services.xmethods.net:80/ 
>perl/soaplite.cgi" rel="freelink">http://services.xmethods.net:80 
>/perl/soaplite.cgi</a>"/&gt;<br> 
59        &nbsp;&nbsp;&nbsp;&nbsp;&lt;port&gt;<br>
60        &nbsp;&nbsp;&lt;/service&gt;<br>
61        &lt;/definitions&gt;<br>
62        <b>Figure 1.</b> Instantiating and initializing a web ser
>vice proxy. 
63      </p>
64    </div>
65    <p>
66      To recap, an interface look at the <tt>createProxyAsync</tt
>> method: 
67    </p>
68    <p>
69      void createProxyAsync (String wsdlURL, String portname, Str
>ing qualifier, boolean isAsync, WebServiceProxyCreationListener l 
>istener) 
70    </p>
71    <p>
72      <span class="comment">edited by sebastian gurin</span> wher
>e the argument's semantics are: 
73    </p>
74    <pre class="eval">
75   <b>wsdlURL:</b> The URL of the WSDL service description. This 
>description will be loaded and used as the basis for the service  
>proxy.  
76   <b>portname:</b> The name of the port of the service that this
> service proxy represents. Currently the port must represent a SO 
>AP binding.  
77   <b>qualifier:</b> The user-specified qualifier is incorporated
> into the names of XPCOM interfaces created for the service proxy 
>. For C++ callers, this qualifier should be the same one used in  
>creating the IDL used at compile time. Script callers need not sp 
>ecify a qualifier.  
78   <b>isAsync:</b> If PR_TRUE, the method signatures of the servi
>ce proxy represent an asynchronous calling convention. A callback 
> instance must be registered with the proxy. A method call to a w 
>eb service is only completed when the corresponding callback meth 
>od is invoked. If PR_FALSE, the method signatures of the service  
>proxy represent a synchronous callling convention. A method call  
>to a web service is completed when the method call to the proxy r 
>eturns.  
79   <b>listener:</b> The callback instance which will be invoked w
>hen the proxy is completely initialized. 
80</pre>
81    <p>
82      You can also use the simpler WebServiceProxyFactory::create
>Proxy(wsdlURL, portname, qualifier,isAsync) method for create a w 
>eb service proxy. The API description of WebServiceProxyFactory c 
>an be found <a class="external" href="http://www.xulplanet.com/re 
>ferences/xpcomref/ifaces/nsIWebServiceProxyFactory.html">here her 
>e</a> 
83    </p>
84    <h3 name="The_Callback">
85      The Callback
86    </h3>
87    <p>
88      As noted above, the last parameter <tt>createProxyAsync</tt
>> takes is a creation listener. The creation listener is an objec 
>t which implements several methods. The creation listener is call 
>ed when either the proxy generation has been successful or if an  
>error has occurred. It is also used when a method is called on th 
>e proxy object. 
89    </p>
90    <p>
91      The creation listener is a variable that holds several meth
>ods. Since the proxy is generated asynchronously, it holds a <tt> 
>onLoad</tt> function that gets called when the proxy has been ini 
>tialized, meaning it is now possible to call methods on the proxy 
>. <tt>onError</tt> is called if an error occurs while generating  
>the proxy or during a method call. 
92    </p>
93    <p>
94      Calling a method on the proxy is also executed asynchronous
>ly. Therefore, the creation listener holds callbacks for each met 
>hod that will be called. The methods for these follow a specific  
>naming scheme: <tt>{methodName}Callback</tt>. The BabelFish web s 
>ervice only contains one method, <tt>BabelFish</tt> (in the WSDL, 
> methods are denoted by the <tt>operation</tt> element), so the c 
>allback function is called <tt>BabelFishCallback</tt>. As can be  
>seen from the WSDL file (relevant parts shown in figure 2), the < 
>tt>BabelFish</tt> method takes in an <tt>BabelFishRequest</tt>, w 
>hich is composed of two parameters, and returns the translated va 
>lue as a string. 
95    </p>
96    <div class="figure">
97      <p>
98        <strong>JavaScript:</strong><br>
99        var listener = {<br>
100        <br>
101        &nbsp;&nbsp;// gets called once the proxy has been instan
>tiated<br> 
102        &nbsp;&nbsp;<strong>onLoad</strong>: function (aProxy)<br
>> 
103        &nbsp;&nbsp;{<br>
104        &nbsp;&nbsp;&nbsp;&nbsp;gProxy = aProxy;<br>
105        &nbsp;&nbsp;&nbsp;&nbsp;gProxy.setListener(listener);<br>
106        &nbsp;&nbsp;&nbsp;&nbsp;requestTranslation(aValue);<br>
107        &nbsp;&nbsp;},<br>
108        <br>
109        &nbsp;&nbsp;// gets called if an error occurs<br>
110        &nbsp;&nbsp;<strong>onError</strong>: function (aError)<b
>r> 
111        &nbsp;&nbsp;{<br>
112        &nbsp;&nbsp;&nbsp;&nbsp;alert("An error has occured while
> processing the WSDL file: " + aError);<br> 
113        &nbsp;&nbsp;},<br>
114        <br>
115        &nbsp;&nbsp;// callback function is hardcoded to {methodn
>ame}Callback in 1.4beta<br> 
116        &nbsp;&nbsp;<strong>BabelFishCallback</strong> &nbsp;: fu
>nction (aResult)<br> 
117        &nbsp;&nbsp;{<br>
118        &nbsp;&nbsp;&nbsp;&nbsp;alert(aResult)<br>
119        &nbsp;&nbsp;}<br>
120        };<br>
121        <br>
122        function requestTranslation(aValue){<br>
123        &nbsp;&nbsp;if (gProxy) {<br>
124        &nbsp;&nbsp;&nbsp;&nbsp;gProxy.BabelFish("en_fr", aValue)
>;<br> 
125        &nbsp;&nbsp;} else {<br>
126        &nbsp;&nbsp;&nbsp;&nbsp;alert("Error: Proxy set up not co
>mplete!");<br> 
127        &nbsp;&nbsp;}<br>
128        }<br>
129        <br>
130      </p>
131      <p>
132        <strong>WSDL:</strong><br>
133        &lt;message name="BabelFishRequest"&gt;<br>
134        &nbsp;&nbsp;&lt;part name="translationmode" type="xsd:str
>ing"/&gt;<br> 
135        &nbsp;&nbsp;&lt;part name="sourcedata" type="xsd:string"/
>&gt;<br> 
136        &lt;/message&gt;<br>
137        <br>
138        &lt;message name="BabelFishResponse"&gt;<br>
139        &nbsp;&nbsp;&lt;part name="return" type="xsd:string"/&gt;
><br> 
140        &lt;/message&gt;<br>
141        <br>
142        &lt;portType name="BabelFishPortType"&gt;<br>
143        &nbsp;&nbsp;&lt;operation <span class="color1">name="Babe
>lFish"</span>&gt;<br> 
144        &nbsp;&nbsp;&nbsp;&nbsp;&lt;input message="tns:BabelFishR
>equest"/&gt;<br> 
145        &nbsp;&nbsp;&nbsp;&nbsp;&lt;output message="tns:BabelFish
>Response"/&gt;<br> 
146        &nbsp;&nbsp;&lt;/operation&gt;<br>
147        &lt;/portType&gt; <b>Figure 2.</b> Handling the callback.
148      </p>
149    </div>
150    <h3 name="Example">
151      Example
152    </h3>
153    <p>
154      This example takes the parts shown in previous figures and 
>creates a fully working example of how to call the BabelFish web  
>service to translate an user inputted string. 
155    </p>
156    <p>
157      The user is given a form to fill out, with two dropdowns an
>d an input field. The first dropdown (id="lang_from") contains th 
>e language to translate from, and the second (id="lang_to") has t 
>he language to translate to. The input is used to enter the strin 
>g that will be translated. There is also a button labeled "transl 
>ate", which calls the function <tt>initTranslation</tt>. The func 
>tion gets the chosen languages from the form and checks if they a 
>re the same. If they are different, the function <tt>Translate</t 
>t> is called. The Babel Fish web service takes in two methods: a  
>string of the format fromLanguage_toLanguage and the string to tr 
>anslate. 
158    </p>
159    <div class="figure">
160      <pre>
161function initTranslation(){
162  var fromLang = document.getElementById('lang_from').value;
163  var toLang = document.getElementById('lang_to').value;
164 
165  if (fromLang != toLang)
166    Translate(fromLang+'_'+toLang, document.getElementById('input
>Value').value); 
167  else
168    alert("Translating a language to itself is kinda useless :)")
>; 
169}
170</pre>
171      <p>
172        <b>Figure 3.</b> Initializing the translation
173      </p>
174    </div>
175    <p>
176      The <tt>Translate</tt> function is the one that actually ta
>kes care of the web service call. It first checks if a proxy obje 
>ct has already been created by checking if the global variable <t 
>t>gProxy</tt> is not <tt>null</tt>. If it is null, then a creatio 
>n listener is generated and stored into a variable called <tt>lis 
>tener</tt>. It then calls the function <tt>createProxy</tt> with  
>the creation listener. If however the proxy was already created,  
>the <tt>requestTranslation</tt> function is called. 
177    </p>
178    <div class="figure">
179      <p>
180        var gProxy = null;<br>
181        <br>
182        function Translate(aLangToFrom, aString){<br>
183        &nbsp;&nbsp;if (!gProxy) {<br>
184        &nbsp;&nbsp;&nbsp;&nbsp;var listener = {<br>
185        <br>
186        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// gets called once t
>he proxy has been instantiated<br> 
187        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onLoad: function (aPr
>oxy)<br> 
188        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
189        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gProxy = 
>aProxy;<br> 
190        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gProxy.se
>tListener(listener);<br> 
191        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;requestTr
>anslation(aLangToFrom, aString);<br> 
192        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br>
193        <br>
194        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// gets called if an 
>error occurs<br> 
195        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onError: function (aE
>rror)<br> 
196        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
197        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert("An
> error has occured: " + aError);<br> 
198        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br>
199        <br>
200        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// callback function 
>is hardcoded to {methodname}Callback<br> 
201        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BabelFishCallback &nb
>sp;: function (aResult)<br> 
202        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
203        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.
>getElementById("results").innerHTML = aResult;<br> 
204        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
205        &nbsp;&nbsp;&nbsp;&nbsp;};<br>
206        <br>
207        &nbsp;&nbsp;&nbsp;&nbsp;<span class="color1">createProxy(
>listener)</span>;<br> 
208        &nbsp;&nbsp;} else {<br>
209        &nbsp;&nbsp;&nbsp;&nbsp;<span class="color2">requestTrans
>lation(aLangToFrom, aString)</span>;<br> 
210        &nbsp;&nbsp;}<br>
211        }<br>
212        <br>
213        function <span class="color1">createProxy</span>(aCreatio
>nListener){<br> 
214        &nbsp;&nbsp;try {<br>
215        &nbsp;&nbsp;&nbsp;&nbsp;var factory = new WebServiceProxy
>Factory();<br> 
216        &nbsp;&nbsp;&nbsp;&nbsp;factory.createProxyAsync("<a clas
>s=" external" href="http://www.xmethods.net/sd/2001/BabelFishServ 
>ice.wsdl" rel="freelink">http://www.xmethods.net/sd/2001/BabelFis 
>hService.wsdl</a>", "BabelFishPort", "", true, aCreationListener) 
>;<br> 
217        &nbsp;&nbsp;} catch (ex) {<br>
218        &nbsp;&nbsp;&nbsp;&nbsp;alert("Failed creating the proxy:
> "+ ex);<br> 
219        &nbsp;&nbsp;}<br>
220        }<br>
221        <br>
222        function <span class="color2">requestTranslation</span>(a
>LangToFrom, aString){<br> 
223        &nbsp;&nbsp;if (gProxy) {<br>
224        &nbsp;&nbsp;&nbsp;&nbsp;gProxy.BabelFish(aLangToFrom, aSt
>ring);<br> 
225        &nbsp;&nbsp;} else {<br>
226        &nbsp;&nbsp;&nbsp;&nbsp;alert("Error: Proxy hasn't been s
>et up correctly!");<br> 
227        &nbsp;&nbsp;}<br>
228        }<br>
229        <b>Figure 4.</b> Proxy generation
230      </p>
231    </div>
232    <p>
233      <tt>createProxy</tt> is run the first time a translation is
> requested. It instantiates a <tt>WebServiceProxyFactory</tt> and 
> creates a new proxy using <tt>createProxyAsync</tt>, which uses  
>the creation listener. Once the proxy has been created, the <tt>o 
>nLoad</tt> method defined in the creation listener is called. It  
>stores the generated proxy in the global <tt>gProxy</tt> variable 
>, sets the listener to be the creation listener and calls <tt>req 
>uestTranslation</tt>, as the proxy is now ready to be used. 
234    </p>
235    <p>
236      The <tt>requestTranslation</tt> function calls the <tt>Babe
>lFish</tt> method on the proxy to initiate the web service call.  
>If the call is sucessfull, the <tt>BabelFishCallback</tt> method  
>in the creation listener is called, which writes out the translat 
>ed value into a <tt>div</tt>. If the call failed for some reason  
>(such as a SOAP fault was returned), <tt>onError</tt> is called. 
237    </p>
238    <p>
239      The full example can be seen{{ mediawiki.external('example.
>html here') }} (requires Netscape 7.1/Mozilla 1.4 or above). 
240    </p>
241    <h3 name="The_security_model">
242      The security model
243    </h3>
244    <p>
245      One problem facing web services support in the browser is t
>he cross-domain security model. JavaScript is limited to only bei 
>ng able to load data from the same domain the JavaScript lives on 
>. For example, Netscape.com can only load XML using <a href="en/X 
>MLHttpRequest">XMLHttpRequest</a> from the netscape.com domain, a 
>nd not from foo.com. If a site is to be able to connect to a remo 
>ve web service, a new security model is required. 
246    </p>
247    <p>
248      Netscape has proposed a security model to the W3C in which 
>the web service provider determines if the web service is accessi 
>ble by anyone, from certain domains only, or not at all from the  
>Internet. An in-depth look at the security model can be found at  
>{{ Source("extensions/webservices/docs/New_Security_Model.html")  
>}}. In brief, the web service provider has to put an XML file in  
>the top level directory where the web service is located. In the  
>case of <a class="external" href="http://www.xmethods.net">XMetho 
>ds</a>, it is located at <a class=" external" href="http://servic 
>es.xmethods.net/web-scripts-access.xml" rel="freelink">http://ser 
>vices.xmethods.net/web-scripts-access.xml</a> and allows any doma 
>in to contact the web service. This is why the example in this ar 
>ticle can contact a cross-domain server. 
249    </p>{{ languages( { "fr": "fr/Services_Web_XML/Acc\u00e9der_\
>u00e0_des_services_web_avec_Mozilla_en_utilisant_un_proxy_WSDL" } 
> ) }} 

Back to History