1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
|
.. _Using_SOAP:
**********
Using SOAP
**********
.. index:: SOAP
.. index:: Simple Object Access Protocol
`SOAP` can be used to implements Web Services. The `SOAP`
implementation uses `AWS HTTP` as the transport layer. `SOAP` is
platforms and languages independent, to ensure a good
inter-operability, `AWS/SOAP` implementation has been validated through
`http://validator.soapware.org/ <http://validator.soapware.org/>`_, the version number listed on
this server corresponds to the AWS version string
(`AWS.Version`) catenated with the `SOAP` version string
(`SOAP.Version`).
This `SOAP` implementation is certainly one with the higher level
of abstraction. No need to mess with a serializer, to know what is a
payload or be an `XML` expert. All the low level stuffs are
completely hidden as the `SOAP` type system has been binded as
much as possible to the Ada type system.
.. index:: WSDL
.. index:: Web Service Definition Language
The `SOAP` type system has been relaxed to be compatible with
`WSDL` based `SOAP` implementation. In these implementations, types
are generally (as in the Microsoft implementation) not part of the
payload and should be taken from the `WSDL` (Web Services Description
Language). `AWS/SOAP` is not `WSDL` compliant at this stage, all
such types are binded into the Ada type system as strings. It is up to
the programer to convert such strings to the desired type.
.. _SOAP_Client:
SOAP Client
===========
.. index:: SOAP Client
.. highlight:: ada
The `SOAP` client interface is quite simple. Here are the step-by-step
instructions to call a `SOAP` Web Service:
* Build the `SOAP` parameters
As for the `SOAP` servers, the `SOAP` parameters are built using a
`SOAP.Parameters.List` object::
Params : constant Parameters.List := +I (10, "v1") & I (32, "v2");
* Build the `SOAP` Payload
The Payload object is the procedure name and the associated parameters::
declare
Payload : Message.Payload.Object;
begin
Payload := Message.Payload.Build ("Add", Params);
* Call the `SOAP` Web Service
Here we send the above Payload to the Web Server which handles the Web
Service. Let's say that this server is named `myserver`, it is
listening on port `8082` and the `SOAPAction` is `soapdemo`::
Resp : constant Message.Response.Object'Class :=
SOAP.Client.Call ("http://myserver:8082/soapdemo", Payload);
* Retrieve the result
Let's say that the answer is sent back into the parameter named
"myres", to get it::
My_Res : constant Integer := SOAP.Parameters.Get (Params, "myres");
In the above example we have called a Web Service whose spec could be
described in Ada as follow::
function Add (V1, V2 : in Integer) return Integer;
-- Add V1 and V2 and returns the result. In SOAP the result is named "myres"
.. _SOAP_Server:
SOAP Server
===========
.. index:: SOAP Server
.. index:: SOAPAction
A `SOAP` server implementation must provides a callback procedure as for
standard Web server :ref:`Callback_procedure`. This callback must
checks for the `SOAP` Action URI to handle both standard Web requests
and `SOAP` ones. The `SOAPAction` is sent with the HTTP headers and
can be retrieved using `AWS.Status.SOAPAction`.
.. _Step_by_step_instructions:
Step by step instructions
-------------------------
Here are the step-by-step instructions to be followed in the `SOAP`
callback procedure:
* Retrieve the `SOAP` Payload
.. index:: Payload
The `SOAP` Payload is the `XML` message, it contains the
procedure name to be called and the associated parameters::
function SOAP_CB (Request : in AWS.Status.Data) return AWS.Response.Data is
use SOAP.Types;
use SOAP.Parameters;
Payload : constant SOAP.Message.Payload.Object :=
SOAP.Message.XML.Load_Payload (AWS.Status.Payload (Request));
`AWS.Status.Payload` returns the `XML` Payload as sent by
the `SOAP` Client. This `XML` Payload is then parsed using
`SOAP.Message.XML.Load_Payload` which returns a
`SOAP.Message.Payload.Object` object.
* Retrieve the `SOAP` Parameters
The `SOAP` procedure's parameters::
Params : constant SOAP.Parameters.List :=
SOAP.Message.Parameters (Payload);
`SOAP.Parameters.List` is a structure which holds the `SOAP`
parameters. Each parameter can be retrieved using a
`SOAP.Parameters` API, :ref:`SOAP.Parameters`. For example to
get the parameter named `myStruc` which is a `SOAP` struct::
My_Struct : constant SOAP_Record :=
SOAP.Parameters.Get (Params, "myStruct");
Another example, to get the parameter named `myInt` which is a
`SOAP` integer::
My_Int : constant Integer := SOAP.Parameters.Get (Params, "myInt");
* Implements the Web Service
This is the real job, as for any procedure you can do whatever is
needed to compute the result.
* Build the `SOAP` answer
This is the procedure answer. A `SOAP` answer is built from the
`SOAP` Payload and by setting the returned parameters::
declare
Resp : SOAP.Message.Response.Object;
Resp_Params : SOAP.Parameters.List;
begin
Resp := SOAP.Message.Response.From (Payload);
Resp_Params := +I (My_Int * 2, "answer");
SOAP.Message.Set_Parameters (Resp, Resp_Params);
This build a response which is a single integer value named
`answer` with the value `My_Int * 2`.
* Returns the answer back to the client
This last step will encode the response object in `XML` and will
returns it as the body of an `HTTP` message::
return SOAP.Message.Response.Build (Resp);
.. _SOAP_helpers:
SOAP helpers
------------
There is two ways to help building the `SOAP`
callbacks. `AWS` provides a `SOAP` specific callback, the spec is::
function SOAP_Callback
(SOAPAction : in String;
Payload : in Message.Payload.Object;
Request : in AWS.Status.Data) return AWS.Response.Data;
With both solutions exposed below, `AWS` retrieve the
`SOAPAction` and the Payload from the `SOAP` request. This
is transparent to the user.
* Using Utils.SOAP_Wrapper
.. index:: Utils.SOAP_Wrapper
It is possible to dispatch to such callback by using the
`SOAP.Utils.SOAP_Wrapper` generic routine::
generic
with function SOAP_CB
(SOAPAction : in String;
Payload : in Message.Payload.Object;
Request : in AWS.Status.Data) return AWS.Response.Data;
function SOAP_Wrapper
(Request : in AWS.Status.Data) return AWS.Response.Data;
-- From a standard HTTP callback call the SOAP callback passed as generic
-- formal procedure. Raise Constraint_Error if Request is not a SOAP
-- request.
For example, from the standard HTTP callback `CB` we want to call
`SOAP_CB` for all `SOAP` requests::
function SOAP_CB
(SOAPAction : in String;
Payload : in Message.Payload.Object;
Request : in AWS.Status.Data) return AWS.Response.Data is
begin
-- Code here
end SOAP_CB;
procedure SOAP_Wrapper is new SOAP.Utils.SOAP_Wrapper (SOAP_CB);
function CB (Request : in AWS.Status.Data) return AWS.Response.Data is
SOAPAction : constant String := Status.SOAPAction (Request);
begin
if SOAPAction /= "" then
SOAP_Wrapper (Request);
else
...
* Using a SOAP Dispatcher
.. index:: SOAP Dispatcher
`AWS` provides also a `SOAP` specific dispatcher. This
dispatcher will automatically calls a standard `HTTP` or
`SOAP` callback depending on the request. If `SOAPAction` is
specified (i.e. it is a `SOAP` request), the dispatcher will call
the `SOAP` callback otherwise it will call the standard `HTTP`
callback. This is by far the easiest integration procedure. Using
dispatcher the above code will be written::
function SOAP_CB
(SOAPAction : in String;
Payload : in Message.Payload.Object;
Request : in AWS.Status.Data) return AWS.Response.Data is
begin
-- Code here
end SOAP_CB;
function CB (Request : in AWS.Status.Data) return AWS.Response.Data is
SOAPAction : constant String := Status.SOAPAction (Request);
begin
-- Code here
end CB;
-- In the main procedure
begin
AWS.Server.Start
(WS,
Dispatcher =>
SOAP.Dispatchers.Callback.Create (CB'Access, SOAP_CB'Access),
Config =>
AWS.Config.Default_Config);
.. index:: SOAP.Dispatchers.Callback
The dispacther is created using `SOAP.Dispatchers.Callback.Create`.
This routine takes two parameters, one is the standard HTTP
callback procedure and the other is the `SOAP` callback procedure.
|