# The &kwsdl_compiler; Handbook

Tobias Koenig

    tokoe@kde.org

2006-01-01
0.1
&FDLNotice;

&kwsdl_compiler; is a tool to generated KDE/C++ code from a WSDL (Web Service Description Language) file for communication with a web service.

KDE kwsdl_compiler WSDL SOAP webservice

## Introduction

Webservices are services provided by more and more software components for platform independend information interchange and encapsulating of business logic. The functionality of a webservice is described by its WSDL (Web Service Description Language) file which is available from the provider of this service. To use a webservice one have to marshal the request in a XML document which is send to the server via HTTP and demarshal the response (also a XML document) returned by the server. This can be done manually, however since the WSDL fully describes the interface of a webservice, the code for marshalling, demarshalling and communication be be generated automatically.

&kwsdl_compiler; is the tool which does this automatic code generation for KDE. The generated code makes use of a couple of KDE features, e.g. KIO slaves for communication which brings the advantage of SSL support and cookie handling. At the moment &kwsdl_compiler; only generates code for a client stub (the part which uses the webservice), but in later versions it is planned to support generation of server stubs (the webservice itself) as well.

## Using &kwsdl_compiler;

### Getting Started

&kwsdl_compiler; is a command line tool because it's mainly used during the development of an application and should be well integrated into KDE's build process.

The simplest usage of &kwsdl_compiler; is to start it with the url of the WSDL file as argument:

    kwsdl_compiler http://url/to/wsdl/file

In this case &kwsdl_compiler; will create two files (kwsdl_generated.h and kwsdl_generated.cpp) in the current working directory, which contain the generated code of this webservice.

If you want the generated files to be in another directory, use the `-d` or `--outputDirectory` argument:

    kwsdl_compiler -d gen_project/ http://url/to/wsdl/file

### The Configuration File

For easier integration into the build process, &kwsdl_compiler; supports the usage of a configuration file, which contains all settings for a flexible code generation. The configuration file which should be used can be passed to &kwsdl_compiler; with the `-c` argument.

    kwsdl_compiler -c myproject.kwsdlcfg

Example:

    <kwsdlcfg>
     <wsdlUrl>http://myserver/apis/ws/seller.wsdl</wsdlUrl>
     <outputFileName>ws_seller</outputFileName>
     <outputDirectory>gen_project</outputDirectory>
     <namespaceMapping prefix="ms" uri="urn:MySeller"/>
     <namespaceMapping prefix="ys" uri="urn:YourSeller"/>
    </kwsdlcfg>

Explanation:

wsdlUrl

  The url of the WSDL file of the webservice. This entry can be omitted when the url is passed as command line argument.

outputFileName

  The name of the generated file. So when outputFileName is set to 'foobar', the files 'foobar.h' and 'foobar.cpp' will be generated. If this entry is omitted, the generated code is saved in 'kwsdl_generated.h' and 'kwsdl_generated.cpp'.

outputDirectory

  The directory where the generated code shall be stored in. If this entry is omitted the current working directory is used.

namespaceMapping

  Types defined in the WSDL file can be namespaced, so the classes in the generated code will be namespaced as well. To avoid meaningless namespaces like 'ns1', this entry allows to assign a prefix to a namespace URI.

So the above example configuration file would cause &kwsdl_compiler; to load the WSDL file from http://myserver/apis/ws/seller.wsdl, parse it and store the generated code as ws_seller.h and ws_seller.cpp in the directory gen_project/. If seller.wsdl contains a type definition with the name 'Request' which is in namespace urn:MySeller, a class MS__Request will be generated.

## Advanced Usage

This chapter is not complete yet, it mainly summarizes some ideas which features could be added to &kwsdl_compiler; in future.

### Use Custom Transport Class

&kwsdl_compiler; is build in a modular way, so that you can easily exchange single parts, like the transport layer for example. There are two buildin types of transport, one for KDE (uses KIO slaves) and one Qt only. The KDE transport is used as default, however you can switch to other transports by using the 'transport' configuration file entry:

    <transport>TransportType</transport>

TransportType can be one of the following strings:

KDE

  The default type which uses the full featured KIO HTTP slave.

Qt

  An Qt only solution without SSL and cookie support.

Custom

  Using this type allows you to use your own transport class (see below).

