Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

C/C++

gSOAP & Web Services


Dressing It Up

To illustrate extensibility based on inheritance, add another type of object to the collision service. Changing the code requires recompilation of the service program. It also affects the WSDL, because a new WSDL is generated with the new type. The new type of object appears as a schema extension of the base Point type. The neat thing about XML schema extensibility is that client programs developed with the old WSDL will still talk to the new service.

Listing Nine shows the new Circle type derived from Point. >Listing Ten shows the method code for Circle. You override the radius method to return the actual radius of the circle. The data member r is public so it can be serialized. To include the new circle object in the collection, import circle.h in service.h to make its definition available to the gSOAP compiler.

Listing Nine

// file: circle.h
#import "point.h"
class Circle: public Point
{ public:
   float r;
   virtual float radius() const;
   Circle();
   Circle(float,float,float);
};

Listing Ten

// file: circle.cpp
#include "soapH.h"
Circle::Circle() : Point(), r(1.0) {}
Circle::Circle(float x, float y, float r) : Point(x, y), r(r) {}
float Circle::radius() const
{ return r; }

Developing a gSOAP Client

Listing Eleven is a C++ client program for the service. The client is directly developed from the service.h header file specification of the CollisionDetection web service. I could have used the generated WSDL and run it through the gSOAP WSDL importer. However, the WSDL notation does not preserve the method definitions of the Point and Circle classes, because only the serializable members are part of the generated WSDL schema type definitions.

Listing Eleven

// file: client.cpp
#include "soapCollisionServiceProxy.h"
#include "CollisionService.nsmap"
main()
{  // create a proxy
   CollisionService proxy;
   // create two points and a circle   
   Point p, q(1.0, 1.0);
   Circle c(1.0, 1.0, 2.0);
   // create a collection with the objects
   Objects collection;
   collection.objects.push_back(&p);
   collection.objects.push_back(&q);
   collection.objects.push_back(&c);
   // compute the hits remotely and print the count
   int hits;
   if (proxy.cws__detect_collisions(collection, hits) == SOAP_OK)
      cout << "Hits=" << hits << endl;
   else
      soap_print_fault(proxy.soap, stderr);
}

The client prints a fault message upon failure. The failure can be due to connection issues or application-related issues such as an empty collection, which the service explicitly prohibits by returning a sender-side fault (see Listing Eight).

Saving and Retrieving XML Data

Suppose you want to retrieve a collection of geometric objects from a file or stream instead of hard coding it in the client program (Listing Eleven). You do this by using the XML serializers directly. For every nontransient type declared in the intermediate header file specification, gSOAP generates a serializer and deserializer. Let X be the name of a primitive type, enum, struct, or typedef, then the serializers and deserializers for type X are:

  • void soap_serialize_X(struct soap*, const X *obj);
  • int soap_out_X(struct soap*, const char *tag, int id, const X *obj, const char *xsitype);
  • X *soap_in_X(struct soap*, const char *tag, X *obj, const char *xsitype);

For a class X, gSOAP generates serialization and deserialization methods:

  • void X::soap_serialize(struct soap*) const;
  • int X::soap_out(struct soap*, const char *tag, int id, const char *xsitype) const;
  • void *X::soap_in(struct soap*, const char *tag, const char *xsitype);

The soap_serialize functions and methods ensure that pointer-based object graphs are serialized in a format that preserves the logical graph structure. Coreferenced data is serialized with XML id-refs. This enables the serialization of arbitrary object graphs without loss of structural integrity. The soap_serialize function or method is called before soap_out. The soap_out function or method emits the data in XML. The soap_in function or method parses XML and returns a pointer to the newly instantiated data. Both functions/methods accept an XML tag name and an optional xsi type value referring to the qualified XML schema typename.

To read a collection of objects from a file, add this code to the client program:

proxy.soap->is = new ifstream("data.xml"); 
         // bind gSOAP runtime to an istream
if (proxy.soap->is == NULL
|| soap_begin_recv(proxy.soap) != SOAP_OK // start reading
|| collection.soap_in(proxy.soap, "objects", NULL) == NULL
|| soap_end_recv(proxy.soap) != SOAP_OK) // stop reading
   exit(1);
proxy.soap->is->close();
delete proxy.soap->is;

The proxy object is managed by a gSOAP runtime context, proxy.soap. The context is used to parse and populate the collection from a file and to manage its memory allocation and deallocation.

Memory Management

Memory management is crucial. The gSOAP runtime context manages the lifetime of an object from allocation and instantiation to destruction. Objects managed by a proxy's runtime context are automatically deallocated when the proxy object is destroyed. At the server side, the destruction of objects and temporary data is explicitly performed with the soap_destroy and soap_end calls; see Listing Eight. The soap_malloc function allocates a temporary string in the service operation, which is deallocated by soap_end after message serialization.

Conclusion

The gSOAP Web Services Toolkit serializes almost any type of C/C++ data directly to and from XML. This feature of the C/C++ language binding to XML, combined with the powerful gSOAP WSDL importer, lets you rapidly develop and deploy web services in C or C++.

References

[1] http://gsoap2.sourceforge.net/.


Robert van Engelen is an associate professor in the Department of Computer Science at Florida State University. He is also president of Genivia Inc., a company dedicated to the research and development of XML products and services. He can be contacted at [email protected] or at [email protected].


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.