17.1.4.Inheritance of Datatypes for SOAP Objects

The Virtuoso SOAP server implements handling of inherited XSD types. The simple example of such relation between types can be explained as

   Type  A, also know as the 'base' type,
   and type B an extension of A.
   +---+   +---+
   | a |-->

| c |
   | b |   | d |
   +---+   +---+

   which can be defined by two separate types without relation

   A type   B type
   +---+   +---+
   | a |   | a |
   | b |   | b |
   +---+   +- -+
           | c |
           | d |
           +---+
   

But when type A has changed, type B will not be changed in second representation. This is because B is not a relative to A per se.

To work in such situations Virtuoso SOAP server handles extensions to XSD types as follows:

  1. each type and base type have defined a User Defined SQL type (UDT).

  2. the XSD types defined for SOAP processing are defined with UDT relation (see soap_dt_define)

  3. the inheritance is declared with 'extension' element in XSD type declaration

When we have these preliminaries the WSDL will declare in 'schema' part of WSDL all depending types. Furthermore the SOAP processor will handle inherited members of derived types.

Example17.2.Declaration and usage of depending types

Consider the following XSD and User Defined Type declaration for a base type 'BaseStruct':

        <!-- XSD type declaration, file base.xsd -->

        <complexType name="BaseStruct">
                <sequence>
                        <element name="floatMessage" type="xsd:float"/>
                        <element name="shortMessage" type="xsd:short"/>
                </sequence>
        </complexType>

        -- corresponding user defined sql type
        create type DB.DBA.BaseStruct as (floatMessage real, shortMessage int __soap_type 'short');
    

Furthermore we are extending the BaseStruct with adding three more elements (members) with declaration of ExtendedStruct:

        <!-- XSD type declaration, file ext.xsd -->

        <complexType name="ExtendedStruct">
                <complexContent>
                        <extension base="tns:BaseStruct">
                                <sequence>
                                        <element name="stringMessage" type="xsd:string"/>
                                        <element name="intMessage" type="xsd:int"/>
                                        <element name="anotherIntMessage" type="xsd:int"/>
                                </sequence>
                        </extension>
                </complexContent>
        </complexType>

        -- corresponding user defined SQL type
       create type DB.DBA.ExtendedStruct under DB.DBA.BaseStruct as (
            stringMessage nvarchar __soap_type 'string',
            intMessage int __soap_type 'int',
            anotherIntMessage int __soap_type 'int');
    

Once we are done with declarations as XSD files and user defined SQL types, we must register them as SOAP types for processing:

SQL> soap_dt_define ('', file_to_string ('base.xsd'), 'DB.DBA.BaseStruct');
SQL> soap_dt_define ('', file_to_string ('ext.xsd'), 'DB.DBA.ExtendedStruct');
    

Now we are able to create a PL procedure to use as a SOAP method, which simply will accept an ExtendedStruct and echo it back to the client.

create procedure
echoExtendedStruct (in param DB.DBA.ExtendedStruct __soap_type 'http://soapinterop.org/types:ExtendedStruct')
returns DB.DBA.ExtendedStruct __soap_type 'http://soapinterop.org/types:ExtendedStruct'
{
  --  All members  of DB.DBA.ExtendedStruct and DB.DBA.BaseStruct are available in param.
  return param;
}
;

grant execute on echoExtendedStruct to SOAP;
    

The SOAP request to that method will be as follows:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:m0="http://soapinterop.org/types">
  <SOAP-ENV:Body>
    <m:echoExtendedStruct xmlns:m="http://soapinterop.org/wsdl">
      <param xsi:type="m0:ExtendedStruct">
        <floatMessage xsi:type="xsd:float">3.14159</floatMessage>
        <shortMessage xsi:type="xsd:short">4096</shortMessage>
        <stringMessage xsi:type="xsd:string">String</stringMessage>
        <intMessage xsi:type="xsd:int">0</intMessage>
        <anotherIntMessage xsi:type="xsd:int">0</anotherIntMessage>
      </param>
    </m:echoExtendedStruct>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
    

The SOAP response to the above request will be as follows:


<SOAP:Envelope
SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:dt="urn:schemas-microsoft-com:datatypes"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext"
xmlns:ref="http://schemas.xmlsoap.org/ws/2002/04/reference/"
xmlns:ns0="http://soapinterop.org/types" xmlns:wsdl="services.wsdl">

  <SOAP:Body>
    <cli:echoExtendedStructResponse xmlns:cli="http://soapinterop.org/wsdl">
      <CallReturn xsi:type="ns0:ExtendedStruct">
        <stringMessage xsi:type="xsd:string">String</stringMessage>
        <intMessage xsi:type="xsd:int">0</intMessage>
        <anotherIntMessage xsi:type="xsd:int">0</anotherIntMessage>
        <floatMessage xsi:type="xsd:float">3.14159</floatMessage>
        <shortMessage xsi:type="xsd:short">4096</shortMessage>
      </CallReturn>
    </cli:echoExtendedStructResponse>
  </SOAP:Body>
</SOAP:Envelope>
    
[Note] Note:

Although the namespace declarations of XSD types are skipped for better readability, these must be present when declaring (see the Extending Datatypes for SOAP Objects section, discussed earlier)