With the 'Custom' transport type set you can create your own Transport class which will be used by the autogenerated code for the communication. The class must derive from QObject and provide the interface of the Transport class:

    class Transport : public QObject
    {
      Q_OBJECT

      public:
        /**
          Constructs a new Transport which communicates
          with the webservice at the given @param url.
         */
        Transport( const QString &url );

        /**
          Sends a valid SOAP @param message to the webservice.

          @param message The SOAP message in xml format.
          @param header An additional SOAP header.
         */
        void query( const QString &message, const QString &header );

      signals:
        /**
          This signal is emitted whenever the query was successfull, otherwise
          @see error() is emitted.

          @param result The result of the query in xml format (SOAP message).
         */
        void result( const QString &result );

        /**
          This signal is emitted whenever an error occured during transmission.

          @param msg An i18n'ed error message.
         */
        void error( const QString &msg );
    };

To actual integrate the custom transport into your project, just rename your class 'Transport' and put the declaration into a file with the name 'transport.h'. The autogenerated code will include this file and make use of it.

## Example

This chapter provides an example how to access the GoogleSearch webservice. The WSDL file of this service can be downloaded at http://apis.google.com. After retrieving the WSDL we create a configuration file for our project

    <kwsdlcfg>
     <wsdlUrl>GoogleSearch.wsdl</wsdlUrl>
     <namespaceMapping prefix="ggs" uri="urn:GoogleSearch"/>
    </kwsdlcfg>

which we store as googlesearch.kwsdlcfg.

Now we let &kwsdl_compiler; generate the code for us:

    kwsdl_compiler -c googlesearch.kwsdlcfg

Two new files (kwsdl_generated.h and kwsdl_generated.cpp) will be in the current working directory now. To actually use the webservice we have to write some glue code, which makes use of the generated code.

main.h

    #ifndef MAIN_H
    #define MAIN_H

    #include "kwsdl_generated.h"

    class KWSDLTest : public QObject
    {
      Q_OBJECT

      public:
        KWSDLTest();
        ~KWSDLTest();

        void run();

      private slots:
        /**
          Slot which is called when the doGoogleSearch call was successfull.
         */
        void googleSearch( GGS__GoogleSearchResult *_return );

        /**
          Slot which is called when an error occured.
         */
        void googleSearchError( SoapFault *fault );

      private:
        GoogleSearchService mService;
    };

    #endif

main.cpp

    #include <kaboutdata.h>
    #include <kapplication.h>
    #include <kcmdlineargs.h>

    #include "main.h"

    KWSDLTest::KWSDLTest()
    {
      // connect the signals of the generated code with our slots

      // return value
      connect( &mService, SIGNAL( doGoogleSearchResponse( GGS__GoogleSearchResult* ) ),
               this, SLOT( googleSearch( GGS__GoogleSearchResult* ) ) );

      // error
      connect( &mService, SIGNAL( doGoogleSearchError( SoapFault* ) ),
               this, SLOT( googleSearchError( SoapFault* ) ) );
    }

    KWSDLTest::~KWSDLTest()
    {
    }

    void KWSDLTest::run()
    {
      // do actually call the service
      mService.doGoogleSearch( new QString( "secret key" ), new QString( "kwsdl" ), new int( 0 ),
                               new int( 10 ), new bool( false ), new QString(), new bool( true ),
                               new QString(), new QString(), new QString() );
    }

    void KWSDLTest::googleSearch( GGS__GoogleSearchResult *_return )
    {
      // extract and show the search result

      GGS__ResultElementArray* resultArray = _return->resultElements();
      QValueList<GGS__ResultElement*> *list = resultArray->items();
      QValueList<GGS__ResultElement*>::ConstIterator it;
      for ( it = list->begin(); it != list->end(); ++it ) {
        qDebug( "url=%s", (*it)->uRL()->toLatin1() );
      }

      delete _return;

      kapp->quit();
    }

    void KWSDLTest::googleSearchError( SoapFault *fault )
    {
      // show error message

      qDebug( "googleSearchError (%s)", fault->description().latin1() );

      delete fault;

      kapp->quit();
    }

    int main( int argc, char **argv )
    {
      KAboutData aboutData( "googlesearch", "Google Search", "0.1" );
      KCmdLineArgs::init( argc, argv, &aboutData );

      KApplication app( false, false );

      KWSDLTest test;
      test.run();

      return app.exec();
    }

    #include "main.moc"

## Command Line Options

&kwsdl_compiler; supports some command-line arguments, which can be used to influence the code generation:

`kwsdl_compiler` `-c, --configfile <file>`

  Uses the given file as configuration file.

`kwsdl_compiler` `-d, --outputDirectory <directory>`

  Save the generated code in the given directory.

`kwsdl_compiler` `<wsdl>`

  Generate code for the given wsdl.

## Credits and License

&kwsdl_compiler; - The &kde; WSDL compiler

Copyright (c) 2005 - 2006, Tobias Koenig tokoe@kde.org

&underFDL;