6. Using WSDL

WSDL (Web Service Definition Language) is an XML based document which described a set of Web Services either based on SOAP or XML/RPC. By using a WSDL document it is possible to describe, in a formal way, the interface to any Web Services. The WSDL document contains the end-point (URL to the server offering the service), the SOAPAction (needed to call the right routine), the procedure names and a description of the input and output parameters.

AWS provides two tools to work with WSDL documents:

ada2wsdl

which creates a WSDL document from an Ada package spec.

wsdl2aws

which create the interfaces to use a Web Service or to implement Web Services. With this tool the SOAP interface is completely abstracted out, users will deal only with Ada API. All the SOAP marshaling will be created automatically.

6.1. Creating WSDL documents

Note that this tool is based on LibAdaLang.

6.1.1. Using ada2wsdl

ada2wsdl can be used on any Ada spec file to generated a WSDL document. The Ada spec is parsed using LibAdaLang.

The simplest way to use it is:

$ ada2wsdl simple.ads

Given the following Ada spec file:

package Simple is
   function Plus (Value : in Natural) return Natural;
end Simple;

It will generate the following WSDL document:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="Simple"
   targetNamespace="http://soapaws/Simple_def/"
   xmlns:tns="http://soapaws/Simple_def/"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:n1="http://soapaws/Standard_pkg/"
   xmlns:n2="http://soapaws/Simple_pkg/">

   <!-- Generated by AWS/Ada2WSDL v1.3.1
        on Tuesday 25 November 2014 at 11:02:44 -->

   <wsdl:message name="Plus_Request">
      <wsdl:part name="Value" type="xsd:int"/>
   </wsdl:message>

   <wsdl:message name="Plus_Response">
      <wsdl:part name="Result" type="xsd:int"/>
   </wsdl:message>

   <wsdl:portType name="Simple_PortType">
      <wsdl:operation name="Plus">
         <wsdl:input message="tns:Plus_Request"/>
         <wsdl:output message="tns:Plus_Response"/>
      </wsdl:operation>
   </wsdl:portType>

   <wsdl:binding name="Simple_Binding" type="tns:Simple_PortType">
      <soap:binding style="rpc"
         transport="http://schemas.xmlsoap.org/soap/http"/>

      <wsdl:operation name="Plus">
         <soap:operation soapAction="Plus"/>
         <wsdl:input>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="http://soapaws/Simple_def/"
               use="encoded"/>
         </wsdl:input>
         <wsdl:output>
            <soap:body
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="http://soapaws/Simple_def/"
               use="encoded"/>
         </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>

   <wsdl:service name="Simple_Service">
      <wsdl:port name="Simple_Port" binding="tns:Simple_Binding">
         <soap:address location="http://.../"/>
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>

The value of the name attribute in the description node is the name of the WSDL document (the name of the Ada spec package). On the portType section we have the description of the Ada Plus function. Something important to note is that in Ada a function does not have a named return parameter, ada2wsdl use Result for the response. Both the input and output parameter are mapped to SOAP xsd:int type.

