gSOAP

From Wikipedia, the free encyclopedia
Jump to: navigation, search
gSOAP
Developer(s) Genivia Inc.
Stable release 2.8.17 / December 2, 2013 (2013-12-02)
Written in C and C++
Operating system Cross-platform
Type Web development software
License GPL v2, commercial licensing
Website http://gsoap2.sourceforge.net

gSOAP is a C and C++ software development toolkit for SOAP/XML web services and generic XML data bindings.

History[edit]

The gSOAP toolkit was first introduced in 1999 as a research project at the Florida State University for generic XML communications by establishing a type-safe data binding between XML schema types and C/C++ data types through automatic programming (source code generation based on a domain-specific C compiler). The toolkit was further developed to support the SOAP web services messaging protocol, introduced at around the same time, hence the name "gSOAP" (generic XML and SOAP). Further development took place under ownership of Genivia Incorporated, which included the addition of new WSDL and XML schema processing capabilities in 2003 as well as the addition of WS-* web services protocol capabilities, XML-RPC messaging, support for the JSON data format, and a stand-alone web server. The gSOAP toolkit is written in portable C/C++ and uses a form of bootstrapping by generating its own code to implement a converter to translate WSDL/XSD specifications to C/C++ source code for WSDL/XSD meta-data bindings. The gSOAP software is offered under the GPLv2 open source license and commercial-use source code licenses.

Web Service Operations by Example[edit]

An example web service operation in C for retrieving the lodging rate of a hotel given a number of guests can be declared in annotated form as

//gsoap ns service namespace: tempuri
//gsoap ns service style:     document
//gsoap ns service encoding:  literal
int ns__get_rate(char* hotel, int guests, float *rate);

The last parameter of the function is always the service return value, which can be denoted as void for one-way operations and should be a struct/class to bundle multiple service return parameters. The function's int return value is used for error diagnostics.

A service invocation in C using the auto-generated soap_call_ns__get_rate function is executed as follows

const char *URL = "http://www.example.com/hotels";
const char *action = NULL;
struct soap *ctx = soap_new();  // new context
float rate;
int err = soap_call_ns__get_rate(ctx, URL, action, "Happy Inn", 2, &rate);
if (err == SOAP_OK && rate < 100.00)
  lets_go();
soap_end(ctx);   // deallocate deserialized data
soap_free(ctx);  // deallocate context

To facilitate web services implementations for legacy C and C++ systems, the prefix qualification of identifier names in C/C++ can be omitted or can be replaced by colon notation, for example ns:get_rate rather than ns__get_rate. The punctuation is removed in the auto-generated source code that is used in project builds.

