$Id: index.html,v 1.3 2005/05/23 20:48:40 rich Exp $
SimpleSOAP is an early, experimental SOAP client for Objective CAML.
It was written by Richard W.M. Jones. For updates, please see the Merjis developers' website. For support please post on the OCaml mailing lists.
To call a remote SOAP service, you have to define
the URL(s) of the service, and the types and functions
accepted by the service. With SimpleSOAP you do this
by writing an interface file, which looks similar to
an ordinary OCaml .mli file.
For example:
URI "http://localhost:8080/campaign_service"
type campaign = {
dailyBudget : int;
id : int;
name : string;
}
val set_campaign : campaign -> unit
val get_campaign : unit -> campaign
This file is then parsed, using a set of camlp4 macros, into stub functions (written in OCaml).
You can then call these stub functions in the usual
way, eg. let campaign = Campaign_service.get_campaign ().
The stub functions actually handle the details of
making the SOAP call to the remote server and
parsing the reply.
Because SimpleSOAP is at a very early stage of development, you may find that you need to examine, and possibly even fix, the stub functions generated. This is possible, and is discussed below.
SimpleSOAP uses PXP, ocamlnet and equeue to generate XML and issue HTTP requests to servers.
SimpleSOAP comes with a library of useful functions and
types, in a module called SimpleSOAP. See
simpleSOAP.mli for a description of the
functions available.
The stub functions use helpers to complete their work.
These are located in the SimpleSOAP.Helpers
module, and should not be called directly by other code.
Once you have written your interface file, which must
have extension .ml (even though it looks
like an mli file), compile it into stubs using:
ocamlc -I +pcre -I +equeue -I +netstring -I +netclient -I +pxp-engine \
-pp "camlp4o ./pa_soapclientstubs.cmo" \
-I +camlp4 -c your_api.ml
You could also use ocamlopt.
To debug SimpleSOAP, you should be able to see the generated stubs. To print these out, use:
camlp4o ./pa_soapclientstubs.cmo pr_o.cmo your_api.ml | less
Interface files have the general form:
type declarations URI "url" function prototypes
Type declarations look just like ordinary OCaml types, for example:
type campaign = {
dailyBudget : int;
id : int;
name : string;
}
The URI line gives the URL (actually the "namespace") of the service. This will be given to you by the service provider.
Function prototypes look like ordinary OCaml function
declarations, as found in .mli files, for
example:
val set_campaign : campaign -> unit val get_campaign : unit -> campaign
You can have several "URI" lines in the file - each one affects subsequent function prototypes until the next URI line is reached.
For each function prototype, two functions are in fact generated, and neither looks exactly like the prototype. For example a function declared as:
val get_campaign : unit -> campaign
generates these two actual functions which you can call:
val get_campaign : ?soap:SimpleSOAP.extra_in -> unit -> campaign val get_campaign__x : ?soap:SimpleSOAP.extra_in -> unit -> campaign * SimpleSOAP.extra_out
The optional ?soap parameter carries
extra information into the function. Normally you
will never use it, but it can be used to send
extra headers in the SOAP request, which some
services will require.
The variant function get_campaign__x
returns the normal result and extra data in a tuple.
The extra data contains, among other things, extra
headers returned in the SOAP response.
For each type declaration, two functions are generated, although generally you will never need to call them directly:
val name_of_soap : SimpleSOAP.Helpers.node -> name val soap_of_name : name -> SimpleSOAP.Helpers.node
Only basic OCaml types, types declared in type declarations, and lists of these, are permitted as parameters to stubs.
The return value from a stub is similarly limited.
SOAP can, in theory, return multiple values from a single call. This is rarely used because so few languages actually allow it. At present we don't support this, but we may do so in future.
Records containing option-al fields are
handled specially, but optional values elsewhere probably
won't be understood by any server.
SOAP supports sending type information with parameters, but at the moment we neither send type information, nor understand it in the response.
Ocamlnet does not support SSL, but you can still call https services with the help of stunnel.
You will need to run stunnel in client
proxy mode, as follows:
stunnel -c -d 8081 -r remote.example.com:https
Modify your URI lines so that instead of referencing the remote server, they reference the stunnel endpoint, eg.:
URI "http://localhost:8081/remote_service/"