Note that the SOAP address generated by default (http://…/) must be edited manually or specified using ada2wsdl’s -a option.

This is of course a very simple example. ada2wsdl does support more complex specifications and will map Ada records, arrays, enumerations, derived types to a corresponding XML schema definition. See section below for a description of the mapping.

6.1.2. Ada mapping to WSDL

ada2wsdl parses Ada records, arrays, derived types, enumerations, procedures and functions and generates the corresponding WSDL document. In this section we describe the mapping between Ada and WSDL.

Integer

Mapped to xsd:int.

Float

Mapped to xsd:float.

Long_Float

Mapped to xsd:double

Long_Long_Float

Mapped to xsd:double, not supported by SOAP, mapped for convenience but precision cannot be guaranteed.

Boolean

Mapped to xsd:boolean

String

Mapped to xsd:string

Unbounded_String

Mapped to xsd:string, note that Unbounded_String should be used only inside a record for full interoperability. This is a current limitation.

Character

Mapped to a Character schema definition:

<simpleType name="Character">
  <restriction base="xsd:string">
    <length value="1"/>
  </restriction>
</simpleType>
Ada.Calendar.Time

Mapped to xsd:dateTime

Duration

Mapped to xsd:duration

SOAP.Utils.SOAP_Base64

Mapped to xsd:base64Binary. SOAP.Utils.SOAP_Base64 is a subtype of string which is is recognized by ada2wsdl to generate the proper SOAP type.

SOAP.Types.Byte

Mapped to xsd:byte. SOAP.Types.Byte is a type which is recognized by ada2wsdl to generate the proper SOAP type.

SOAP.Types.Short

Mapped to xsd:short. SOAP.Types.Short is a type which is recognized by ada2wsdl to generate the proper SOAP type.

SOAP.Types.Long

Mapped to xsd:long. SOAP.Types.Long is a type which is recognized by ada2wsdl to generate the proper SOAP type.

SOAP.Types.Unsigned_Byte

Mapped to xsd:unsignedByte. SOAP.Types.Unsigned_Byte is a type which is recognized by ada2wsdl to generate the proper SOAP type.

SOAP.Types.Unsigned_Short

Mapped to xsd:unsignedShort. SOAP.Types.Unsigned_Short is a type which is recognized by ada2wsdl to generate the proper SOAP type.

SOAP.Types.Unsigned_Int

Mapped to xsd:unsignedInt. SOAP.Types.Unsigned_Int is a type which is recognized by ada2wsdl to generate the proper SOAP type.

SOAP.Types.Unsigned_Long

Mapped to xsd:unsignedLong. SOAP.Types.Unsigned_Long is a type which is recognized by ada2wsdl to generate the proper SOAP type.

Derived types

Mapped to a type schema definition:

type Number is new Integer;

is defined as:

<simpleType name="Number" targetNamespace="http://soapaws/WSDL_C_pkg/">
  <restriction base="xsd:int"/>
</simpleType>
Derived types with constraints

Mapped to a type schema definition with minInclusive and maxInclusive attributes:

type Number is new Integer range 1 .. 9345;

is defined as:

<simpleType name="Number" targetNamespace="http://soapaws/WSDL_C_pkg/">
  <restriction base="xsd:int">
    <xsd:minInclusive value=" 1"/>
    <xsd:maxInclusive value=" 9345"/>
  </restriction>
</simpleType>

Or for a string:

.. highlight:: ada

type Code is String (1 .. 10);

is defined as:

<simpleType name="Code" targetNamespace="http://soapaws/WSDL_C_pkg/">
  <xsd:restriction base="xsd:string">
    <xsd:Length value="10"/>
  </xsd:restriction>
</simpleType>
Ranges

Mapped to a type schema definition with minInclusive and maxInclusive attributes:

type Small is range 1 .. 10;

is defined as:

<simpleType name="Small" targetNamespace="http://soapaws/WSDL_C_pkg/">
  <restriction base="xsd:byte">
    <xsd:minInclusive value=" 1"/>
    <xsd:maxInclusive value=" 10"/>
  </restriction>
</simpleType>
Modular types

Mapped to an unsigned type with an optional maxInclusive attribute:

type Count is mod 14;

is defined as:

<simpleType name="Count" targetNamespace="http://soapaws/WSDL_C_pkg/">
  <xsd:restriction base="xsd:unsignedByte">
    <xsd:maxInclusive value=" 13"/>
  </xsd:restriction>
</simpleType>
Enumerations

Mapped to an enumeration schema definition. For example:

type Color is (Red, Green, Blue);

is defined as:

<simpleType name="Color">
  <restriction base="xsd:string">
    <enumeration value="Red"/>
    <enumeration value="Green"/>
    <enumeration value="Blue"/>
  </restriction>
</simpleType>
Records

Mapped to a struct schema definition. For example:

type Rec is record
   A : Integer;
   B : Float;
   C : Long_Float;
   D : Character;
   E : Unbounded_String;
   F : Boolean;
end record;

is defined as:

<complexType name="Rec">
  <all>
    <element name="A" type="xsd:int"/>
    <element name="B" type="xsd:float"/>
    <element name="C" type="xsd:double"/>
    <element name="D" type="tns:Character"/>
    <element name="E" type="xsd:string"/>
    <element name="F" type="xsd:boolean"/>
  </all>
</complexType>
Arrays

Mapped to an array schema definition. For example:

type Set_Of_Rec is array (Positive range <>) of Rec;

is defined as:

<xsd:complexType name="Set_Of_Rec">
  <xsd:sequence>
     <xsd:element name="x" type="n1:Rec"
          minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

A SOAP encoded format can be generated with the -sea option:

<complexType name=”Set_Of_Rec”>
<complexContent>
<restriction base=”soap-enc:Array”>

<attribute ref=”soap-enc:arrayType” wsdl:arrayType=”tns:Rec[]”/>

</restriction>

</complexContent>

</complexType>

Array inside a record

This part is a bit delicate. A record field must be constrained but a SOAP arrays is most of the time not constrained at all. To support this AWS use an Ada.Containers.Vectors or a safe access array component (legacy mode). Both support are described below.

Array inside a record (Ada.Containers.Vectors)

Using an Ada.Containers.Vectors is the preferred way of supporting array inside records.

For example, let’s say that we have an array of integer that we want to put inside a record:

type Set_Of_Int is array (Positive range <>) of Integer;

The first step is to create the corresponding Ada.Containers:

package Set_Of_Int_Type is
  new Ada.Containers.Vectors (Positive, Integer);

And then the vectors can be added into the record:

type Complex_Rec is record
   SI : Set_Of_Int_Type.Vectors;
end record;

These Ada definitions are fully recognized by ada2wsdl and will generate standard array and record WSDL definitions as seen above:

<xsd:complexType name="Integer_List_Type">
   <xsd:sequence>
      <xsd:element name="x" type="xsd:int"
                   minOccurs="0" maxOccurs="unbounded"/>
   </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="Complex_Rec">
   <xsd:all>
      <xsd:element name="SI" type="tns:Integer_List_Type"/>
   </xsd:all>
</xsd:complexType>
Array inside a record (legacy)

Using a safe pointer array component to support array inside records. Such a type is built using a generic runtime support package named SOAP.Utils.Safe_Pointers. This package implements a reference counter for the array access and will automatically release the memory when no more reference exist to a given object.

For example, let’s say that we have an array of integer that we want to put inside a record:

type Set_Of_Int is array (Positive range <>) of Integer;

The first step is to create the safe array access support:

type Set_Of_Int_Access is access Set_Of_Int;

package Set_Of_Int_Safe_Pointer is
  new SOAP.Utils.Safe_Pointers (Set_Of_Int, Set_Of_Int_Access);

Note that the name Set_Of_Int_Safe_Pointer (<type>_Safe_Pointer) is mandatory (and checked by ada2wsdl) to achieve interoperability with wsdl2aws. Working with WSDL documents.

From there the safe array access can be placed into the record:

type Complex_Rec is record
   SI : Set_Of_Int_Safe_Pointer.Safe_Pointer;
end record;

To create a Safe_Pointer given a Set_Of_Int one must use Set_Of_Int_Safe_Pointer.To_Safe_Pointer routine. Accessing individual items is done with SI.Item (K).

These Ada definitions are fully recognized by ada2wsdl and will generate standard array and record WSDL definitions as seen above:

<xsd:complexType name="Set_Of_Int">
  <xsd:sequence>
     <xsd:element name="x" type="xsd:int"
          minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

<complexType name="Complex_Rec">
  <all>
    <element name="SI" type="tns:Set_Of_Int"/>
  </all>
</complexType>
Array as routine parameter

When an array is passed as parameter to a SOAP routine it is also required to create a corresponding Ada.Containers.Vectors or a Safe_Pointer when using a Document/Literal binding and using a user’s type package (see -types and ‘-spec wsdl2aws options).

Array as routine parameter (Ada.Containers.Vectors)

This is needed for the AWS generated code to handle this routine. Even if required in a very specific case it is never an error to declare such a Ada.Containers.Vectors for an array.

For example:

type Set_Of_Int is array (Positive range <>) of Integer;

procedure Call (Values : Set_Of_Int);

Then the following declaration is required:

package Set_Of_Int_Type is
  new Ada.Containers.Vectors (Positive, Integer);
Array as routine parameter (legacy)

This is needed for the AWS generated code to handle this routine. Even if required in a very specific case it is never an error to declare such a Safe_Pointer for an array.

For example:

type Set_Of_Int is array (Positive range <>) of Integer;

procedure Call (Values : Set_Of_Int);

Then the following declarations are required:

type Set_Of_Int_Access is access Set_Of_Int;

package Set_Of_Int_Safe_Pointer is
  new SOAP.Utils.Safe_Pointers (Set_Of_Int, Set_Of_Int_Access);

6.1.3. ada2wsdl

Usage: ada2wsdl [options] ada_spec

ada2wsdl options are:

-a url

Specify the URL for the Web Server address. Web Services will be available at this address. A port can be specified on the URL, http://server[:port]. The default value is http://…/.

-f

Force creation of the WSDL file. Overwrite exiting file with the same name.

-doc

Generate document’s style binding (default is RPC)

-lit

Generate literal’s style binding (default is encoded)

-n name

Specify the schema name space root name. The default value is “soapaws”.

-noenum

Do not generate WSDL representation for Ada enumerations, map them to standard string. Ada mapping to WSDL.

-sea

Generate SOAP encoded format for array definitions. This option is kept for compatibility reason, but the schema based definition for arrays is recommended for better interoperability.

-o file

Generate the WSDL document into file.

-P proj

The project file to use for building the spec.

-q

Quiet mode (no output)

-s name

Specify the Web Service name for the WSDL document, by default the spec package’s name is used.

-t path

Specify the path to the tree file directory to use. This is needed when using a project file the object directory is not the current directory.

-d

Do not generate date/time in WSDL.

-v

Verbose mode, display the parsed spec.

6.1.4. ada2wsdl limitations

  • Constrained array field in records unsupported.

  • Unbounded_String are supported with full interoperability only inside a record.

  • Only unconstrained arrays are supported.

  • Arrays with multiple dimensions are not supported.

6.2. Working with WSDL documents

6.2.1. Client side (stub)

This section describe how to use a Web Service. Let’s say that we want to use the Barnes & Noble Price Quote service. The WSDL document for this service can be found at http://www.xmethods.net/sd/2001/BNQuoteService.wsdl. In summary this document says that there is a service named getPrice taking as input a string representing the ISBN number and returning the price as floating point.

The first step is to generate the client interface (stub):

$ wsdl2aws -noskel http://www.xmethods.net/sd/2001/BNQuoteService.wsdl

This will create many files, the interesting one at this point is bnquoteservice-client.ads, inside we have:

function getPrice (isbn : in String) return Float;
--  Raises SOAP.SOAP_Error if the procedure fails

Let’s call this service to find out the price for The Sword of Shannara Trilogy book:

with Ada.Text_IO;
with BNQuoteService.Client;

procedure Price is
   use Ada;

   ISBN : constant String := "0345453751";
   --  The Sword of Shannara Trilogy ISBN

   package LFIO is new Text_IO.Float_IO (Float);

begin
   Text_IO.Put_Line ("B&N Price for The Sword of Shannara Trilogy");
   LFIO.Put (BNQuoteService.Client.getPrice (ISBN), Aft => 2, Exp => 0);
end Price;

That’s all that is needed to use this Web Service. This program is fully functional: it is possible to build it and to run it to get the answer.

6.2.2. Server side (skeleton)

Building a Web Service can also be done from a WSDL document. Let’s say that you are Barnes & Noble and that you want to build Web Service getPrice as described in the previous section.

You have created the WSDL document to specify the service spec. From there you can create the skeleton:

$ wsdl2aws -nostub http://www.xmethods.net/sd/2001/BNQuoteService.wsdl

This will create many files, the interesting one here is bnquoteservice-server.ads, inside we have:

Port : constant := 80;

generic
   with function getPrice (isbn : in String) return Float;
function getPrice_CB
  (SOAPAction : in String;
   Payload    : in SOAP.Message.Payload.Object;
   Request    : in AWS.Status.Data) return AWS.Response.Data;

This is a SOAP AWS’s callback routine that can be instantiated with the right routine to retrieve the price of a book given its ISBN number. A possible implementation of such routine could be:

function getPrice (isbn : in String) return Float is
begin
   if isbn = "0987654321" then
      return 45.0;
   elsif ...
end getPrice;

function SOAP_getPrice is new BNQuoteService.Server.getPrice_CB (getPrice);

SOAP_getPrice is a SOAP AWS’s callback routine (i.e. it is not a standard callback). To use it there is different solutions:

Using SOAP.Utils.SOAP_Wrapper

This generic function can be used to translate a standard callback based on AWS.Status.Data into a SOAP callback routine:

function getPrice_Wrapper is new SOAP.Utils.SOAP_Wrapper (SOAP_getPrice);

The routine getPrice_Wrapper can be used as any other AWS’s callback routines. Note that inside this wrapper the XML payload is parsed to check the routine name and to retrieve the SOAP parameters. To call this routine the payload needs to be parsed (we need to know which routine has be invoked). In this case we have parsed the XML payload twice, this is not efficient.

Building the wrapper yourself

This solution is more efficient if there is many SOAP procedures as the payload is parsed only once:

function CB (Request : in Status.Data) return Response.Data is
   SOAPAction : constant String := Status.SOAPAction (Request);
   Payload    : constant SOAP.Message.Payload.Object :=
     SOAP.Message.XML.Load_Payload
       (AWS.Status.Payload (Request), Schema => BNQuoteService.Schema);
   Proc       : constant String :=
     SOAP.Message.Payload.Procedure_Name (Payload);
begin
   if SOAPAction = "..." then

      if Proc = "getPrice" then
         return SOAP_getPrice (SOAPAction, Payload, Request);
      elsif ...
         ...
      end if;

   else
      ...
   end if;

Note that the port to be used by the AWS server is described in the server specification.

6.2.3. wsdl2aws

Usage: wsdl2aws [options] <file|URL>

It is possible to pass a WSDL file or direct wsdl2aws to a WSDL document on the Web by passing it’s URL.

wsdl2aws options are:

-q

Quiet mode (no output)

-d

Do not generate date/time in Ada comment.

-debug

Generate debug code. Will output some information about the payload to help debug a Web Service.

-a

Generate using Ada style names. For example getPrice will be converted to Get_Price. This formatting is done for packages, routines and formal parameters.

-f

Force creation of the file. Overwrite any exiting files with the same name.

-e URL

Specify the default endpoint to use instead of the one found in the WSDL document.

-s

Skip non supported SOAP routines. If -s is not used, wsdl2aws will exit with an error when a problem is found while parsing the WSDL document. This option is useful to skip routines using non supported types and still be able to compile the generated files.

-o name

Specify the name of the local WSDL document. This option can be used only when using a Web WSDL document (i.e. passing an URL to wsdl2aws).

-p name

Specify a name prefix for all SOAPActions defined in the WDSL. This option can be used when multiple WSDL generated callback are to be used together and some of the WSDL may have the same name.

-doc

Handle document style binding as RPC ones. This is sometimes needed because some WSDL document specify a document style binding even though the service behave like an RPC one.

-v

Verbose mode, display the parsed spec.

-v -v

Verbose mode, display the parsed spec and lot of information while parsing the WSDL document tree.

-wsdl

Add WSDL document as comment into the generated root unit.

-cvs

Add CVS Id tag in every generated file.

-nostub

Do not generated stubs, only skeletons are generated.

-noskel

Do not generated skeletons, only stubs are generated.

-cb

Generate a SOAP dispatcher callback routine for the server. This dispatcher routine contains the code to handle all the operations as described in the WSDL document. You need also to specify the -spec and/or -types options, see below.

-x operation

Add operation to the list of SOAP operations to skip during the code generation. It is possible to specify multiple -x options on the command line.

-spec spec

Specify the name of the spec containing the Ada implementation of the SOAP routines. This is used for example by the -cb option above to instantiate all the server side SOAP callbacks used by the main SOAP dispatcher routine. If -types is not specified, the type definitions are also used from this spec.

-types spec

Specify the name of the spec containing the Ada types (record, array) used by SOAP routines specified with option -spec. If -spec is not specified, the spec definitions are also used from this spec.

-main filename

Specify the name of the server’s procedure main to generate. See below for the description about the way it is generated.

-n name

Specify the schema name space root name. The default value is “soapaws”.

-proxy name|IP

Use this proxy to access the WSDL document and generate code to access to these Web Services via this proxy. The proxy can be specified by its DNS name or IP address.

-pu name

User name for the proxy if proxy authentication required.

-pp password

User password for the proxy if proxy authentication required.

-sp

Generate legacy Safe Pointers code for the support of array inside records.

-timeouts [timeouts | connect_timeout,send_timeout,receive_timeout ]

Set the timeouts for the SOAP connection. The timeouts is either a single value used for the connect, send and receive timeouts or three values separated by a colon to set each timeout independently.

6.2.4. wsdl2aws code generator

The wsdl2aws tool reads a WSDL document and generates - based on different templates files - a set of packages. The templates are rendered with the Templates_Parser engine.

All the templates can be found in AWS installation under share/examples/aws/wsdl2aws-templates. They can be copied into the directory where wsdl2aws is started or pointed to by the environment variable AWS_TEMPLATE_FILES. One can then change the generated code by editing those templates.

The generated packages and the corresponding templates are described below:

<root>

Template:

s-root.tads

This is the main package, it eventually contains the full WSDL in comments and the description of the services as read from the WSDL document.

<NS>.<type>_type_pkg

Templates:

s-name-space-pkg.tads

s-type-record.tads     s-type-record.tadb
s-type-enum.tads       s-type-enum.tadb
s-type-derived.tads
s-type-array.tads

Contains all the type definitions for non standard Ada types. In these packages we find for example the definition of the records and the operations to convert them to/from SOAP objects. The types defined here have possible constraints like range attributes and/or Dynamic_Predicate aspects for Pattern and/or Length WSDL attributes.

The root package <NS> is the name-space of the actual type. This ensure that no type name clash will happen. These packages are generally not directly withed.

<root>.Types

Templates:

s-types.tads               s-types.tadb
s-type-record-types.tads
s-type-enum-types.tads
s-type-derived-types.tads
s-type-array-types.tads
s-stub-types.tads

This package contains the definitions of the types which are not SOAP base types. We find here the definitions of the SOAP structs and arrays with routines to convert them between the Ada and SOAP type model. A subtype definition is also created for every routine’s returned type. In fact, all definitions here are only aliases or renamings of types and/or routines generated in other packages rooted with a name-space as described above. This package is the one that user’s should import to gain visibility to the type definitions.

This package also contains the schema object which must be used when calling a Web service or parsing a payload.

<root>.Client

Templates:

s-stub.tads   s-stub.tadb

All specifications to call Web Services.

<root>.Server

Templates:

s-skel.tads   s-skel.tadb

All specifications to build Web Services. These specifications are all generic and must be instantiated with the correct routine to create the web services.

<root>.CB

Templates:

s-skel-cb.tads   s-skel-cb.tadb

The SOAP dispatcher callback routine.

<main>

Template:

s-main.tadb

The template used to generate the main procedure (see option -main). The template can reference the following variable tags:

SOAP_SERVICE

The name of the service as described into the WSDL document. This tag can be used to include the right units:

with @_SOAP_SERVICE_@.Client;
with @_SOAP_SERVICE_@.CB;
SOAP_VERSION

The AWS’s SOAP version.

AWS_VERSION

The AWS’s version.

UNIT_NAME

The name of the generated unit. This is the name of the procedure that will be created:

procedure @_UNIT_NAME_@ is
begin
   ...

6.2.5. wsdl2aws limitations

It is hard to know all the current limitations due to the complexity of the WSDL and SOAP world is quite complex. We list there all known limitations:

  • Some SOAP base types are not currently

supported: date, time, xsd:hexBinary, decimal, but all (with the exception of decimal) should be simple to add in the future.

  • Multi-dimensional arrays are not supported.

  • Abstract types are not supported.

  • SOAP MIME attachments are not supported.

  • WSDL type inheritance is not supported.

  • The Document/Encoded SOAP messages’ style is not supported.

  • complexType with xs:choice are only supported with a single occurence of each choice.

6.2.6. awsascb

The awsascb (AWS Aggregate Server Callback) tool can be used to aggregate multiple SOAP callback together. That is, after generating multiple SOAP callbacks with wsdl2aws it may be necessary to create a single server handling all the services. This tools is designed for this.

Usage: awsascb <root1> <root2>

There are no option for this tool. The root parameters are the wsdl2aws generated root service name units. This tool generates a unit named agg_server_cb which contains a SOAP callback and a dispatcher to be used by the server’s main subprogram. Here is the specification:

--  DO NOT EDIT : generated by awsasc

with AWS.Response;
with AWS.Status;

with SOAP.Dispatchers.Callback;
with SOAP.Message.Payload;
with SOAP.WSDL.Schema;

package Agg_Server_CB is

   use AWS;
   use SOAP;

   pragma Style_Checks (Off);

   type Handler is new SOAP.Dispatchers.Callback.Handler with null record;

   overriding function Schema
     (Dispatcher : Handler;
      SOAPAction : String)
      return WSDL.Schema.Definition;

   function Create
     (HTTP_Callback : AWS.Response.Callback) return Handler;
   --  Returns an handler whose SOAP_Callback is the one below

   function SOAP_CB
     (SOAPAction : String;
      Payload    : Message.Payload.Object;
      Request    : AWS.Status.Data)
      return Response.Data;

end Agg_Server_CB;

And following is an example on using such generated aggregate server callback from a server’s main:

   WS   : Server.HTTP;
   Conf : Config.Object;
   Disp : Agg_Server_CB.Handler;

begin
   Config.Set.Server_Port (Conf, 0);

   Disp := Agg_Server_CB.Create (HTTP_CB'Access);

   AWS.Server.Start (WS, Disp, Conf);

6.3. Using ada2wsdl and wsdl2aws together

Using both tools together is an effective way to rapidly build a SOAP server. It can be said that doing so is quite trivial in fact. Let’s take the following spec:

package Graphics is

   type Point is record
      X, Y : Float;
   end record;

   function Distance (P1, P2 : in Point) return Float;
   --  Returns the distance between points P1 and P2

end Graphics;

We do not show the body here but we suppose it is implemented. To build a server for this service it is as easy as:

$ ada2wsdl -a http://localhost:8787 -o graphics.wsdl graphics.ads

The server will be available on localhost at port 8787:

$ wsdl2aws -cb -main server -types graphics graphics.wsdl
$ gnatmake server -largs ...

Options

-cb

is to create the SOAP dispatcher callback routine,

-main server

to generate the main server procedure in server.adb,

-types graphics

to use graphics.ads to get references for user’s specification (reference to Graphics.Point for example).