/[svn]/website/trunk/web/cduce_ws.xml
ViewVC logotype

Contents of /website/trunk/web/cduce_ws.xml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4075 - (show annotations)
Tue Feb 21 06:03:32 2012 UTC (15 months, 4 weeks ago) by jmaloberti
File MIME type: text/xml
File size: 15853 byte(s)
Typos.
1 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
2 <page name="cduce_ws">
3
4 <title>CDuce_WS</title>
5 <left>
6 <p>
7 This page is an introduction to CDuce_WS.
8 </p>
9 <boxes-toc/>
10 <p>See also:</p>
11 <local-links href="index,memento,manual,tutorial"/>
12 </left>
13
14 <box title="Introduction" link="intro">
15
16 <p>
17 CDuce_WS is a library for Web Services prototyping. It can be used alone
18 for the creation of clients programs, and
19 with <a href="http://ocsigen.org/occduce">OcCDuce</a> for servers.
20 </p>
21 <p> Basically, CDuce_WS is a CDuce representation of the SOAP protocol
22 structures (SOAP Envelope, SOAP Encoding, etc.) with some helper
23 functions to ease the programmation of Web Services.
24 Additionally, a WSDL structure is also provided, as well as some
25 functions (adapted from
26 <a href="http://forge.ocamlcore.org/projects/ocsoap/">OCSoap</a>) to
27 extract useful information from a WSDL file.
28 </p>
29 </box>
30 <box title="Installation" link="install">
31 <p>
32 CDuce_WS requires:
33 </p>
34 <ul>
35 <li><a href="http://www.cduce.org">CDuce</a></li>
36 <li><a href="http://sourceforge.net/projects/ocurl/">Ocurl</a></li>
37 <li><a href="http://projects.camlcity.org/projects/findlib.html">ocamlfind</a></li>
38 <li>and <a href="http://ocsigen.org/occduce/">OcCduce</a> if you want to use CDuce_WS to create
39 servers.</li>
40 </ul>
41 <p> Alternatively, you can use
42 <a href="http://godi.camlcity.org/godi/index.html">GODI</a> to
43 compile and install all the dependencies.
44 </p>
45 <p>You must first download the archive
46 file of <a href="download/cduce_ws-0.1.tar.gz"> version 0.1</a> and
47 untar it in a temporary directory.
48 </p>
49 <p>
50 To compile and install it, executes
51 <code>make</code> and <code>make install</code> in the base directory.
52 </p>
53 <p>
54 You should look in the <b>examples</b> directory and try to compile
55 and install them, once CDuce_WS is installed.
56 </p>
57 </box>
58 <box title="First example" link="first">
59 <p>
60 This example corresponds to the example in the directory: examples/echo/.
61 <br/>
62 It is a very simple service that receives an integer from a client and
63 sends it back.
64 <br/>
65 The first file, <b>common.cd</b>, contains all the declarations used by
66 the client and the server, and is included by all other files.
67 The type <b>Msg</b> corresponds to the information that a client sends
68 to the server, while the type <b>Answer</b> embeds the response from
69 the server to the client.
70 </p>
71 <sample><![CDATA[(* file common.cd *)
72
73 namespace on;;
74 using SoapEnv = "soapenv";;
75 namespace ns = "urn:echo"
76
77 type Msg = <ns:echoInteger>[
78 <inputInteger>Latin1
79 ];;
80
81 type Answer = <ns:echoIntegerResponse> [
82 <return>Latin1
83 ];;
84 ]]></sample>
85
86 <p>The next file, <b>ws_echo.cd</b>, contains the code necessary
87 to register a web service in Ocsigen, via OcCduce.
88 <br/>
89 The call to <b>Lib.register_webservice</b> registers 2
90 services in Ocsigen:
91 </p>
92 <ul>
93 <li> <code>wsEcho</code>, which is called when a client requests the URL with
94 the POST method. The first argument corresponds to the POST
95 parameters, the second argument to the GET parameters and the third
96 one is the content of the request. POST and GET parameters are
97 empty in case of a web service. The content of the request is the
98 SOAP message as a string (actually a Latin1 string).</li>
99 <li> <code>wsError</code>, which is called if the client uses the
100 GET method (hopefully, it should not happen). </li>
101 </ul>
102 <p><b>NOTE1:</b> it is not possible to load more than once the same
103 CDuce program in OcCDuce. Therefore, you should never give the same
104 name to the source files of different services if you plan to load
105 them simultaneously.
106 </p>
107 <p>
108 <b>NOTE2:</b> Sometimes, the namespaces used by the client and the
109 server do not match. This problem can be avoided by using 3
110 functions: <code>Cduce_ws.load_xml_subst</code>,
111 <code>Cduce_ws.print_xml_subst</code>,
112 and <code>Occduce_lib.set_subst_uri</code>.
113 Both load_xml_subst and print_xml_subst are equivalent to load_xml and
114 print_xml with an additional parameter, a list of pairs of URIs. For
115 each pair of URIs, the first one is the original (i.e. used in the
116 in the other parameter), and the second URI is the new URI. Every
117 original URI will be substituted by the new one in the returned
118 value.
119 <br/>
120 <code>set_subst_uri</code> also takes a list of pairs of URIs as a
121 parameter, and it must be used <b>before</b> returning the
122 XML value in the server. The namespaces of the XML value returned
123 will be converted before it is sent to the client.
124 </p>
125
126 <sample><![CDATA[(* file ws_echo.cd *)
127
128 include "../common.cd"
129 using Echo = "echo";;
130 using Lib = "occduce_lib";;
131
132 let wsError (_ : []) : AnyXml =
133 SoapEnv.std_soap_fault;;
134
135 let wsEcho (_ : []) (_ : []) (content : Latin1) : AnyXml =
136 Occduce.debug_string "wsEcho\n";
137 try
138 (let a = Echo.echo content in
139 Occduce.set_subst_uri
140 [("http://schemas.xmlsoap.org/soap/envelope",
141 "http://schemas.xmlsoap.org/soap/envelope/")];
142 a)
143 with err & Latin1 ->
144 Occduce.debug_string [ 'Cduce exception: ' !err '\n'];
145 exit 2;;
146
147 let ws_echo =
148 Lib.register_webservice
149 { path = ["ws_echo"]; serviceName = "wsEcho" }
150 wsEcho wsError
151 ]]></sample>
152 <p>
153 The next file, <b>echo.cd</b>, contains the processing of the SOAP
154 message and the generation of the response message.
155 <br/>
156 <code>load_xml_subst</code> converts the string containing the SOAP
157 message in a SOAP XML structure after the substitution of the URIs
158 (obviously, using namespaces substitution in the server and client
159 code is not useful).
160 <br/>
161 The body of the SOAP structure, a list of AnyXml, is extracted with the
162 function <code>SoapEnv.get_body</code>, while the
163 function <code>SoapEnv.hd</code> returns the first XML structure in
164 the list.
165 <br/>
166 After the processing of the message and the creation of the response
167 message, <code>SoapEnv.add_envelope</code> embeds it in a SOAP envelope.
168 </p>
169 <sample><![CDATA[(* file echo.cd *)
170
171 include "../common.cd"
172
173 let echo (s : Latin1) : SoapEnv.Envelope =
174 let xml = Cduce_ws.load_xml_subst [ 'string:' !s]
175 [("http://schemas.xmlsoap.org/soap/envelope",
176 "http://schemas.xmlsoap.org/soap/envelope/")]
177 in
178 let res = SoapEnv.hd (SoapEnv.get_body xml) in
179 let tmp :? Msg = res in
180 let number = (match tmp with <ns:echoInteger>[<inputInteger>n] -> n)
181 in
182 let msg =
183 <ns:echoIntegerResponse>[
184 <return> number
185 ] in
186 SoapEnv.add_envelope msg;;
187 ]]></sample>
188 <p>
189 The last file, <b>client.cd</b>, executes the following steps:
190 </p>
191 <ul>
192 <li>it creates a message of type Msg. <br/>
193 <b>NOTE: </b>Since we need to
194 use <code>load_xml</code> or <code>load_xml_subst</code> to convert the string in XML, it is
195 not possible to use primitive types such as integer in the types
196 transmitted between the client and the server. We can only use
197 Latin1 strings</li>
198 <li>the message is embedded in a SOAP envelope
199 using <code>SoapEnv.add_envelope</code>, and converted as a string by
200 <code>print_xml_subst</code>.</li>
201 <li>the string message is sent to the server
202 with <code>Cduce_ws.send</code>, where the parameters are: the
203 message string, the host address, the soap action, and the content
204 type.
205 <br/> The returned value of <code>send</code> is a Latin1 string
206 with the response message in SOAP.
207 </li>
208 <li>the response message is converted back in XML by <code>load_xml_subst</code>.</li>
209 <li>the body part of the SOAP response is extracted
210 using <code>SoapEnv.get_body</code>, and printed.</li>
211 </ul>
212 <sample><![CDATA[(* file client.cd *)
213
214 include "../common.cd"
215 let msg : Msg =
216 <ns:echoInteger>[
217 <inputInteger>['1234567890']
218 ];;
219
220 let _ =
221 let string_msg = Cduce_ws.print_xml_subst (SoapEnv.add_envelope msg)
222 [("http://schemas.xmlsoap.org/soap/envelope/",
223 "http://schemas.xmlsoap.org/soap/envelope")]
224 in
225 let answer_string = Cduce_ws.send string_msg
226 "http://localhost/ws/ws_echo" "" "text/xml; charset=utf-8" in
227 print [ 'CDuce: ' !answer_string '\n'];
228 let xml = Cduce_ws.load_xml_subst [ 'string:' !answer_string]
229 [("http://schemas.xmlsoap.org/soap/envelope",
230 "http://schemas.xmlsoap.org/soap/envelope/")]
231 in
232 print (string_of (SoapEnv.get_body xml));;
233 ]]></sample>
234 </box>
235 <box title="A more advanced example" link="calc">
236 <p>
237 This example corresponds to the example in the directory: examples/calc/ in the CDuce_WS distribution.
238 <br/>
239 It is a simple calculator over integer values that receive two values
240 with an operator from a client and return the result.
241 <br/>
242 The first file, <b>common.cd</b>, contains all the declarations used by
243 the client and the server, and is included by all other files.
244 The type <b>Operation</b> corresponds to all possible operations that
245 a client can send
246 to the server, while the type <b>Response</b> embeds the result sent by
247 the server to the client.
248 </p>
249
250 <sample><![CDATA[(* file common.cd *)
251
252 namespace on;;
253 namespace ns = "urn:calc"
254 using SoapEnv = "soapenv";;
255
256 type Params = [ <a>Latin1 <b>Latin1 ];;
257 type AddIn = <ns:add>Params;;
258 type SubIn = <ns:sub>Params;;
259 type MulIn = <ns:mul>Params;;
260 type DivIn = <ns:div>Params;;
261 type Result = <result>Latin1;;
262 type AddOut = <ns:addResponse>[Result];;
263 type SubOut = <ns:subResponse>[Result];;
264 type MulOut = <ns:mulResponse>[Result];;
265 type DivOut = <ns:divResponse>[Result];;
266 type Operation = AddIn | SubIn | MulIn | DivIn;;
267 type Response = AddOut | SubOut | MulOut | DivOut;;
268 ]]></sample>
269
270 <p>The next file, <b>ws_calc.cd</b>, contains the code necessary
271 to register a web service in Ocsigen, via OcCduce.
272 <br/>
273 It is quite similar to the code from the previous example.
274 </p>
275
276 <sample><![CDATA[(* file ws_calc.cd *)
277
278 include "../common.cd"
279 using Calc = "calc";;
280 using Lib = "occduce_lib";;
281
282 let wsError (_ : []) : AnyXml =
283 SoapEnv.std_soap_fault;;
284
285 let wsCalc (_ : []) (_ : []) (content : Latin1) : AnyXml =
286 Occduce.debug_string "wsCalc\n";
287 try (Calc.calc content)
288 with err & Latin1 ->
289 Occduce.debug_string [ 'Cduce exception: ' !err '\n'];
290 exit 2;;
291
292 let ws_calc =
293 Lib.register_webservice
294 { path = ["ws_calc"]; serviceName = "wsCalc" }
295 wsCalc wsError
296 ]]></sample>
297
298 <p>
299 The next file, <b>calc.cd</b>, contains the processing of the SOAP
300 message and the generation of the response message.
301 <br/>
302 <code>load_xml</code> converts the string containing the SOAP
303 message in a SOAP XML structure which is passed
304 to <code>SoapEnv.get_body</code> and <code>SoapEnv.hd</code> to
305 extract the content of the body of the SOAP structure.
306 <br/>
307 The function <code>compute</code> processes the message and returns a
308 result in a response message, which is embedded in a SOAP envelope by <code>SoapEnv.add_envelope</code>.
309 </p>
310
311 <sample><![CDATA[(* file calc.cd *)
312
313 include "../common.cd"
314 using SoapEnv = "soapenv";;
315
316 (* For a finer-grained type-checking, declare the
317 function compute with the following type declaration:
318
319 let compute ( AddIn -> AddOut,
320 SubIn -> SubOut,
321 MulIn -> MulOut,
322 DivIn -> DivOut )
323 | <ns:add>[<a>a <b>b] ->
324 <ns:addResponse>[<result>(string_of ((int_of a) + (int_of b)))]
325 | <ns:sub>[<a>a <b>b] ->
326 <ns:subResponse>[<result>(string_of ((int_of a) - (int_of b)))]
327 | <ns:mul>[<a>a <b>b] ->
328 <ns:mulResponse>[<result>(string_of ((int_of a) * (int_of b)))]
329 | <ns:div>[<a>a <b>b] ->
330 <ns:divResponse>[<result>(string_of ((int_of a) div (int_of b)))];;
331 *)
332
333 let compute (op : Operation) : Response =
334 match op with
335 <ns:add>[<a>a <b>b] ->
336 <ns:addResponse>[<result>(string_of ((int_of a) + (int_of b)))]
337 | <ns:sub>[<a>a <b>b] ->
338 <ns:subResponse>[<result>(string_of ((int_of a) - (int_of b)))]
339 | <ns:mul>[<a>a <b>b] ->
340 <ns:mulResponse>[<result>(string_of ((int_of a) * (int_of b)))]
341 | <ns:div>[<a>a <b>b] ->
342 <ns:divResponse>[<result>(string_of ((int_of a) div (int_of b)))];;
343
344 let calc (s : Latin1) : SoapEnv.Envelope =
345 let xml = load_xml [ 'string:' !s] in
346 let res = SoapEnv.hd (SoapEnv.get_body xml) in
347 let op :? Operation = res in
348 let answer = compute op in
349 SoapEnv.add_envelope answer;;
350 ]]></sample>
351
352 <p>
353 The last file, <b>client.cd</b>, executes the following steps:
354 </p>
355 <ul>
356 <li>it creates a message of type Operation. </li>
357 <li>the message is embedded in a SOAP envelope
358 using <code>SoapEnv.add_envelope</code></li>
359 <li>it is then converted as a string by
360 <code>print_xml</code> and sent to the server
361 with <code>Cduce_ws.send</code>, where the parameters are: the
362 message string, the host address, the soap action, and the content
363 type.
364 <br/> The returned value of <code>send</code> is a Latin1 string
365 with the response message in SOAP.
366 </li>
367 <li>the response message is converted back in XML by <code>load_xml</code>.</li>
368 <li>the body part of the SOAP response is extracted
369 using <code>SoapEnv.get_body</code>, and printed.</li>
370 </ul>
371
372 <sample><![CDATA[(* file client.cd *)
373
374 include "../common.cd"
375 using SoapEnv = "soapenv";;
376
377 let msg :? Operation = <ns:add>[ <a>"24" <b>"18" ];;
378
379 let _ =
380 let msg_soap = SoapEnv.add_envelope msg in
381 let answer_string = Cduce_ws.send (print_xml msg_soap)
382 "http://localhost/ws/ws_calc" "" "text/xml; charset=utf-8" in
383 print [ 'CDuce: ' !answer_string '\n'];
384 let xml = load_xml [ 'string:' !answer_string ] in
385 let soap_answer :? SoapEnv.Envelope = xml in
386 print (string_of (SoapEnv.get_body xml));;
387 ]]></sample>
388
389 </box>
390
391 <box title="WSDL" link="wsdl">
392 <p>
393 You can extract some useful information from WSDL files using
394 functions from the WSDL module.
395 </p>
396 <ul>
397 <li><code>wsdl_load "file.wsdl"</code>: loads a WSDL file in a Wsdl structure.</li>
398 <li><code>wsdl_port_types</code>: extracts the port types from a
399 Wsdl structure.</li>
400 <li><code>show_port_type</code>: prints all the messages of a port type.</li>
401 <li><code>extract_schema</code>: save the xsd schema part of a Wsdl
402 structure in a file.</li>
403 </ul>
404 <p>
405 The following program, <code>wsdl_test.cd</code>, prints the messages
406 from a wsdl file <b>calc.wsdl</b> (you can download it from the <a href="http://gsoap2.sourceforge.net/">gsoap
407 website</a>), and save the xsd part in a file "calc_sch.xsd".
408 </p>
409 <sample><![CDATA[(* wsdl_test.cd *)
410 using WSDL = "wsdl"
411
412 let _ =
413 let w = WSDL.wsdl_load "calc.wsdl" in
414 let port_types = WSDL.wsdl_port_types w in
415 transform port_types with (name,pt) -> WSDL.show_port_type pt name;
416 WSDL.extract_schema w "calc_sch.xsd";;
417 ]]></sample>
418 <p>
419 You need to compile and execute <b>wsdl_test.cd</b> with the following command:
420 </p>
421 <sample><![CDATA[
422 cduce --compile -I `ocamlfind query cduce_ws` wsdl_test.cd
423 cduce --run -I `ocamlfind query cduce_ws` wsdl_test.cdo
424 ]]></sample>
425 <p>
426 The output of <b>wsdl_test.cd</b> is:
427 </p>
428 <sample><![CDATA[calcPortType
429 <ns:add>[ <a>double <b>double ]
430 -> <ns:addResponse>[ <result>double ]
431
432 <ns:sub>[ <a>double <b>double ]
433 -> <ns:subResponse>[ <result>double ]
434
435 <ns:mul>[ <a>double <b>double ]
436 -> <ns:mulResponse>[ <result>double ]
437
438 <ns:div>[ <a>double <b>double ]
439 -> <ns:divResponse>[ <result>double ]
440
441 <ns:pow>[ <a>double <b>double ]
442 -> <ns:powResponse>[ <result>double ]
443 ]]></sample>
444 <p> Which has been translated in the following CDuce code from
445 the <b>calc</b> example:</p>
446 <sample><![CDATA[namespace ns = "urn:calc"
447
448 type Params = [ <a>Latin1 <b>Latin1 ];;
449 type AddIn = <ns:add>Params;;
450 type SubIn = <ns:sub>Params;;
451 type MulIn = <ns:mul>Params;;
452 type DivIn = <ns:div>Params;;
453 type Result = <result>Latin1;;
454 type AddOut = <ns:addResponse>[Result];;
455 type SubOut = <ns:subResponse>[Result];;
456 type MulOut = <ns:mulResponse>[Result];;
457 type DivOut = <ns:divResponse>[Result];;
458 type Operation = AddIn | SubIn | MulIn | DivIn;;
459 type Response = AddOut | SubOut | MulOut | DivOut;;
460 ]]></sample>
461
462 <p>
463 Apart from the conversion of <b>double</b> in <b>Latin1</b>, the
464 translation is quite straightforward.
465 </p>
466 </box>
467 </page>
468
469

CVS Admin">CVS Admin
ViewVC Help
Powered by ViewVC 1.1.5