A Soap Stack For The QT Framework
A Soap Stack For The QT Framework
A Soap Stack For The QT Framework
Peter Hartmann
September 22, 2008
diploma thesis
[email protected]
Contents
1 Introduction
1.1
Task denition
1.2
Overview
2 Basics
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1
Web services
2.2
SOAP
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3 The Qt framework
3.1
Meta-Object system
3.2
3.3
. . . . . . . . . . . . . . . . . . . . . . . . .
6
7
10
13
16
18
3.3.1
Networking
. . . . . . . . . . . . . . . . . . . . . . . . . .
18
3.3.2
XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
22
22
4.1.1
23
4.1.2
4.2
26
29
Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
4.2.2
Java RMI . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
4.2.3
4.3
. . . . . . . .
4.2.1
REST-based services . . . . . . . . . . . . . . . . . . . . .
34
. . . . . . . . . . . . . . . . . . . . . . .
37
. . . . . . . . . . . . . . . . . . . . . .
38
4.3.1
4.3.2
42
4.3.3
gSOAP (C++) . . . . . . . . . . . . . . . . . . . . . . . .
52
4.3.4
4.4
SOAP::Lite (Perl)
.NET (C#) . . . . . . . . . . . . . . . . . . . . . . . . . .
56
59
. . . . . . . . . . . . . . . . . . . . .
61
61
5.1.1
. . . . . . . . . . . . . . . . . .
61
5.1.2
65
5.1.3
XML parsing
. . . . . . . . . . . . . . . . . . . . . . . . .
67
5.1.4
5.2
71
73
WSDL parsing
74
5.2.2
5.3
WSDL handling . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.1
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
76
78
83
85
2
Abstract
SOAP is a protocol for enabling communication in a distributed system.
other distributed computing techniques like REST, Java RMI and AJAX.
Furthermore, it evaluates the Qt framework as well as existing SOAP
stacks (Apache Axis2, gSOAP, SOAP::Lite and .NET); after that, the
design and implemenetation of a SOAP stack for the Qt framework is
proposed. An analysis of this system will then show whether the requirements of a SOAP toolkit could be met.
Introduction
SOAP evaluation
Before designing an architecture of a SOAP stack, this document will evaluate SOAP, trying to answer the following questions:
What is the main eld of use of the SOAP protocol? How does it overlap
with similar techniques?
What API do other SOAP toolkits oer? What are their strengths and
weaknesses?
In order to propose a SOAP framework that ts user needs, other frameworks
will be analyzed. The main focus of this evaluation will be the API the toolkits oer; features and architectural paradigms of those toolkits could then be
adopted in the SOAP toolkit that is to be designed.
The SOAP evaluation will discuss the SOAP protocol itself and its use cases
as well as analyze existing toolkits, and see how SOAP is used in practice.
Qt evaluation
In addition to evaluating SOAP, the Qt framework needs to be analyzed.
Here, evaluating means both describing what features the Qt framework already
oers in terms of networking and XML support as well as the main use case
for programs using Qt.
inuence the architecture of the Qt SOAP stack; moreover, the SOAP stack
should of course oer an API that is similar to the API of other Qt modules.
1.2 Overview
The subsequent chapters of this document are structured as follows:
chapter 2 gives an introduction into Web services and SOAP from a very
general and high-level view.
chapter 3 describes the Qt framework: The chapters 3.1 and 3.2 describe
the framework in general, while chapter 3.3 gives an overview over the
tools needed by the SOAP stack (which is described later).
Basics
That is, a
very basic Web service scenario involves at least the following, as can be seen
in Figure 1:
1. a service provider oering a specic functionality
2. a service requester demanding that functionality
3. a medium used for communication between the two
In the case of a Web service, the medium used for communication is the
Internet or a Local Area Network. From this scenario, a lot of questions arise,
for instance:
Basically, any application or transport level protocol could be used here; however, in practice the most frequently used protocol is HTTP. Another common
use case involves JMS-compliant middleware messaging protocols like ActiveMQ
or WebSphereMQ. More rare scenarios use TCP, UDP or XMPP as an underlying protocol.
How does the service requester know how to invoke the functionality of
the service provider?
Since the parties involved in a Web service system want to exchange information,
they have to agree on a format to encode the exchanged data. Alternatives for
such an encoding are XML, JSON (JavaScript Object Notation), or any selfdesigned or programming language dependent encoding.
A Web service might require a dierent number of inbound messages and outbound messages. A standard scenario of organizing message exchange is to have
one inbound message to the service provider, which in turn sends one message
back to the requester. But several Web services require other Message Exchange
Patterns (MEPs), e.g. one-way operation (in-only), solicit-response (rst out,
then in) or notication (out-only).
More advanced use cases of a Web service include multiple service requesters
and providers, service registries, actors that fulll both the role of a service
provider and requester, Web services that are composites of other Web services
etc.
document.
2.2 SOAP
SOAP [28] is an XML-based protocol destined for exchanging messages over
a network. It is commonly used as a protocol in Web service infrastructures.
Going back to the four questions from chapter 2.1, SOAP provides an answer
for each of those:
When using SOAP, the usual choice for an underlying protocol is HTTP. The
SOAP standard even describes an HTTP binding, but does not mandate its
use, i.e.
other underlying protocols are possible (with JMS being one of the
alternatives).
How does the service requester know how to invoke the functionality of
the service provider?
As already said, to address this issue there must be an interface accessible for
the service requester.
As SOAP is mostly used with HTTP, the most common message exchange pattern is request-response, since it maps naturally to the HTTP request-response
mechanism.
Apart from that, as the purpose of this document is to propose a SOAP implementation for the Qt framework, which is described in chapter 3, using the
request-response pattern via HTTP (which can be viewed as issueing a RPC)
shall be the common scenario here.
As a basic example of a SOAP communication, consider a scenario where a
StockQuote service oers looking up the stock price of a company (this example
is similar to the one in [27]). A request would send the symbol of the company
that it wants to know the stock price from:
www . s t o c k q u o t e s e r v e r . com
C o n t e n t Type :
t e x t / xml ;
C o n t e n t L e n g t h :
SOAPAction :
c h a r s e t =" u t f
8"
nnnn
<s o a p : E n v e l o p e
x m l n s : s o a p=" h t t p : / / s c h e m a s . x m l s o a p . o r g / s o a p / e n v e l o p e /">
<s o a p : Header ></s o a p : Header>
<s o a p : Body>
<n s : G e t L a s t T r a d e P r i c e
x m l n s : n s="StockQuoteURI">
<n s : symbol>
TROLL
</n s : symbol>
</n s : G e t L a s t T r a d e P r i c e >
</ s o a p : Body>
</ s o a p : E n v e l o p e >
The stock quote service provider could, upon receiving the message, invoke
a procedure to look up the price with symbol TROLL, and respond with the
following message:
Listing 2: A sample SOAP-over-HTTP response
HTTP/ 1 . 1
2 0 0 OK
C o n t e n t Type :
t e x t / xml ;
C o n t e n t L e n g t h :
c h a r s e t =" u t f
nnnn
8"
<s o a p : E n v e l o p e
x m l n s : s o a p=" h t t p : / / s c h e m a s . x m l s o a p . o r g / s o a p / e n v e l o p e /">
<s o a p : Header ></s o a p : Header>
<s o a p : Body>
<n s : G e t L a s t T r a d e P r i c e R e s p o n s e
x m l n s : n s="StockQuoteURI">
<n s : p r i c e >16.5 </ n s : p r i c e >
</n s : G e t L a s t T r a d e P r i c e R e s p o n s e >
</ s o a p : Body>
</ s o a p : E n v e l o p e >
The response contains the stock price of the symbol requested before, which
amounts to 16.5.
A more detailed discussion of SOAP messages structure will be given in
chapter 4.1.
The Qt framework
1
hensive list of classes, with the main focus on ready-to-go GUI elements (push
buttons, radio buttons, text input elds, icons...). Furthermore, it also provides
APIs for database usage, networking and XML, among others. The Qt APIs
are designed to be easy and intuitive for end users, with classes and methods
having self-documenting names. Figure 3 shows the component diagram of the
Qt modules, with the QtCore module being the central component. Since the
main focus of the Qt library is set on GUI programming, the QtGui module
is also (as the QtCore module) included implicitly in the build process. As an
example, Listing 3 shows a simple Hello World application (similar to the one
from [1]), that displays a Hello World button, as depicted in Figure 4.
1 http://trolltech.com/products/qt/
10
11
#include
#include
int
int
<Q A p p l i c a t i o n >
<QPushButton>
main (
argc ,
QApplication
QPushButton
char
button
button
>show ( ) ;
return
argv
app ( a r g c ,
=
[])
argv ) ;
new
QPushButton ( " H e l l o
World " ) ;
app . e x e c ( ) ;
QProcess
start new processes and communicate with them. A program using that class
which is compiled on Windows, will use the CreateProcessA or CreateProcessW calls from the Windows API ([16]); while the same program compiled on
Linux will fork (as described in the POSIX standard [13]) to create the process.
The
QProcess
QFile
QDir
(directories),
QThread
(for reading from and writing to les), among others. Actually, the
most frequently used cross-platform classes in Qt are GUI elements like widgets, toolbars, buttons etc., but since this document focuses more on low-level
functionality like networking, the GUI parts of Qt are not discussed here.
12
TEMPLATE :
or lib (library).
TARGET :
The name of the application (will in the example turn into helloworld on Unix and helloworld.exe on Windows).
SOURCES :
There are a lot more options for .pro les, listed under [23] (e.g. C++ header
les, building in debug and release mode, GUI forms as described below etc.).
Qt Designer.
mode (see Figure 5). To use a created form in an application, Qt comes with a
source code generator called uic (user interface compiler) which creates C++
header les from Qt designer form les.
below was called lineEdit, the generated header le allows access via code like
lineEdit->setText('my text').
There are several parts of Qt that are not discussed here, for instance internationalization support and scripting; the following chapters rather dig deeper
into the Qt library.
This enables
some convenient features that are usually not there in C++ programs, the most
type introspection,
property system. To enable these
the
and Qt's
mechanism
inherit from the class QObject, which is the base class of al Qt objects, and
additionally include the Q_OBJECT macro in the private section of its class
declaration, as Listing 5 shows.
class
public
QObject
Q_OBJECT
13
public
void
private
int
:
doSomething ( ) ;
myMember ;
};
To use the meta-object features for a class, Qt comes with a commandline tool called moc (Meta-Object Compiler); this tool can, similar to the
user interface compiler described earlier, be invoked via the command line, but
usually is invoked automatically via the qmake build system. The meta-object
compiler creates for each class that inherits from QObject and includes the
Q_OBJECT macro a meta class; this meta class can be accessed via the
method metaObject() of the class QObject; this relationship is shown in
Figure 6. Note that the meta class is retrieved via the metaObject() call and
has no name by itself. The meta-object system enables the following features:
introspection.
the class name as a string at run-time, without requiring native runtime type information (RTTI) support through the C++ compiler
([21]). Additionally, the QObject class contains a method inherits(), which lets class instances determine whether they inherit from
a specied class.
14
signals
and slots.
property
system.
class
Q_OBJECT
Q_PROPERTY(
public
int
QObject
p r i o r i t y READ p r i o r i t y
setPriority )
public
void
doSomething ( ) ;
15
WRITE
void
int
private
int
int
const
setPriority (
priority ()
priority ) ;
;
myMember ;
};
Actually, C++ does oer a technique for connecting objects between each other,
namely function callbacks: Imagine object B (the
slot
signal
of class QObject,
thus connecting a signal to a slot (or multiple slots) can be done anywhere in
code, not necessarily resident in the object containing the signal or the slot.
16
Figure shows the sequence diagram of the now decoupled sender (publisher)
and retriever (subscriber).
#include
#include
int
int
<Q A p p l i c a t i o n >
<QPushButton>
main (
argc ,
QApplication
QPushButton
char
argv
app ( a r g c ,
button
[])
new
QObject : : c o n n e c t ( b u t t o n ,
SLOT( q u i t ( ) ) ) ;
return
QPushButton ( " H e l l o
World " ) ;
SIGNAL ( c l i c k e d ( ) ) , &app ,
button
>show ( ) ;
argv ) ;
app . e x e c ( ) ;
17
This example connects the button's signal with the application's slot without tying them together. In practice, classes in the Qt library provide a lot of
signals and slots suited for GUI programming; some self-describing examples for
signals are QLineEdit::returnPressed() and QProgressBar::valueChanged();
some examples for slots are QWidget::hide(), QWidget::showFullScreen()
and QTextEdit::paste().
described in chapter 5.
3.3.1 Networking
The Qt library comes with extensive networking support. As Qt is mostly used
as a GUI framework, most network classes concentrate on client side networking,
i.e. there are classes for issueing HTTP, TCP and UDP requests, but no HTTP
server class (there is, however, a TCP server class).
stack in chapter 5 only supports client-side SOAP over HTTP, so here only the
client-side HTTP networking classes shall be considered.
As of version 4.4, Qt contains a fully HTTP 1.1 compatible HTTP stack,
called the Network Access API. It consists of the following classes:
QNetworkAccessManager :
work via its methods get, post, put and head, which resemble
the respective HTTP verbs. Upon receiving the response, it issues
the signal nished(); this signal can then be connected to a slot in
a custom class to parse the response.
The QNetworkAccessMan-
QNetworkRequest :
and HTTP header elds, but not the payload data (which is handled
separately when e.g. posting or putting via the QNetworkAccessManager).
QNetworkReply :
18
The network access API only supports asynchronous calls via Signals and
Slots; retrieving a resource synchronously must be implemented by a user.
Listing 8: example usage of the Network Access API
1
2
3
4
5
6
7
8
9
10
#include
#include
#include
class
public
void
<QNetworkReply>
<QDebug>
NetworkSample
Q_OBJECT
public
QObject
slots :
r e p l y F i n i s h e d ( QNetworkReply
reply )
qDebug ( ) <
< reply
>r e a d A l l ( ) ;
11
12
networksample . h
<QObject>
}
};
13
14
15
16
17
18
19
20
#include
#include
#include
#include
#include
main . cpp
<Q A p p l i c a t i o n >
<QNetworkAccessManager>
<QNetworkRequest>
<QNetworkReply>
" networksample . h"
19
21
22
int
main (
int
char
argc ,
QApplication
argv
app ( a r g c ,
[])
argv ) ;
23
NetworkSample
24
QNetworkAccessManager
sample ;
25
QObject : : c o n n e c t (&manager ,
manager ;
SIGNAL ( f i n i s h e d (
QNetworkReply ) ) , &s a m p l e ,
SLOT( r e p l y F i n i s h e d (
QNetworkReply ) ) ) ;
26
27
28
return
app . e x e c ( ) ;
3.3.2 XML
Qt provides extensive support for dealing with XML documents and data. It
includes classes for accessing XML via the SAX2 interface, the DOM interface
and via streaming (see also [1]). The SAX and DOM implementations are not
covered here, since they are not used in the SOAP implementation described
in chapter 5.
The XML classes that are used, however, are the XML stream
What this
means is that a SAX API provides callbacks that are called from the parser
whenever a part of the documents are read; as an example (taken from
[1], chapter 15), when parsing the document from Listing 9, the following
events are reported to the respective event handlers:
Listing 9: A simple XML document
<d o c>
<q u o t e>Ars
longa
vita
b r e v i s</ q u o t e>
</ d o c>
startDocument ( )
s t a r t E l e m e n t ( " doc " )
startElement (" quote ")
c h a r a c t e r s ( " Ars
longa
vita
b r e v i s ")
20
( not
finished )
p a r s e r . readNext ( ) ;
i f ( too
much memory
consumed )
break ;
s w i t c h ( p a r s e r . tokenType ( ) )
case
//
case
do
something
with
the
start
something
with
the
text
with
the
end
element
Text :
//
case
StartElement :
do
EndElement :
//
do
something
element
}
}
For
21
The theoretical aspects of Web services have been explained in chapter 2.1; this
chapter does not only try to explain dierent Web service standards, but also
how they are used in practice and how dierent standards are typically used
together (e.g. SOAP and WSDL).
There are a lot of well-known Websites that oer a Web service API, some
of them use SOAP as an interface, and some other techniques like REST; the
reasons for choosing either technique are explained in the remainder of this
chapter. Some examples for services using a SOAP interface are: eBay API ,
3
4
Microsoft MSN Search and Google AdWords .
Examples for Web services using a REST interface are: Facebook , Flickr
7
and Youtube .
Platform
open
W3C standard.
2 http://developer.ebay.com/developercenter/soap/
3 http://search.msn.com/developer/
4 http://www.google.com/apis/adwords/
5 http://developers.facebook.com/documentation.php
6 http://www.ickr.com/services/api/
7 http://code.google.com/apis/youtube/overview.html
22
Human
attachment support.
(attachments here means binary data not inlined in the XML itself ) via either MIME or, more eciently, an own W3C standard
called MTOM ([10]).
protocol. In fact, the most common case is using SOAP over HTTP,
but there are also toolkits supporting e.g.
XMPP. This allows not only the nodes that are processing SOAP
messages to be independent of each other, but also the underlying
network structure to be independent of a specic protocol.
operability Organization .
8 http://www.ws-i.org/
23
24
The reason for splitting the scenario in two diagrams is that the scenario
consists of two phases: The rst phase, shown in Figure 10, shows the
time
1.
compile
of the scenario:
publish :
part of the server side component of SOAP, it is not described in this document.
However, a WSDL le is usually automatically generated from a programming
language specic interface (e.g. a Java interface or a C++ header le). After
creating the WSDL le, it is typically uploaded to a Web server.
2.
retrieve :
The service requester retrieves the WSDL le. Usually, the ser-
vice provider just tells the requester the URL of the WSDL le. More advanced
techniques like Web service registries (e.g. UDDI) are not treated here.
3.
generate code :
WSDL le. For this purpose, SOAP toolkits usually oer a command-line tool
to create programming language code from the WSDL (e.g. Wsdl2Java from
the Axis framework or Wsdl2h from the gSOAP framework).
Figure 11 shows the
4.
SOAP request :
runtime
vice provider. As already explained, this happens by using the code generated
in step 3, thus abstracting from the XML layer.
5.
SOAP response :
Again, the requester accessess the response via the generated code.
document
and
document
So a
RPC
SOAP
tains one single XML element (as child of the SOAP body); that single element
can contain a list of (in most cases simple) arguments.
Distinguishing between the datatypes used in the message, there are two
dierent data encodings:
SOAP encoding
and
uses the datatype encoding described in section 5 of the SOAP standard ([27],
therefore it is also often called Section 5 encoding).
25
ENC:string>hello</myString>', with the SOAP-ENC prex set to a special URI (http://schemas.xmlsoap.org/soap/encoding/) in the SOAP envelope. The other option,
literal encoding,
element in the SOAP message itself. In that case, the datatype of an element
is given in a WSDL le (see chapter 4.1.2) and is usually described with XML
Schema (also described in chapter 4.1.2).
Combining these options, the most one used in practice is document/literal.
Sometimes the rpc/encoded style is applied, but as of this writing (August
2008) it is mostly outdated. The WS-Interoperability Standard ([5], see below)
even mandates the usage of document/literal SOAP messages, so this one
is the only one treated in this document.
WSDL
As already said, WSDL ([3]) stands for Web Service Description Language,
and is XML-based. A WSDL le describes all details that are necessary to make
a valid SOAP call; consider again Listing 1. What the requester needs to know
to make the request is: The URL to post the request to, the HTTP header eld
SOAPAction, and the structure of the body. All this information is contained
in a WSDL; Listing 11 shows a complete WSDL le (in the currently most
widely used version 1.1). It consists usually of the following parts:
An XML Schema part (Lines 3 - 20). This is described in the next section.
C function or
Java/C# method).
26
A port is an
xml version
<?
<d e f i n i t i o n s
=" 1 . 0 "
StockQuoteURI "
"
name=" S t o c k Q u o t e "
t a r g e t N a m e s p a c e="
x m l n s=" h t t p : / / s c h e m a s . x m l s o a p . o r g / w s d l /
x m l n s : s o a p=" h t t p : / / s c h e m a s . x m l s o a p . o r g / w s d l / s o a p / "
<t y p e s>
<x s : s c h e m a
e l e m e n t F o r m D e f a u l t=" q u a l i f i e d "
<x s : e l e m e n t
< x s : s e q u e n c e>
<x s : e l e m e n t
9
10
name=" G e t L a s t T r a d e P r i c e ">
<x s : c o m p l e x T y p e>
name=" s y m b o l "
</ x s : s e q u e n c e>
</ x s : c o m p l e x T y p e>
11
</ x s : e l e m e n t>
12
<x s : e l e m e n t
13
14
< x s : s e q u e n c e>
15
<x s : e l e m e n t
16
17
18
19
name=" G e t L a s t T r a d e P r i c e R e s p o n s e ">
<x s : c o m p l e x T y p e>
name=" p r i c e "
</ x s : s e q u e n c e>
</ x s : c o m p l e x T y p e>
</ x s : e l e m e n t>
</ x s : s c h e m a>
20
</ t y p e s>
21
<m e s s a g e
22
<p a r t
name=" P r i c e R e q u e s t ">
e l e m e n t=" t n s : G e t L a s t T r a d e P r i c e " name="
p a r a m e t e r s " />
23
</ m e s s a g e>
24
<m e s s a g e
25
<p a r t
name=" P r i c e R e s p o n s e ">
e l e m e n t=" t n s : G e t L a s t T r a d e P r i c e R e s p o n s e " name="
p a r a m e t e r s " />
26
</ m e s s a g e>
27
<p o r t T y p e
name=" S t o c k Q u o t e P o r t T y p e ">
28
<o p e r a t i o n
29
<i n p u t
30
31
name=" G e t L a s t T r a d e P r i c e ">
<o u t p u t
</ o p e r a t i o n>
32
</ p o r t T y p e>
33
<b i n d i n g
name=" S t o c k Q u o t e B i n d i n g "
t y p e="
t n s : S t o c k Q u o t e P o r t T y p e ">
34
<o p e r a t i o n
name=" G e t L a s t T r a d e P r i c e ">
27
35
<s o a p : o p e r a t i o n
s o a p A c t i o n=" S t o c k Q u o t e A c t i o n "
style
<i n p u t>
37
<s o a p : b o d y
38
39
</ i n p u t>
<o u t p u t>
40
<s o a p : b o d y
41
</ o u t p u t>
42
</ o p e r a t i o n>
43
</ b i n d i n g>
44
<s e r v i c e
45
<p o r t
name=" S t o c k Q u o t e S e r v i c e ">
b i n d i n g=" t n s : S t o c k Q u o t e B i n d i n g " name="
S t o c k Q u o t e B i n d i n g ">
46
<s o a p : a d d r e s s
l o c a t i o n=" h t t p : / /www . s t o c k q u o t e s e r v e r
</ p o r t>
48
</ s e r v i c e>
49
</ d e f i n i t i o n s>
XML Schema
XML Schema ([4]) is a language to describe the structure of XML documents. Unlike Document Type Denitions, XML Schema documents are also
based on XML. The language is used in WSDL les to describe the structure of
the XML sent inside the SOAP body and header data. It will not be described
here, but it is necessary to deal with when writing a code generator in chapter
5. As already said, the SOAP standard comes with an own data encoding, but
the WS-Interoperability standard ([5], see below) forbids its use.
WS-* standards
To enrich the functionality of SOAP calls, dierent organizations (W3C, OA-
WS-Interoperability ([5]): does not really provide new features, but narrows down the SOAP (and WSDL) specication in order to improve interoperability between dierent SOAP implementations.
WS-Addressing
mation; for instance, the SOAPAction HTTP header eld contains such
information, but is tied to HTTP. WS-Addressing includes that information in the SOAP message itself.
WS-Security
9 http://www.oasis-open.org/
10 http://www.w3.org/Submission/2004/SUBM-ws-addressing-20040810/
11 http://www.oasis-open.org/specs/index.php#wssv1.0
28
WS-ReliableMessaging
nodes. Of course, as HTTP uses TCP, SOAP messages sent over HTTP
can be viewed as delivered reliably. However, WS-ReliableMessaging also
guarantees reliable delivery in case of spontaneous network or system failures.
WS-Policy
tion via a SOAP call, the amount of SOAP protocol specic information
(envelope, header, body etc.) might be even higher than the actual data
the SOAP node wants to send. Furthermore, using a binary format (e.g.
Java RMI) could result in lower transmission and message parsing time.
complex usage.
leaves room for dierent options (e.g. HTTP or TCP or something else as
underlying transport protocol, text or binary XML representation, SOAP
specic encoding or XML Schema). Moreover, for sending only few data
between network nodes going through a automatic code generation procedure might be overkill, and just building up the XML by hand is the
better solution.
imperfect interoperability.
gramming language code on the server side and the reverse procedure on
the client side do not work out-of-the-box and often require some editing
by hand. Again, this could result in too complex usage.
In this chapter some techniques are described that could be considered an alternative to SOAP.
4.2.1 Ajax
Ajax stands for Asynchronous JavaScript and XML. It is used in Web Sites to
improve user experience and fasten responsiveness: Using Ajax, the user does
not interact in the usual click and wait scenario with a Web page, but by
12 http://download.boulder.ibm.com/ibmdl/pub/software/dw/specs/ws-rm/wsreliablemessaging200502.pdf
13 http://www.w3.org/Submission/WS-Policy/
29
dynamically reloading small parts of the page: With the traditional web site
browsing scenario, the user controlled at what time an HTTP request was made
to the web server (e.g. when clicking a link or the back button of the browser).
However, when using Ajax, small portions of data are requested from the web
server by a layer called the Ajax engine; these requests transfer less data than
when loading a whole HTML page, but are made more often, which results in
better responsiveness and user experience. This scenario is depicted in Figure
12.
how the
browser displays the data received by the engine) is not explained in detail here;
it is sucient to know that the user interface processes the data to eventually
display HTML. The more relevant part is the HTTP request to the server and
the corresponding response. As Figure 12 shows, the overall concept of communication between the service requester (Ajax engine) and the service provider
(Web server) are similar to the SOAP communication ow: The Ajax engine
issues an HTTP request and gets back an HTTP response with the data.
However, the design goals of Ajax and SOAP are dierent.
According to
transferred to and from the server, there are dierent formats for data carried
in Ajax calls:
HTTP GET / POST : If possible, carrying no payload data from the Ajax
engine to the Web server is ideal; in that case, a simple HTTP GET with
information specied in the URL can be used. If the data should or can
not be sent in the URL, an HTTP POST with content type application/xwww-form-urlencoded can be used, sending simple key/value pairs in the
form key1=value1&key2=value2.
XML:
As the x in Ajax stands for XML, this is the usual way of trans-
mitting data, especially from the Web server to the receiver. However, one
30
JSON :
a syntax for storing JavaScript literals, namely objects and arrays. The
Listings 12 and 13 show the representation of an array in XML and JSON
(adapted from [31]), with the latter one needing less bytes for representation. This dierence may seem marginal here, but when transmitting a
lot of bytes, it can lead to a performance improvement using the JSON
approach. Moreover, when an Ajax engine receives a JSON construct, it
need not be parsed by hand to extract information into JavaScript language constructs, but can be included via JavaScript's eval() function
for interpreting code. Thus, JSON is a good alternative over XML when
making Ajax calls.
Smith</name>
"classinfo"
{
" students "
{
"name"
" Michael
Smith " ,
99.5 ,
17 ,
true
}
]
}
}
As a summary, Ajax and SOAP share the same overall communication
model, namely requesting and receiving data from a service provider.
31
This
data is usually formatted in XML, with JSON being a good alternative. While
sharing the same communication model, Ajax and SOAP have dierent application areas: While SOAP oers a generic model for communication over the
network, Ajax is tied closely to displaying HTML in Web pages.
As [31] explains, making SOAP calls with Ajax is possible, yet tedious; when
a service provider oers functionality that is to be used within Web pages, an
Ajax interface is better than a generic SOAP interface, which was the case why
Google shut down its SOAP interface and recommended using its AJAX search
API instead
14 .
15 (R emote
M ethod I nvocation)
calls tries to mimic performing local calls, thus hiding the low-level network
communication completely from the programmer.
This chapter only describes the parts of RMI that have a functional equivalent with the SOAP technology; advanced distributed object techniques of RMI
like e.g. distributed garbage collection are not described here.
As [19] describes, the core concept of RMI is to separate the denition of
functionality and its implementation. Thus, if an object's functionality shall be
accessible remotely, a Java Interface (denition of the object's functionality) is
made public for remote use, while the object's implementation is not exported.
Whenever now a client wants to access a remote object, it does so via a proxy
object (following the proxy design pattern from [8]), which resembles the object in client space.
the real object in server space, implement the same interface. Whenever the
proxy object's functionality is invoked, it forwards the call over the network to
the object in server space. Figure 13, adapted from [19], illustrates this.
In order to make an object accessible, the object resident in the server JVM
must register itself at a naming service.
Java Naming and Directory Interface (JNDI) or the RMI built-in service called
RMI registry.
server program can publish one of its objects to the registry by registering itself
at a RMI-style URL (of the form rmi://hostName:hostPort/myServiceName).
For a client program to invoke functionality of that remote object, it has to
know the URL that the remote object registered itself to, and instantiate the
object from that URL via RMI's naming technique. That instantiated object
is, as Figure 13 displays, a proxy object; when calls are made to this object,
they are forwarded via TCP to the object in server space. The serialization of
the call parameters is done in background, without the programmer needing to
14 http://code.google.com/apis/soapsearch/
15 http://java.sun.com/javase/technologies/core/basic/rmi/index.jsp
32
know the details. After instantiating the object from the URL, the object looks
like a local object to the programmer.
The serialization of the data from proxy to implementation object and back
is done in a binary format; since this binary format uses less network bandwith
than XML, RMI is usually more performat than a SOAP-based Web service
(see [9]).
Table 1 lists some concepts that are similar in both Java RMI and SOAP.
To summarize this chapter, Java RMI oers a ready-to-go interface for distributed programming. It is not a direct competitor with Web service, since it
focuses more on programming distributed objects than on loosely coupled systems as Web services do. That is, RMI oers a lot more functionality needed
by distributed objects or middleware systems (e.g. distributed garbage collection and remote object references); by also requiring Java to run on all entities
involved, it keeps them coupled together more tightly. As additional benets,
RMI provides lower network bandwith usage and the fact that a lot of the communication and serialization is hidden from the programmer, as Table 1 shows.
Systems interconntected by SOAP Web services, on the other hand, are more
loosely coupled than RMI: There are no such concepts like remote object references; the only contract between service provider and consumer is the WSDL
le, which describes how the XML sent back and forth should be formed. A service consumer needs to obtain the WSDL to access a service; from that WSDL,
he can create code in any language he wants to call the service. That is, using
the SOAP approach there is much more freedom to choose (programming languages, code generators etc.), but also more work to do, e.g. the code generation
from the WSDL must be invoked by hand.
33
RMI
SOAP
Java
any
Java interface
WSDL
service
exposure
generator + publishing
at Web server
programming
language
interface
specication
client code
creation
serialization
binary
XML
underlying
TCP
HTTP
service
endpoint
JNDI)
time)
protocol
specication
Table 1: Java RMI and SOAP concepts
It is rather
Addressability :
Uniform interface :
34
Web server.
system:
Resources are Web pages, which are accessed usually only for
retrieving (not for updating); that is, when browsing Web pages, a browser
sends only HTTP GET messages to the Web server. However, some Web
2.0 techniques like Ajax described in chapter 4.2.1 violate the REST view
of Web sites: Using Ajax, dierent content can be displayed under the
same URL by changing the content dynamically; that is, there can be
dierent resources accessed via one URL.
RSS/Atom feeds.
date. By checking the publishing date of each article, a feed reader can
now retrieve the new feeds via the article URL. Additionally to such a
16 provides means
are Facebook
access, but not content formats. Thus, many dierent content formats are possible:
XML (either described and built up by hand or some XML language,
e.g. RSS, Atom or XSPF)
In practice, mostly simple XML is used; i.e. it is no special XML dialect nor
specied via an XML schema langauges. Other formats like JSON or text formats are also used.
35
21 :
Amazon has both SOAP and REST interfaces to their web services, and 85%
of their usage is of the REST interface). However, REST and SOAP are not
direct competitors, but serve rather dierent elds:
1.
As de-
scribed earlier in this chapter, the REST paradigm suggests resourceoriented access to a system with four basic access methods (create, read,
update, delete) to the resources. It does no mandat the data format used
for accessing the system; thus, a lot of heterogeneous systems are considered REST-based.
mandates the usage of XML and describes the structure of SOAP messages.
2.
As already ex-
plained in detail, the base of a REST-ful system is a collection of resources that are accessed via URIs. SOAP on the other hand, is rather
activity-oriented, as its original focus was set on Remote Procedure Calls.
However, with a specically designed WSDL it is possible to mimic a
resource-oriented architecture. But in general a REST-based system consists of a lot of resources that are accessed via four easy methods, while
a SOAP system consists of a few endpoints (resources) that are accessed
via many dierent (and sometimes complex) methods.
3.
That is,
REST with e.g. TCP instead of HTTP does not make sense. SOAP, on
the other side, can use any underlying protocol for transportation; because
of that it can use any underlying protocol only as a transport protocol:
4.
21 http://www.oreillynet.com/pub/wlg/3005
36
6.
Most of
22 ; this
22 see
3. Does the tool comply to Web service standards (SOAP standard and WSInteroperability) and does it provide support for additional WS-* standards (e.g. WS-Security and WS-Addressing or MTOM for attachments)?
Jabber, MQSeries, FTP and SMTP. The module comes with a command-line
tool to generate code from WSDL les.
A disadvantage of SOAP::Lite is its focus on rpc/encoded SOAP calls, which
are outdated nowadays, as already explained in chapter 4.1.1.
x m l n s : x s i=" h t t p : //www . w3 . o r g / 2 0 0 1 /
XMLSchema i n s t a n c e "
x m l n s : s o a p e n c=" h t t p : / / s c h e m a s .
23 http://www.soaplite.com/
24 http://soaplite.com/features.html
38
x m l n s : x s d=" h t t p : / /www . w3 .
s o a p : e n c o d i n g S t y l e=" h t t p : // s c h e m a s
x m l n s : s o a p=" h t t p : //
s c h e m a s . x m l s o a p . o r g / s o a p / e n v e l o p e / ">
<s o a p : B o d y>
<e c h o
x m l n s=" h t t p : / / l o c a l h o s t /Demo">
<myArgument
x s i : t y p e =" x s d : s t r i n g ">myValue</
myArgument>
</ e c h o>
</ s o a p : B o d y>
</ s o a p : E n v e l o p e>
x m l n s : x s i =" h t t p : / /www . w3 . o r g / 2 0 0 1 /
XMLSchema i n s t a n c e "
x m l n s : s o a p e n c =" h t t p : / / s c h e m a s .
x m l s o a p . o r g / s o a p / e n c o d i n g /"
o r g / 2 0 0 1 /XMLSchema"
x m l n s : x s d=" h t t p : / /www . w3 .
s o a p : e n c o d i n g S t y l e =" h t t p : / / s c h e m a s
. xmlsoap . o r g / s o a p / e n c o d i n g /"
x m l n s : s o a p=" h t t p : / /
s c h e m a s . x m l s o a p . o r g / s o a p / e n v e l o p e /">
<s o a p : Body>
<e c h o R e s p o n s e
x m l n s=" h t t p : / / l o c a l h o s t /Demo">
myValue</e c h o R e s p o n s e >
</ s o a p : Body>
</ s o a p : E n v e l o p e >
#! / usr / b i n / p e r l
use
print
SOAP : : L i t e ;
>
>
>
>
>
SOAP : : L i t e
on_action (
sub
})
# a l t e r n a t i v e t o above l i n e : XPath
# > v a l u e o f ( ' / Envelope /Body / [ 1 ] / [ 1 ] ' ) ;
In Listing 16, a SOAP call is made and its answer parsed immediately in
the lines 5 - 10. Line 6 sets the global namespace of all XML elements that are
descendants of the SOAP body element (in Listing 14, these are the echo
and myArgument elements).Line 7 sets the SOAPAction HTTP header eld;
line 8 sets the address to post the HTTP request to; line 9 species the actual
39
payload data (as children of the body element: the call to echo results an
echo XML element as single child of the SOAP body element. Since that
call in line 9 looks like a function call, this points out the focus on RPC of
SOAP::Lite. Arguments to the echo element can be supplied as shown in line
9 via SOAP::Data constructs.
blocks until the SOAP response has arrived and prints the result in line 10.
The call to the result function in line 10 returns the contents of the child
of the SOAP body element, in the case of Listing 15, the string myValue is
returned. This again shows how SOAP::Lite is focused on RPC calls, since the
rst element of the body item is not returned and only one single argument in
the return function is expected. Alternatively, SOAP responses can be parsed
via XPath, as shown in line 12: This is a very powerful and elegant way to
extract information from complex or deeply nested elements.
The SOAP::Lite API is easy to start with, but has several disadvantages:
setting the SOAPAction HTTP Header eld: When not overriden, SOAP::
Lite assumes the SOAPAction eld to be of the form URI#methodName,
in the case of Listing 16 it would be "http://localhost/Demo#echo". In
many cases, this needs to be overridden, which can only be done in a
non-intuitive way, as Listing 16 shows in line 7.
16 above with '-> echo("myArgument")', this will be encoded as '<cgensym3 xsi:type="xsd:string">myArgument</c-gensym3>'; these additional elements called c-gensym3 are of course not always wanted.
Besides of that, overriding the namespace of XML elements is also not
intuitive
25 .
that automatically sets the correct HTTP POST address, the SOAPAction
25 for
how this is done,
consult the SOAP::Lite
http://search.cpan.org/~byrne/SOAP-Lite/lib/SOAP/Lite.pm
40
documentation
at
HTTP header eld and the namespace of the XML elements inside the SOAP
body.
For in-
3. Does the tool comply to Web service standards and does it provide support
for additional WS-* standards?
As already said, SOAP::Lite complies to both SOAP 1.1 and 1.2 and by
default sends rpc/encoded SOAP messages. The latter does not comply to the
WS-Interoperability standard ([5]), as it states (in section R1005):
An ENVELOPE MUST NOT contain soap:encodingStyle attributes on any of the elements whose namespace name is
"http://schemas.xmlsoap.org/soap/envelope/".
This default usage of rpc/encoded calls can be overriden to use literal calls, but
would be quite tedious, since for every XML element used in the call the type
would have to be overridden.
Besides of that, SOAP::Lite does not provide support for additional WS-*
standards like WS-encryption or WS-Addressing. However, it supports binary
attachments via multipart/MIME messages (often called SOAP with Attachments, SwA); additionally, it supports DIME, which is an advanced standard
for binary attachments in SOAP
lete and the usage of MTOM encouraged, which is not supported by SOAP::Lite.
As a summary, SOAP::Lite seems quite outdated nowadays with its focus
on rpc/encoded messages, no support for WS-* standards and its poor support
of WSDL code generation.
26 http://soap.search.msn.com/webservices.asmx?wsdl
27 http://xml.coverpages.org/draft-nielsen-dime-00.txt
41
Apache Axis2
It supports both SOAP standards 1.1 and 1.2, and its code generator supports
both common WSDL verisons 1.1 and 2.0. According to [14], Axis2 oers the
following protocols for transportation of SOAP messages: HTTP, HTTPS, TCP,
SMTP, JMS and XMPP. Apart from that, it supports attachments via both
SOAP with Attachments (SwA) and the more advanced MTOM. Axis2 has
also implementations for many WS-* standards (among them the important
WS-Security and WS-Addressing), which are explained below.
The Axis2 framework even oers REST-style interfaces for its services; however, there are discussions
oering a URI-style service access method (for instance, HTTP GET methods
can in Axis2 change data resources).
Axis2 has as its two main goals exibility and extensibility. These goals are
achieved by structuring Axis2 in a modular architecture, as shown in Figure 15
(adapted from [14]).
28 http://ws.apache.org/axis2/index.html
29 e.g. http://atmanes.blogspot.com/2007/06/how-not-to-do-restful-web-services.html
42
from a WSDL (on the client and sometimes also on the server side) or
generating a WSDL from code (on the server side). When creating a Web
service, the former approach (generating server-side code from a WSDL)
is called contract-rst approach, since the WSDL servers as a contract between the service provider and the service consumers. The other approach
is to generate a WSDL from a given piece of code, and is called code-rst
approach. As these techniques are only relevant on the server side, they
are not discussed here. On the client side, the only relevant approach is
to generate code from a WSDL.
language access level to SOAP messages, especially to the XML inside the
SOAP header and body. It has not been included in the core to leave the
exibility to provide other data bindings in the future. Axis2 comes with
four dierent data bindings; they dier in various items like for instance
usage complexity, coverage of supported XML Schema constructs and API
oered to the user.
conguration context of a message. It is split up into a Description Hierarchy, which keeps static data (coming from e.g. system congurations) and
a Context Hierarchy, which keeps dynamic data. Both hierarchies provide
dierent layers of conguration contexts (that is: key-value pairs), where
the lower layer override the values from the above layer. The layers for
both hierarchies are, from down to up: Message layer, Operation layer,
Service layer, ServiceGroup layer, Conguration layer.
O bject M odel);
Axi s2
lier) for ecient usage; these details are encapsulated in the implementation and hidden from the user.
Deployment Model :
43
Transport Model :
ServiceClient API :
basic Web Service features. It allows only to get and set the SOAP body,
and to add content to the SOAP header, but it does for instance not allow
to retrieve header elds. When sending simple messages without usage of
WS-* protocols, the ServiceClient is the right choice.
OperationClient API :
ServiceClient API
As a usage example of that API, consider again the sample from Listing 14.
The Axis2 sequence diagram to issue a client call can be seen in gure 16; the
corresponding code to send the message in Listing 14 can be seen in Listing 17.
Listing 17: A simple Axis2 client
1
2
3
4
5
6
7
import
// import
public class
public static void
try
[ . . . ] ;
AXIOMClient
s t a t e m e n t s l e f t out
{
main ( S t r i n g [ ]
args )
// c o n s t r u c t XML
OMFactory
f a c = O M A b s t r a c t F a c t o r y . getOMFactory ( ) ;
l o c a l h o s t /Demo" ,
10
OMElement
p a y l o a d = f a c . c r ea t eO M El em e nt ( " e c h o " ,
omNs )
;
11
OMElement
omNs ) ;
44
12
v a l u e . a d d C h i l d ( f a c . createOMText ( v a l u e ,
13
payload . addChild ( v a lu e ) ;
14
15
// h an d l e HTTP r e q u e s t
16
Options
17
o p t i o n s . setTo (
18
options =
/Demo" ) ) ;
new
new
Options ( ) ;
ServiceClient
20
21
sender =
new
19
22
23
OMElement
ServiceClient () ;
24
result
// p a r s e r e s p o n s e
25
26
String
27
System . e r r . p r i n t l n ( " r e s p o n s e :
28
29
( Exception
r e s u l t . getFirstElement ( ) . getText ( ) ;
e)
e . printStackTrace () ;
30
31
32
catch
response =
}
}
45
" + response ) ;
The example above needs a lot more code than the SOAP::Lite one; one
reason might be the more compact syntax of Perl compared to Java, but for
instance generating the XML requires also more lines of code with Axis2 than
with SOAP::Lite. The XML payload generation is done in the lines 8 - 13, and
generates an echo element with a myArgument element as child. Lines 16 20 show how the HTTP values are set (endpoint URL and SOAPAction header);
line 23 sends the message in a
blocking
are discussed below. In the lines 26 and 27, the program parses the response
and prints it on the standard output.
The code above does not generate the same code as in Listing 14, there
are two dierences: First, the SOAP encoding attribute of the envelope is not
generated, as Axis2 concentrates on doc/literal SOAP calls. Second, it uses an
XML prex for the children of the SOAP body, which allows for the usage of
elements of the same name in dierent namespaces. Listing 18 shows the SOAP
request generated by Axis2.
Listing 18: SOAP request generated by Axis2
<s o a p e n v : E n v e l o p e
x m l n s : s o a p e n v=" h t t p : / / s c h e m a s . x m l s o a p .
o r g / s o a p / e n v e l o p e / ">
<s o a p e n v : B o d y>
<t n s : e c h o
x m l n s : t n s=" h t t p : // l o c a l h o s t /Demo">
call is the better alternative; however, this is more dicult to program. Axis2
supports non-blocking calls by using callbacks: When sending the message (via
the method sendReceiveNonBlocking), it just sends out the HTTP request
and returns immediately. But when invoking that method, a callback method
must be given to handle the HTTP response. When the program receives the
response, it calls the callback method that was registered earlier. Thus, while
waiting for the response, the program can do other tasks and does not stall. [14]
describes how to do asynchronous calls.
The synchronous and asynchronous calls both support sending and immediate receiving of messages (following the Message Exchange Pattern in-out).
There are also methods for only sending a message (MEP in-only):
sendRobust: This method also just sends the SOAP request and continues;
however, when there is an error, it throws an exception.
46
OperationClient API
As already sais, that API oers more functionality than the ServiceClient API,
but also requires more work. For instance, when creating a SOAP message by
hand with the OperationClient API, one has to create a SOAP envelope and
add headers and body to it (for how this is done, see [14]).
However, when using enterprise-level web services, the most common way is
to generate code from a WSDL le and not build up the SOAP calls by hand.
Therefor, the OperationClient API is not described here, but more focus is set
on code generation from a WSDL le.
when a contract-
rst approach was used). This section here only describes the client-side code
generation from a WSDL le.
The wsdl2java.sh tool is to be used from the command line; however, there
30 . But as all
are also plugins for use in Eclipse or a script for use in Apache Ant
those tools use the command-line tool in the end, the plugins are not described
here.
There are a lot of command line parameters for usage with wsdl2java which
show the feature-richness of Axis2; the most important among them are:
Ant build script (build.xml): An Ant script to compile and run the client
code.
Stub code: A le that contains stub classes for usage; it encapsulates all
needed HTTP information (POST URL and SOAPAction header eld)
30 http://ant.apache.org/
47
and provides Java access for items specied in the WSDL le (e.g. operations and XML Schema information).
Callback handler:
asynchronous invocation (this can be changed via command line parameters). The callback handler serves for asynchronous invocation and provides special callbacks for the operations dened in the WSDL.
An important aspect of the code generation is the data binding:
It controls
the programming language layer of the SOAP message that encapsulates the
low-level XML handling. Axis2 comes with four dierent data bindings:
ADB (Axis Data Binding): This is the default data binding; it is meant to
be simple and easy to start with. As a drawback, ADB does not support all
of the XML Schema standard (for instance, complex and simple extensions
and restrictions are not supported), but in many cases ADB is enough to
cover the whole XML Schema part of a WSDL le. In that case, it is the
easiest data binding to use.
XML Beans:
support the whole XML Schema standard. It is destined for complex XML
Schema documents, and has as a drawback a more complex interface. For
instance, the code generated for the MSN Search WSDL contains 258 Java
les and 470 other les, whereas the code generated for the same WSDL
but with ADB contains 2 Java les.
JibX: This data binding is useful for binding own classes to a Web service,
for instance when binding a legacy application to a Web service.
As an example, Listing 19 shows the XML Schema part that corresponds to the
SOAP messages in the Listings 14 and 15; Listing 20 shows how to send the
SOAP message from Listing 14 with the ADB data binding, and the Figures 17
and 18 show the UML representation of the two most important auto-generated
classes.
Listing 19: part of a WSDL le
1
<x s : s c h e m a
x m l n s : n s=" h t t p : / / l o c a l h o s t /Demo"
a t t r i b u t e F o r m D e f a u l t=" q u a l i f i e d "
qualified "
2
3
4
5
6
<x s : e l e m e n t
e l e m e n t F o r m D e f a u l t="
t a r g e t N a m e s p a c e=" h t t p : / / l o c a l h o s t /Demo">
name=" e c h o ">
<x s : c o m p l e x T y p e>
< x s : s e q u e n c e>
<x s : e l e m e n t
</ x s : s e q u e n c e>
48
</ x s : c o m p l e x T y p e>
</ x s : e l e m e n t>
9
10
11
12
<x s : e l e m e n t
...
<w s d l : p o r t T y p e
13
14
name=" e c h o R e s p o n s e "
</ x s : s c h e m a>
name=" M y S e r v i c e P o r t T y p e ">
<w s d l : o p e r a t i o n
</ w s d l : p o r t T y p e>
1
2
3
4
5
6
7
8
9
10
11
package
import
import
public class
public static void
try
new
l o c a l h o s t . demo ;
l o c a l h o s t . demo . M y S e r v i c e S t u b . Echo ;
l o c a l h o s t . demo . M y S e r v i c e S t u b . E c h o R e s p o n s e ;
MyService
main ( j a v a . l a n g . S t r i n g
MyServiceStub
Echo
e =
stub =
Echo ( ) ;
new
args [ ] ) {
MyServiceStub ( ) ;
12
EchoResponse
13
System . o u t . p r i n t l n ( " r e t u r n :
14
System . o u t . p r i n t l n ( e r . g e t E c h o R e s p o n s e ( ) ) ;
15
16
17
( Exception
") ;
e){
e . printStackTrace () ;
18
19
20
catch
e r = stub . echo ( e ) ;
}
}
In the listing above, line 9 creates the stub that was automatically generated
from the WSDL. As already explained, that stub encapsulates as much information as possible and contains for each WSDL operation a member method:
For instance, as the WSDL in Listing 19 contains an operation called echo
in line 13, the stub class contains a member method named echo (line 12
in Listing 20).
Line 11 sets the SOAP body, namely sets the content of the
pletely encapsulated from the user by oering an interface written in Java. The
generated code class takes care of the right namespaces and element names. Line
12 sends out a blocking call and line 14 again extracts the needed information
from the SOAP response message.
This chapter has explained the thorough code generation support that Axis2
oers. It is one of the few toolkits that provide full XML Schema support, moreover, it comes with pluggable data binding support and additional features like
49
50
3. Does the tool comply to Web service standards and does it provide support
for additional WS-* standards?
Axis2 supports several WS-* standards. Only one of them is part of the Axis2
distribution, while all other modules are shipped as independent projects. The
supported standards are:
WS-Addressing: contained in the distribution, and serves to address messages and identify Web Services (e.g.
SOAPAction eld).
messages.
issuing and
WS-SecureConversation: part of Apache Rampart, built on top of WSSecurity and WS-Trust and serves to support secure communication between Web service nodes.
WS-SecurityPolicy:
31 http://ws.apache.org/rampart/
51
WS-BusinessActivity:
WS-MetadataExchange:
part of Axis2/metadataExchange
35 , servers to
base64 encoding: this might be an option when only few binary data is
sent and using one of the techniques below would be overkill.
SOAP with attachments (SwA): Axis2 automatically detects SOAP messages that contain SwA-style attachments via its content type. Those attachments can be retrieved by accessing the Message Context as described
earlier.
MTOM (Message Transmission Optimization Mechanism): Axis2 also automatically detects MTOM messages without the user needing to take
additional actions.
All in all, Axis2 is a very comprehensive Web service framework, if not the most
comprehensive at all. With its huge feature support and its exible architecture
it is suited to build enterprise applications.
versions 1.1 and 1.2 and WSDL version 1.1; WSDL version 2.0 is not supported
as of this writing.
32 http://ws.apache.org/sandesha/sandesha2/index.html
33 http://ws.apache.org/kandula/2/index.html
34 http://ws.apache.org/commons/neethi/index.html
35 http://wiki.apache.org/ws/Axis2/metadataExchange
36 http://www.cs.fsu.edu/~engelen/soap.html
52
building up a SOAP query by hand. But as code generation from WSDL is the
common use case, this is not a big disadvantage of gSOAP.
int
parameter
ns2__echo ,
&n s 2 _ _ e c h o R e s p o n s e
) ;
The second-phase tool called soapcpp2, takes as input that header le and
generates the following les (via the command soapcpp2 myservice.h):
37 http://www.cs.fsu.edu/~engelen/soapdoc2.html
53
The most important le needed when writing code is the binding proxy (soapMyServiceSOAP11BindingProxy.h), which contains all the necessary information. Listing 22 shows how the generated code can be used to invoke the service
(by sending the message from Listing 18).
1
2
3
4
5
6
#include
#include
#include
int
main ( )
MyServiceSOAP11Binding
echo
_ns2__echo
echo
>myArgument =
std : : s t r i n g
if
10
new
new
binding ;
_ns2__echo ( ) ;
s t d : : s t r i n g ( " myValue " ) ;
echoResponse ;
( b i n d i n g . __ns3__echo ( e c h o ,
)
11
e c h o R e s p o n s e ) == SOAP_OK
{
std : : cout <
< " result :
12
" <
< echoResponse <
< " \n" ;
else
13
14
15
16
{
s o a p _ p r i n t _ f a u l t ( b i n d i n g . soap ,
stderr ) ;
}
}
The code above is compact and self-explanatory. The only drawback here
is the cumbersome usage of namespace prexes in class names (e.g.
_ns2__echo).
class
54
3. Does the tool comply to Web service standards and does it provide support
for additional WS-* standards?
As already said, gSOAP supports both SOAP versions 1.1 and 1.2 and
WSDL version 1.1.
Basic Prole 1.0a
38 .
WS-Addressing
WS-Discovery
WS-Enumeration
WS-Security
38 see
some of its features make it somehow cumbersome to use (e.g. the two-phase
construction or the usage of namespace prexes in class and method names).
generation tool and supporting all SOAP and WSDL versions. It supports several WS-* standards and dierent kinds of attachments.
System ;
using
System . C o l l e c t i o n s . G e n e r i c ;
using
System . L i n q ;
using
System . Text ;
namespace
{
ConsoleApplication1
class
static void
Program
Main ( s t r i n g [ ]
MyService
string
service
result
args )
new
MyService ( ) ;
Console . WriteLine ( r e s u l t ) ;
}
39 http://msdn.microsoft.com/netframework/
56
}
}
Making asynchronous calls can be done in dierent ways, as [17] describes:
The common way to make asynchronous calls with .NET generated code
is to use callbacks, as already described earlier.
the generated code containing the synchronous method echo as well as the
asynchronous method Beginecho which takes a callback method as argument,
and, after being called, returns immediately. Finally, the Endecho call can be
called by the callback method when the response has been retrieved.
public
object [ ]
[]
return
echo ( s t r i n g
results
myArgument )
this
new
object
myArgument } ) ;
(( string ) ( results [ 0 ] ) ) ;
/// <remarks/>
public
System . I A s y n c R e s u l t
Beginecho ( s t r i n g
myArgument ,
System . A s y n c C a l l b a c k
asyncState )
return this
57
callback ,
new
callback ,
object
object [ ]
asyncState ) ;
/// <remarks/>
public
)
string
object [ ]
Endecho ( System . I A s y n c R e s u l t
return
results
this
asyncResult
. EndInvoke ( a s y n c R e s u l t ) ;
(( string ) ( results [ 0 ] ) ) ;
Another way of issuing an asynchronous call is to use the WaitHandle technique: Sometimes, when using the Callback technique, it might be undesired
that the callback method is called exactly when the Web service is nished;
sometimes, it is more convenient to let the user control when the Web service response is to be parsed.
It calls the same asynchronous method as the Callback technique, but without
registering a callback method. Instead, after nishing some other work, after
issuing the call and probably doing some other works, at some point it polls
for the request to nish. This technique can be seen as a hybrid between the
synchronous (polling) technique and the Callback technique. As an advantage,
it lets the programmer control when the response is parsed; as a disadvantage,
polling for the result to early might lead to wasted time as with synchronous
calls.
Those three methods (synchronous calls, Callbacks and WaitHandles) are
supported by .NET, as [17] describes.
3. Does the tool comply to Web service standards and does it provide support
for additional WS-* standards?
40 - some of them are part of the
WS-ReliableMessaging
WS-Addressing
WS-Security
WS-SecureConversation
WS-AtomicTransaction
WS-Discovery
40 for
a
complete
list,
us/library/aa480728.aspx#wsmsplat_topic32
58
see
http://msdn.microsoft.com/en-
All in all, the .NET framework comes with excellent support for code generation and WS-* standards and is suited to build enterprise applications. Its
internals are not documented as well as e.g. Axis2, but its API is both easy to
start with and powerful.
toolkit and the primary use case for building applications using SOAP.
The SOAP toolkit proposed in chapter 5 should thus contain a commandline tool that takes as input a URL or a path and produces C++ code
stubs that use the Qt library. That code stubs should ideally both oer
an easy API and at the same time should be powerful to support most
common WSDL and XML Schema constructs.
2.
However,
asynchronous calls.
ture that is supported by both Axis2 and gSOAP: gSOAP oers dierent
mappings from XML Schema types to programming language data types.
The data bindings that Axis2 oers all have their own architecture, which
makes the toolkit very exible. However, for the Qt framework it should
always be clear what XML Schema type to map to which Qt data type,
so in the rst version of the Qt SOAP toolkit it will be acceptable to
hard-code the data types.
5.
The
WSDL standard is tied closely to the XML Schema standard; that is,
59
toolkit it would be desirable to separate the XML Schema part from the
WSDL part and pack the XML Schema part into a component that is
reusable in other contexts.
6.
60
This chapter shall propose an architecture for the QtSoap module. The framework consists of two main parts: First, the C++ classes for sending and receiving
SOAP messages; second, the WSDL parser for generating code. As already described partially in chapter 3, the C++ classes rely on the following Qt classes:
QtCore classes :
anism and the XML streaming classes (QXmlStreamWriter and QXmlStreamReader) reside in QtCore; moreover, basic classes like QString and
QLinkedList are also part of QtCore.
QtNetwork classes :
XML data types for representing SOAP message elements (like arrays or
nested structures)
XML parsing for generating SOAP message elements from XML and back
QtSoapQName
This class represents a qualied name as dened in the XML Schema standard. That is, it contains a local name and a namespace URI; however, it does
not contain a prex, because the prex is automatically given to XML elements
when using the QXmlStreamWriter class.
QtSoapType
This is an abstract class generalizing the dierent SOAP data types. Basically speaking, it contains XML information that is common for all elements,
61
Figure 23: data type class diagram for the QtSOAP framework
62
e.g. the information from QtSoapQName as well as XML attributes and methods for serialization (the methods toXml() and serialize() are overriden in
the subclasses).
As an API, it contains the union of the functionality of its subclasses (those
functions are not shown in the class diagram above). Those functions are implemented as dummy functions as in Listing 25; they are overridden in the
subclasses if the classes contain that functionality.
void
const
to
QtSoapData &n o d e )
not
supported
on
that
type " ) ;
QtSoapData
This is a wrapper class for instances of class QtSoapType.
It oers more
or less the same API as class QtSoapType, but allocates instances on the heap
(with the new operator).
an example, consider a function that takes as argument any SOAP data type.
If its signature would take a QtSoapType as argument (i.e.
if it looked like
void
const
QtSoapData &i t e m )
d
>i n s t a n c e
>append ( i t e m ) ;
}
Besides the QtSoapType instance, the class contains a static method to
create a QtSoapData instance from a QByteArray; this function is used when
receiving a SOAP message over the network.
QtSoapSimpleType
This class represents a specic SOAP data type, namely an XML element
that only contains text and no other XML elements as children. Apart from the
methods and attributes inherited from QtSoapType, it contains only a value
attribute (plus its getter- and setter methods) for storing the value of the XML
element. Listing 27 shows the XML representation of a QtSoapSimpleType.
Listing 27: A QtSoapSimpleType
63
<myType>myValue</myType>
QtSoapFault
This class represents a SOAP fault according to the SOAP standard ([27]).
A SOAP fault is a Fault element resident in the same namespace URI as
the envelope; this element contains the mandatory children faultcode and
faultstring and an optional element detail, as in Listing 28.
Listing 28: A QtSoapFault
<SOAP ENV:Fault
xmlns:SOAP
ENV ' h t t p : / / s c h e m a s . x m l s o a p .
=
o r g / s o a p / e n v e l o p e / '>
< f a u l t c o d e>app . e r r o r</ f a u l t c o d e>
< f a u l t s t r i n g> A p p l i c a t i o n
< d e t a i l> d e t a i l s
go
E r r o r</ f a u l t s t r i n g>
h e r e</ d e t a i l>
</SOAP ENV:Fault>
QtSoapStruct
This class represents an XML element that contains other elements, as shown
in Listing 29.
from QtSoapType) for inserting and retrieving children elements; as the children again can be of any SOAP data type, a QtSoapStruct instance contains a
list of QtSoapData elements (that is, a member variable QList<QtSoapData>
children). A SOAP envelope is always of type QtSoapStruct, as it contains at
least always a body element.
Listing 29: A QtSoapStruct
<myType>
<myChild1>myValue1</ myChild1>
<myChild2>myValue2</ myChild2>
<myChild3>
<myOtherType1>myOtherValue1</ myOtherType1>
<myOtherType2>m y O t h e r v a l u e 2</ myOtherType2>
</ myChild3>
</myType>
QtSoapArray
This class is a speciality of a QtSoapStruct: A QtSoapArray contains children that are all of the same type, that is, that have the same qualied name,
as in Listing 30. As the QtSoapStruct class, it oers accessors for retrieving and
manipulating the children elements.
Listing 30: A QtSoapArray
<myType>
<myChild1>myValue1</ myChild1>
<myChild1>myValue2</ myChild1>
<myChild1>myValue3</ myChild1>
</myType>
64
Figure 24: messages and transports class diagram for the QtSOAP framework
Most code in those data type classes are easy getter and setter methods.
Exceptions of that are the XML serialization and deserialization, which are
described below in section 5.1.3; actually that feature should described here, as
the functionality is part of the data type classes, but conceptually they are part
of the XML parsing chapter.
QtSoapMessage
This class represents a SOAP 1.1 message; that is, it consists of a SOAP
envelope element that contains a body element (which is mandatory according to the SOAP standard) and methods to add QtSoapData elements to the
body and the header. To be more precise, QtSoapMessage contains a private
variable envelope of type QtSoapData which upon class instance construction
is initialized with an envelope element; this element contains a child element
of name body. Basically, the QtSoapMessage class is just a wrapper around
the QtSoapData class containing a specially designed element (the envelope);
the functionality of the class is limited to only modify the header and body
element of the envelope.
Listing 31 shows two public methods of class QtSoapMessage: The method
65
void
const
QtSoapData &newItem
return
SOAPv11_ENVELOPE) ] ;
QtSoapHttpTransport
This class provides functionality to send and retrieve SOAP messages over
HTTP (which is the only transport protocol supported in the QtSoap framework
so far). It encapsulates the network interaction via the Network Access API (i.e.
it contains instances of the classes QNetworkAccessManager, QNetworkRequest
and QNetworkReply) and provides higher-level signals and slots: When sending
a SOAP message, it takes as argument a QtSoapMessage and sends it via a
QNetworkRequest as shown in Listing 32.
Listing 32: Sending SOAP requests via QtSoapHttpTransport
void
QtSoapHttpTransport : : submitRequest (
b = r e q u e s t . toXml (
QByteArray
false
const
) ;
a = b . toUtf8 ( ) . constData ( ) ;
d
>r e p l y = d
>manager . p o s t ( d
>r e q u e s t ,
a) ;
}
When receiving a response from the NetworkAccessManager, the class parses
the response, then creates a QtSoapMessage, stores it at the response member
variable and then emits a signal. In order to rst parse the message and then
emit its own signal, QtSoapHttpTransport connects the QNetworkAccessManager's signal nished with its own slot replyFinished, as shown in Listing
33.
Listing 33: QtSoapHttpTransport constructor
Q t S o a p H t t p T r a n s p o r t : : Q t S o a p H t t p T r a n s p o r t ( QObject
:
QObject ( p a r e n t )
d =
new
QtSoapHttpTransportPrivate ;
d
>manager . s e t P a r e n t (
this
) ;
66
parent )
d
>r e q u e s t . s e t H e a d e r ( QNetworkRequest : :
ContentTypeHeader ,
c o n n e c t (&d
>manager ,
this
SIGNAL ( f i n i s h e d ( QNetworkReply
SLOT( r e p l y F i n i s h e d ( QNetworkReply
) )
) ) ) ;
setSoapAction ( "" ) ;
}
When the replyFinished slot has been called, it parses the response and
emits a signal, as shown in Listing 34.
Listing 34: parsing the SOAP response in class QtSoapHttpTransport
void
Q t S o a p H t t p T r a n s p o r t : : r e p l y F i n i s h e d ( QNetworkReply
{
QByteArray
b = d
>r e p l y
>p e e k ( d
>r e p l y
>
bytesAvailable () ) ;
QtSoapData
if
r e s p o n s e = QtSoapData : : importFromXml ( b ) ;
( response . type ( )
!=
QtSoapType : : S t r u c t )
qWarning ( " m a l f o r m e d
envelope
detected ") ;
}
d
>r e s p o n s e . s e t E n v e l o p e ( r e s p o n s e ) ;
emit
responseReady ( ) ;
}
An example of how to use the QtSoapHttpTransport class is given below in
chapter 5.1.4.
process.
The classes contain the following functionality:
QtSoapXmlElement
This class can be seen as a light version of the QtSoapData class; it only
contains the qualied name, attributes and a pointer to its parent (if it has
one) and its children (if it has some). The class serves to store XML elements
while parsing a document; a QtSoapXmlElement is constructed when it is not
yet clear what type of QtSoapType an element will become (this is explained in
detail below).
QtSoapXmlHandler
This is the main class involved in XML parsing and also the entry point.
When a byte stream is to be parsed by the QtSoapXmlHandler, QtSoapData's
67
Figure 25: XML parsing class diagram for the QtSoap framework
static function importFromXml needs to be called, which calls QtSoapXmlHandler's parse function. When that function is called, the handler creates
a QXmlStreamReader object (described in chapter 3), then adds the supplied
data to the parser and parses it, as Listing 35 shows.
Listing 35: QtSoap XML parsing
QtSoapData &QtSoapXmlHandler : : p a r s e (
buffer )
QTextStream
const
QByteArray &
out ( s t d o u t ) ;
QXmlStreamReader
xml ;
xml . addData ( b u f f e r ) ;
while
switch
case
(!
xml . atEnd ( ) )
xml . r e a d N e x t ( ) ;
( xml . t o k e n T y p e ( ) )
QXmlStreamReader : : S t a r t E l e m e n t :
s t a r t E l e m e n t ( xml . n a m e s p a c e U r i ( ) . t o S t r i n g ( ) ,
() . toString () ,
xml . name
xml . q u a l i f i e d N a m e ( ) . t o S t r i n g ( ) ,
xml
. attributes () ) ;
case
case
break
QXmlStreamReader : : C h a r a c t e r s :
c h a r a c t e r s ( xml . t e x t ( ) . t o S t r i n g ( ) ) ;
break
QXmlStreamReader : : EndElement :
e n d E l e m e n t ( xml . n a m e s p a c e U r i ( ) . t o S t r i n g ( ) ,
xml . name ( ) . t o S t r i n g ( ) ,
xml . q u a l i f i e d N a m e
() . toString () ) ;
case
break
QXmlStreamReader : : EndDocument :
68
endDocument ( ) ;
default
}
break
// do n o t h i n g
break
if
( xml . h a s E r r o r ( ) )
qWarning ( " an
error
occurred " ) ;
out <
< xml . e r r o r S t r i n g ( ) <
< endl ;
}
}
return
_soapType ;
As the listing above shows, the parser always processes the whole input at
once; there is no on demand or delayed parsing.
69
element stack keeps those elements that have started but not nished parsing.
Since an XML element is always in exactly one of the states already parsed,
being parsed and not yet parsed, both stacks together keep at most as many
elements as there are XML elements in the document.
There are two other parsing events: characters, which is called when characters are detected outside angle brackets. In that case, the content eld of
QtSoapXmlElement is set, and, after parsing that element, a QtSoapSimpleType is constructed.
when the XML document has been parsed completely. In that function, there
must exactly be one element on the type stack (the SOAP envelope) which is
then popped and set as the private member variable _soapType, as described
in Listing 36. That variable is returned as a result by the parse function (as
already shown in Listing 35).
bool
if
}
else
return false
{
_soapType = _ t y p e S t a c k . pop ( ) ;
70
return
_ t y p e S t a c k . empty ( ) ;
}
The reverse functionality, XML serialization, usually takes place when sending a message: as Figure 27 shows, when a message is sent, that call is passed
on to the SOAP envelope. That serialize function takes as argument a QXmlStreamWriter instance, writes its qualied name and attributes, then calls its
children's serialize function (for structs and arrays) or writes its content (for
simple types), and then writes its end attribute, as Listing 37 shows.
void
const
Q t S o a p S t r u c t : : s e r i a l i z e ( QXmlStreamWriter &w r i t e r )
{
w r i t e r . w r i t e S t a r t E l e m e n t ( name ( ) . n a m e s p a c e U r i ( ) ,
name
( ) . localName ( ) ) ;
writer . writeAttributes ( attributes () ) ;
for int
(
a = 0;
a < count ( ) ;
a++) {
d
>c h i l d r e n . a t ( a ) . s e r i a l i z e ( w r i t e r ) ;
}
w r i t e r . writeEndElement ( ) ;
}
When the serialization has nished, the string returned by QtSoapMessage::toXml is sent as HTTP body by the QtSoapHttpTransport class.
#ifndef
soaptest . h
SOAPTEST_H
71
#define
#include
class
public
private
void
private
SOAPTEST_H
" . . / . . / s r c / q t s o a p . h"
SoapTest
public
Q_OBJECT
QObject
parent
S o a p T e s t ( QObject
= 0) ;
slots :
getResponse ( ) ;
QtSoapHttpTransport
http ;
};
#endif
#include
#include
#include
#include
s o a p t e s t . cpp
<QtGui / Q A p p l i c a t i o n >
<QTextStream>
<QNetworkReply>
" s o a p t e s t . h"
S o a p T e s t : : S o a p T e s t ( QObject
http (
this
parent )
QObject ( p a r e n t ) ,
h t t p . s e t U r l ( " h t t p : / / l o c a l h o s t /Demo" ) ;
h t t p . s e t S o a p A c t i o n ( " mySOAPActionHeader " ) ;
c o n n e c t (& h t t p ,
SIGNAL ( r e s p o n s e R e a d y ( ) ) ,
getResponse ( ) ) ) ;
Qt Soap Mess age
QString
this
SLOT(
message ;
u r i ( " h t t p : / / l o c a l h o s t /Demo" ) ;
QtSoapStruct
uri ) ;
uri ,
"
myValue " ) ;
e c h o . append ( myArgument ) ;
m e s s a g e . addBodyItem ( e c h o ) ;
QTextStream
out ( s t d o u t ) ;
out <
< " request : " <
< endl <
< m e s s a g e . toXml ( ) <
< endl ;
http . submitRequest ( message ) ;
}
void
Msn : : g e t R e s p o n s e ( )
QTextStream
out ( s t d o u t ) ;
r e s p o n s e = http . soapResponse ( ) ;
if
( response . isFault () )
out <
< " string :
" <
< response . faultString () <
<
endl ;
}
else
72
out <
< " selected
element :
" <
< body [ " e c h o R e s p o n s e
parses the WSDL specic part of a WSDL le, while the second script, xsdSchema.xsl parses the XML Schema part of a WSDL le. Thus, the functionality of parsing WSDL and XML Schema are separated, and XML Schema les
can also be parsed independently of WSDL les.
The reason for choosing XSLT instead of parsing a WSDL le in C++ are
the following:
ease of use.
into code), and is thus a good choice for XML parsing. Writing a WSDL parser
in C++ would have required reading in the le, parsing each token and then
write to an output le.
performance.
le.
programming languages like Java or C++, the code generation process took a
lot of time and sometimes showed memory problems (e.g. the java generator
running out of heap space); this is a problem especially because WSDL les are
often auto-generated and several mega bytes of size.
41 had to be used.
This
41 http://www.xmlsoft.org/
73
WSDL
code
<port name=foo1>
<part name=foo2>
<operation name=foo3>
<message name=foo4>
<types>
xsl:template
xsl:apply templates
xsl:value of
match=" w s d l : p o r t ">
<
s e l e c t =" w s d l : d o c u m e n t a t i o n " /
>
class <
s e l e c t ="@name" />S t u b
public
QObject
Q_OBJECT
private:
QtSoapHttpTransport
_transport ;
public:
<
xsl:value of
0)
QObject ( p a r e n t )
parent
_ t r a n s p o r t . s e t U r l ( "< x s l : v a l u e o f
s e l e c t ="
s o a p : a d d r e s s / @ l o c a t i o n "/>" ) ;
}
(...)
</
xsl:template
>
<
xsl:template
74
75
(...)
//
<
member
variable
xsl:value of
xsl:value of
public:
//
member method
void <
xsl:value of
xsl:value of
s e l e c t ="@name" />(<
xsl:value of
s e l e c t ="@name" />_ s o a p A c t i o n ( ) ;
_ t r a n s p o r t . s u b m i t R e q u e s t ( param . s e r i a l i z e ( ) ) ;
c o n n e c t (& ; _ t r a n s p o r t ,
this ,
SLOT(<
() ) ) ;
SIGNAL ( r e s p o n s e R e a d y ( ) ) ,
xsl:value of
s e l e c t ="@name" />R e s p o n s e
}
(...)
</
xsl:template
>
Those operations take as argument a type that was generated from a WSDL
message element.
several member variables; for each WSDL part element inside a message
element the class contains one member variable; WSDL part elements are
transformed to own classes, which contain variables that were generated from
XML Schema types.
The XSL stylesheet shown in excerpts above generates valid C++ code using
QtSoap data types; however, it does not (yet) respect namespaces in element
names. For instance, a WSDL le could contain two WSDL message elements
with the same local name but a dierent namespace URI, which would cause
the code generator to create two classes of the same name. This is currently the
biggest drawback of the code generator.
the whole XML Schema standard, but to support the most frequently used
constructs in a robust way.
When parsing the XML Schema part of a WSDL le, it basically constructs
two types of classes: QtSoapSimpleType objects from simpleType elements
and QtSoapStruct objects from complexType elements. Figure 29 lists some
Schema constructs and its resulting code architecture.
Each generated class contains member variables according to the XML Schema
elements, the usual getter- and setter-methods and a serialize and deserialize
76
77
Figure 30: the auto-generated class for using the MSN API
function. When building up a SOAP request, the setter methods of the generated types can be used to build up the request; upon sending, the serialize
method is called which returns the correctly formatted QtSoap data type. When
receiving a SOAP response, the deserialize method is called to extract information from the XML and set the member variables, which can then be accessed
via getter methods.
As already said, by far not the whole XML Schema standard is supported
by the XSLT stylesheet; moreover, as with WSDL types, namespaces are not
respected. But since the most common constructs are supported, WSDL les
that contain easy XML Schema parts are parsed correctly.
42
WSDL code generator. As an example, a search with the MSN Search API
43
is performed, including code generation from the WSDL le . That API has
been chosen because the WSDL is relatively easy and small, but nevertheless is
a real-world example.
Invoking the code generator with the MSN WSDL produces a header le
that contains 29 classes; 5 of them deal with WSDL messages, elements and
bindings. The other 24 classes represent XML Schema types. The class responsible for sending and receiving messages is shown in Figure 30. The WSDL le
contains only the operation Search, and thus there is only one method in the
MSNSearchPortStub class that takes a QtSoapMessage as argument, namely
the method Search. Besides that, there is one method for getting the response
method (getSearchResponseMessageMessage) and one slot which is called by
the QtSoapHttpTransport member _transport. Listing 41 shows how to create the necessary types to invoke the Search method.
Listing 41: invoking the MSN Search with the QtSoap API
MSNSearchPortStub
stub ;
SearchMessageMessage
message ;
42 http://msdn.microsoft.com/en-us/library/bb251794.aspx
43 http://soap.search.msn.com/webservices.asmx?wsdl
78
SearchElement
searchElement ;
SearchRequestType
request ;
r e q u e s t . set_AppID ( " 8
E56C2042A3D27AC7439A863C38A3D51C396CEC7 " ) ;
r e q u e s t . set_Query ( " T r o l l t e c h " ) ;
r e q u e s t . s e t _ C u l t u r e I n f o ( " enUS" ) ;
LocationType
location ;
l o c a t i o n . set_Radius ( 5 . 0 ) ;
request . set_Location ( l o c a t i o n ) ;
ArrayOfSourceRequestRequestsType
SourceRequestType
SourceTypeType
requests ;
type1 ;
source1 ;
s o u r c e 1 . appendEnum ( S o u r c e T y p e T y p e : : _Web) ;
type1 . set_Source ( source1 ) ;
type1 . set_Offset ( 0 ) ;
t y p e 1 . set_Count ( 2 0 ) ;
SourceRequestType
SourceTypeType
type2 ;
source2 ;
s o u r c e 2 . appendEnum ( S o u r c e T y p e T y p e : : _News ) ;
type2 . set_Source ( source2 ) ;
type2 . set_Offset ( 0 ) ;
t y p e 2 . set_Count ( 2 0 ) ;
r e q u e s t s . append_SourceRequest ( type1 ) ;
r e q u e s t s . append_SourceRequest ( type2 ) ;
r e q u e s t . set_Requests ( r e q u e s t s ) ;
searchElement . set_Request ( r e q u e s t ) ;
message . set_SearchElement ( searchElement ) ;
stub . Search ( message ) ;
That code creates a SearchMessageMessage object (which is derived from
QtSoapMessage), then builds up the necessary request and nally sends out the
message. Building up the request requires the confusing task of buliding up a
lot of elements and then nesting them repeatedly.
avoided because the nested structure of the XML Schema elements and WSDL
parts just resembles the nested structure of the required XML; this complicated
structure is common to all SOAP frameworks. Figure 31 shows how the classes
required for a Search are nested.
When invoking the Search method, the class implementation uses the
_transport instance to send and receive the SOAP message.
When the
SearchResponseReady (see Listing 42), which tells the program it can now
access the data via the class' getter methods, as shown in Listing 43.
Listing 42: receiving the MSN Search response message
79
80
Figure 31: auto-generated class hierarchy for the MSN search
public
void
Q_SLOTS :
SearchResponse ( )
_SearchResponseMessage = SearchResponseMessageMessage
( _transport . soapResponse ( ) ) ;
_SearchResponseMessage . d e s e r i a l i z e ( ) ;
emit
SearchResponseReady ( ) ;
message = stub .
getSearchResponseMessageMessage ( ) ;
const
const
const
const
for int
S e a r c h R e s p o n s e E l e m e n t &s e a r c h R e s p o n s e E l e m e n t =
message . get_SearchResponseElement ( ) ;
S e a r c h R e s p o n s e T y p e &r e s p o n s e =
searchResponseElement . get_Response ( ) ;
A r r a y O f S o u r c e R e s p o n s e R e s p o n s e s T y p e &r e s p o n s e s =
r e s p o n s e . get_Responses ( ) ;
Q L i s t<S o u r c e R e s p o n s e T y p e > &s o u r c e R e s p o n s e =
r e s p o n s e s . get_SourceResponse ( ) ;
a = 0;
a++) {
out <
< "" <
<
endl ;
out <
< "results
for :
" <
< sourceResponse [ a ] . get_Source
() . toString () <
< "
(" <
< sourceResponse [ a ] . get_Total
() <
< ")" <
< endl ;
out <
< "" <
<
endl <
< endl ;
const
const
for int
ArrayOfResultResultsType &r e s u l t s
sourceResponse [ a ] . get_Results ( ) ;
Q L i s t<R e s u l t T y p e > & r e s u l t
r e s u l t s . get_Result
() ;
b = 0;
b <
out <
< "title :
r e s u l t . count ( ) ;
" <
<
b++) {
r e s u l t [ b ] . get_Title () <
< endl
;
out <
< "" <
<
endl ;
out <
< " description :
" <
<
result [b ] .
get_Description () <
< endl <
< endl ;
out <
< " url :
" <
<
r e s u l t [ b ] . get_Url ( ) <
< endl <
<
endl <
< endl ;
}
}
As with the creation of the SOAP message, the parsing of the response
requires accessing the nested class structure in the same way. Again, this cannot
81
be avoided; however, the code listings for creating the SOAP request and parsing
the response show that no XML whatsoever is involved, so the XML layer of
the SOAP call is encapsulated completely inside the generated code (but it can
be accessed e.g. for debugging purposes if needed).
82
This chapter shall evaluate whether the solutions proposed in the main chapters
of this document answers the questions and fulll the requirements of chapter
1.1. Moreover, the results of the SOAP toolkit evaluation from section 4.4 are
compared to the QtSoap features.
The general questions about SOAP from chapter 1.1 were:
What is the main eld of use of the SOAP protocol? How does it overlap
with similar techniques?
The main eld of use of the SOAP protocol is the eld of sophisticated distributed programming systems, which require several quality of service aspects,
for instance encryption, reliable messaging or complex message ows. Most of
these systems are not realized in the eld of publicly available Web APIs, since
a SOAP system poses a higher entry barrier onto the programmer than other
techniques. Moreover, they require more work to enable the features of a SOAP
system.
the eld of Web APIs. Compared to SOAP, REST is easy to adapt, but not as
feature-rich as SOAP. A more feature-rich solution than SOAP is for instance
Java RMI, which ties the involved systems closer together and is directed towards distributed objects. AJAX is a technique to issue remote procedure calls
for Web pages.
All in all, all the distributed programming techniques have their own area
of application, where the strengths of SOAP are its feature-richness by simultaneously providing a relatively loose coupling between the distributed systems.
What API do other SOAP toolkits oer? What are their strengths and
weaknesses?
Thus, the
SOAP class system should be designed to be easily adaptable for the code generator. As a plus, it should also be possible to easily build up a SOAP call by
hand with the class system. A more detailed evaluation of the existing SOAP
toolkits is described in chapter 4.4.
83
3. asynchronous calls.
ports asynchronous calls, this features was included in QtSoap from the
beginning.
4. pluggable data binding. This feature is not supported, since there is always
only one candidate of a Qt type to be mapped to a XML Schema type.
However, in future versions of QtSoap it should be considered to support
both user-dened type mappings as well as dierent class architectures.
5. separate XML Schema parsing entity from WSDL parsing entity.
This
an XML Schema le can be parsed against the XML Schema stylesheet
instead of the WSDL stylesheet.
6. possibility to add WS-* support and attachments.
Outlook
There are several elds were the QtSoap stack could be enhanced. The most
important area is clearly the code generator: Here, the WSDL support as well
as the XML Schema support should be improved to support a broader range of
constructs. After that, attachment support should be added, followed by the
most important WS-* standards, which are WS-Addressing and WS-Security.
Apart from that, there are a lot of other features left to be implemented (e.g.
SOAP version 1.2, WSDL version 2.0 and several other WS-* standards). In
general, a SOAP stack is never really complete, so the next features to be
implemented should always be considered carefully.
84
References
[1] Jasmin Blanchette and Mark Summereld. C++ gui programming with qt
4.
[2] Roberto Chinnici, Jean-Jacques Moreau, Arthur Ryman, and Sanjiva Weerawarana. Web services description language (wsdl) version 2.0 part 1: Core
language.
[3] Erik
jiva
http://www.w3.org/TR/wsdl20/, 2007.
Christensen,
Francisco
Weerawarana.
Web
Curbera,
services
http://www.w3.org/TR/wsdl, 2001.
Greg
Meredith,
and
San-
language
(wsdl)
1.1.
description
Primer
http://www.w3.org/TR/xmlschema-0/, 2004.
1.2.html, 2007.
http://www.ws-i.org/Proles/BasicProle-
tation/top.htm, 2000.
[8] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design
patterns: Elements of reusable object-oriented software.
Addison-Wesley,
1995.
[9] N.A.B.
Gray.
java-rmi,
Comparison
and
corba
of
web
service
services,
implementations.
http://mercury.it.swin.edu.au/ctg/AWSA04/Papers/gray.pdf, 2004.
[10] Martin
Gudgin,
Ruellan.
Noah
Soap
Mendesohn,
message
Mark
transmission
http://www.w3.org/TR/soap12-mtom/, 2005.
[11] Hugo
Haas
and
Allen
Brown.
http://www.w3.org/TR/ws-gloss/, 2004.
[12] Marc
Hadley.
What's
Nottingham,
and
optimization
mechanism.
Web
new
http://hadleynet.org/marc/whatsnew.html, 2002.
services
in
85
glossary.
soap
[13] The IEEE and The Open Group. fork - create a new process.
Herve
1.2.
The Open
shop, 2008.
[16] Microsoft.
Createprocess
function.
us/library/ms682425(VS.85).aspx, 2008.
Seshadri.
Remote
method
O'Reilly, 2007.
invocation
http://java.sun.com/developer/onlineTraining/rmi/RMI.html, 2000.
(rmi).
[20] Davanum Srinivas, Paul Fremantle, Amila Suriarachchi, and Deepal Jayas-
http://wso2.org/node/588/print, 2007.
http://doc.trolltech.com/4.4/metaobjects.html,
2008.
[22] Trolltech.
Platform notes.
platforms.html, 2008.
[23] Trolltech.
qmake
manual.html, 2008.
http://doc.trolltech.com/4.4/platform-noteshttp://doc.trolltech.com/4.4/qmake-
manual.
http://doc.trolltech.com/4.4/properties.html,
2008.
[25] Trolltech. Signals and slots.
http://doc.trolltech.com/4.4/signalsandslots.html,
2008.
[26] Robert A. van Engelen and Kyle A. Gallivan. The gsoap toolkit for web services and peer-to-peer computing networks. proceedings of the 2nd IEEE International Symposium on Cluster Computing and the Grid (CCGrid2002),
2002.
[27] W3C.
Simple
object
access
protocol
(soap)
http://www.w3.org/TR/2000/NOTE-SOAP-20000508/, 2000.
1.1.
http://www.w3.org/TR/soap/, 2007.
http://www.w3.org/TR/soap12/, 2007.
86
Pren-
Professional ajax.