A service invocation in C++ using the auto-generated Proxy class is executed as follows (using the Proxy's default endpoint URL and SOAP action values)

Proxy proxy;
float rate;
int err = proxy.get_rate("Happy Inn", 2, &rate);
if (err == SOAP_OK && rate < 100.00)
  lets_go();
proxy.destroy();  // deallocate deserialized data

By using annotations and identifier naming conventions, i.e. qualification with the prefix ns__ for the function ns__get_rate and by declaring properties of the ns namespace using the //gsoap directives in the example, a binding is established to web service operations. The auto-generated Web Services Description Language (WSDL) document declares a request message, a response message, and the get-rate operation portType interface and SOAP binding for the ns__get_rate function as follows

<definitions name="Service" targetNamespace="tempuri" xmlns:tns="tempuri" xmlns:ns="tempuri"
  xmlns="http://schemas.xmlsoap.org/wsdl/">
...
<message name="get-rateRequest">
 <part name="parameters" element="ns:get-rate"/>
</message>
<message name="get-rateResponse">
 <part name="parameters" element="ns:get-rateResponse"/>
</message>
 
<portType name="ServicePortType">
 <operation name="get-rate">
  <input message="tns:get-rateRequest"/>
  <output message="tns:get-rateResponse"/>
 </operation>
</portType>
 
<binding name="Service" type="tns:ServicePortType">
 <SOAP:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
 <operation name="get-rate">
  <SOAP:operation soapAction=""/>
  <input>
   <SOAP:body parts="parameters" use="literal"/>
  </input>
  <output>
   <SOAP:body parts="parameters" use="literal"/>
  </output>
 </operation>
</binding>

where the request and responses messages of the operation refer to XML elements that are defined in the types section of the WSDL as follows

<types>
 <schema targetNamespace="tempuri" ...> 
  <element name="get-rate">
   <complexType>
    <sequence>
     <element name="hotel" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
     <element name="guests" type="xsd:int" minOccurs="1" maxOccurs="1"/>
    </sequence>
   </complexType>
  </element>
  <element name="get-rateResponse">
   <complexType>
    <sequence>
     <element name="rate" type="xsd:float" minOccurs="0" maxOccurs="1" nillable="true"/>
    </sequence>
   </complexType>
  </element>
 </schema>
</types>

Likewise, client and server C/C++ source code can be auto-generated from a set of WSDLs and XML schemas. Services must be completed by defining the appropriate service operations. For example, the auto-generated C++ service class for this WSDL must be completed by defining the get_rate method as follows

int Service::get_rate(char *hotel, int guests, float *rate)
{
  *rate = ...  // determine the lodging rate of the hotel given the number of guests
  return SOAP_OK;
}

There are no restrictions on the type of the operation parameters that can be marshaled in XML for web service messaging, except that certain type declaration conventions and annotations should be followed to establish a data binding.

Data Binding by Example[edit]

To establish an XML data binding with C/C++ data types, gSOAP uses three basic forms of source code annotation: directives, identifier naming conventions, and punctuation.

A fully annotated structure declaration in C for a hierarchical employee record may appear as

//gsoap ns schema namespace: tempuri
//gsoap ns schema form:      qualified
struct ns__employee_record
{
   @char  *xml__lang  = "en";
   @int    ID         = 9999;
    char  *full_name         1:1;     
   $int    size              0:12;
    struct ns__employee_record *manages;
};

where the following annotations and conventions are used:

  • namespace qualification of types and members by identifier naming conventions: ns__employee_record, xml__lang
  • attributes for members: @char*, @int
  • default values for members: xml__lang = "en", ID = 9999
  • occurrence constraints in the form of minOccurs:maxOccurs for XML validation: full_name 1:1, size 0:12
  • dynamic arrays of element sequences consist of a pair of a special size field and an array pointer member: $int size; struct ns__employee_record *manages

The gSOAP tools convert C/C++ data types to/from XML schema data types. Since C does not support namespaces and struct/class member names cannot be namespace-qualified in C++, the use of identifier naming conventions in gSOAP allow for binding this structure and its members to an XML schema complexType that is auto-generated as follows

<schema targetNamespace="tempuri" xmlns:ns="tempuri"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/2001/XMLSchema"
  elementFormDefault="qualified" attributeFormDefault="qualified">
 
  <complexType name="employee-record">
   <sequence>
    <element name="full-name" type="xsd:string" minOccurs="1" maxOccurs="1" nillable="true"/>
    <element name="manages" type="ns:employee-record" minOccurs="0" maxOccurs="12"/>
   </sequence>
   <attribute ref="xml:lang" use="default" default="en"/>
   <attribute name="ID" type="xsd:int" use="default" default="9999"/>
  </complexType>
 
</schema>

Furthermore, unions in a struct/class that are annotated with a special selector field for union member selection are mapped to/from schema choice particles, STL containers are mapped to/from sequence particles, enumerations are mapped to/from XML schema simpleType enumerations, and standard C/C++ primitive types are mapped to/from XSD types. For conversion of XSD schema to C/C++ data types, the actual mapping is configurable in gSOAP with a type mapping file.

An instance of the example hierarchical employee structure is serialized in XML as a tree by default, for example

<ns:employee xmlns:ns="tempuri" xml:lang="en" ns:ID="12">
 <ns:full-name>Jane Doe</ns:full-name>
 <ns:manages xml:lang="en" ns:ID="34">
  <ns:full-name>John Doe</ns:full-name>
 </ns:manages>
 <ns:manages xml:lang="en" ns:ID="56">
  <ns:full-name>Bob Oz</ns:full-name>
  <ns:manages xml:lang="en" ns:ID="78">
   <ns:full-name>Alice Oz</ns:full-name>
  </ns:manages>
 </ns:manages>
</ns:employee>

When the SOAP encoding style is enabled, the XML serialization in gSOAP respects co-referenced objects and cyclic data structures as per SOAP encoding rules resulting in XML with id-ref edges.

Features[edit]

See also[edit]