Compare Revisions

Accessing Web Services in Mozilla Using WSDL Proxying

Revision 70327:

Revision 70327 by Sheppy on

Revision 70328:

Revision 70328 by rawand on

Accessing Web Services in Mozilla Using WSDL Proxying
Accessing Web Services in Mozilla Using WSDL Proxying
"XML Web Services"
"XML Web Services"

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=" 
>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:
>C-8BD920E1B4DD">Babelfish</a> web service provided by <a class="e 
>xternal" href="">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 
>" rel="freelink">htt 
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
>://" rel="freelink" 
>></a>", <spa 
>n style="color:green">"BabelFishPort"</span>, "", true, aCreation 
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 
55      </p>
56      <p>
57        &nbsp;&nbsp;&nbsp;&nbsp;&lt;port <span style="color:green
>">name="BabelFishPort"</span> binding="tns:BabelFishBinding"&gt;< 
58        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;soap:address loca
>tion="<a class=" external" href=" 
>perl/soaplite.cgi" rel="freelink"> 
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 
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  
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 
79   <b>listener:</b> The callback instance which will be invoked w
>hen the proxy is completely initialized. 
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=" 
>ferences/xpcomref/ifaces/nsIWebServiceProxyFactory.html">here her 
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
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
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)
125        &nbsp;&nbsp;} else {<br>
126        &nbsp;&nbsp;&nbsp;&nbsp;alert("Error: Proxy set up not co
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
135        &nbsp;&nbsp;&lt;part name="sourcedata" type="xsd:string"/
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;
140        &lt;/message&gt;<br>
141        <br>
142        &lt;portType name="BabelFishPortType"&gt;<br>
143        &nbsp;&nbsp;&lt;operation <span class="color1">name="Babe
144        &nbsp;&nbsp;&nbsp;&nbsp;&lt;input message="tns:BabelFishR
145        &nbsp;&nbsp;&nbsp;&nbsp;&lt;output message="tns:BabelFish
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 
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;
165  if (fromLang != toLang)
166    Translate(fromLang+'_'+toLang, document.getElementById('input
167  else
168    alert("Translating a language to itself is kinda useless :)")
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
188        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
189        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gProxy = 
190        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
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
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(
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
214        &nbsp;&nbsp;try {<br>
215        &nbsp;&nbsp;&nbsp;&nbsp;var factory = new WebServiceProxy
216        &nbsp;&nbsp;&nbsp;&nbsp;factory.createProxyAsync("<a clas
>s=" external" href=" 
>ice.wsdl" rel="freelink"> 
>hService.wsdl</a>", "BabelFishPort", "", true, aCreationListener) 
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
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, can only load XML using <a href="en/X 
>MLHttpRequest">XMLHttpRequest</a> from the domain, a 
>nd not from 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="">XMetho 
>ds</a>, it is located at <a class=" external" href="http://servic 
>" rel="freelink">http://ser 
></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