Calling the SOAP Web Service
Finally, it's time to call the Google search service.
GoogleSearchResult *ret = gsp.doGoogleSearch(key, query, );
The WSDL compiler creates a stub class for every <port> mentioned in the <service> element of the WSDL document. This stub class further declares each of the services, i.e. <operation> elements in the <binding> tag, these services arguments, and their return types. The name of this class is the same as the name attribute of the <port> element, i.e., GoogleSearchPort. The class declaration is in the GoogleSearch.h header file.
Your code instantiates an instance of this class, and then calls the service (aka method) you want. This is the beauty of Web servicesthe ability to call a service written in an unknown language, hosted on a foreign computer, as if it were local to your own machine!
A review of the WSDL shows that the doGoogleSearch() service has an <output message> of doGoogleSearchResponse. The doGoogleSearchResponse message points you to the <complexType> GoogleSearchResult. When wsdlc generated our stub code it turned this type into the eponymous WASP_AbstractStructure, GoogleSearchResult (defined in GoogleSearchStructs.h). This structure is returned by the call to doGoogleSearch().
The public member elements of the GoogleSearchResult are fairly straightforward. This implementation concerns itself only with the searchQuery and resultElements members. searchQuery contains the original query as returned from Google, and is a WASP_VString. Print it out by calling its transcode() method. This method converts the return value from Unicode, returning a simple char *. Note that transcode() dynamically allocates its return value, and that value will need to be deleted. WASP_VString makes a variety of transcoders available, this particular transcoder is specific to the ASCII character set.
char *sq = ret->searchQuery.transcode();
printf("You queried Google on %s\n", sq);
The resultElements member is interesting. doGoogleSearch() returns up to ten results for each query. However, the results are not simple strings, but are complex types themselves, containing such things as a snippet of the found text and the URL where the document resides. As dictated by the WSDL, WASP has represented this complex type as a ResultElement structure, and has placed these ResultElement structures in a ResultElementArray class.
The ResultElementArray class implements another WASP wrapper class, WASP_AbstractArray. For now, it is only important to know that you can get a reference to a native C++ array via the ResultElementArray's array member and the array size from its length member. With this information in hand you can loop through the result set and print out the information of interest.
ResultElementArray *results = ret->resultElements;
ResultElement **i_results = results->array;
int num_results = results->length;
printf(Your query has returned %d results\n\n, num_results);
for (int i = 0; i < num_results; i++)
char *snippet = i_results[i]->snippet->transcode();
char *url = i_results[i]->URL->transcode();
printf("%d. %s\nURL: %s\n\n", i+1, snippet, url);
All that is left is to clean up. Deleting a complex type like a WASP_AbstractStructure or a WASP_AbstractArray involves instantiating a WASP_DeleteContext, and passing it into the object's remove() method (there are variations). The DeleteContext is a helper object that aids the object in safely removing itself, and any other objects it may reference, from memory. Its primary value becomes evident where there are complex linkages among objects, as seen here where deleting only the GoogleSearchResult is enough to also delete the ResultElementArray and the ResultElements that array holds.
Finally, there is the exception handling code. Length restrictions prohibit an in-depth discussion on this topic. However, there is little new in this section, and the code can be treated as a template. It is worth noting, however, that the first CATCH block catches SOAP faults as returned from the Google server, while the AND_CATCH_ALL block handles all other exceptions.
Compile and Run
Compile your code as follows, assuming WASP is installed in /usr/local:
g++ -o MyGoogleSearch *.cpp -I/usr/local/waspc/include \
Run our client, ./MyGoogleSearch, and see what Google considers the (at least) top ten results for a search query. Of course, the results are HTML formatted, but that's beyond your control.
Thats all there is to it. An interesting exercise might be to re-implement this code to exercise Google's, simpler, doSpellingSuggestion service.
I hope this was useful. In the next article Ill explain how to write a C++ Web service.