SOAP In Practice
Peter
Komisar © Conestoga College v.1.5 / 2005
references:
"SOAP Version 1.2 Part 1: Messaging Framework,W3C
Recommendation",
http://www.w3.org/TR/2003/REC-soap12-part1-20030624/, "What's
New in SOAP 1.2",
Marc Hadley, Sun MicroSystems,
http://www.hadleynet.org/marc/whatsnew.html
'Professional
Java Web Services' , M.Hendricks et. al., Wrox Press,
'Developing
Java Web Services', R. Nagappan et. al. Wiley Press.
'Building Web
Services With Java', S.Graham et.al. Sam's Publishing.
Apache
Axis Installation Guide,
http://ws.apache.org/axis/java/install.html
Apach Axis User Guide
http://ws.apache.org/axis/java/user-guide.html
Fault Handling Scenarios
Handling VersionMismatch Faults
The SOAP 1.2 schema has defined a new 'Upgrade' header element and
a new 'SupportedEnvelope' element which is nested inside the 'Upgrade'
element. These elements have been added to provide a way to handle
cross version errors. Following is the schema representation of the
'Upgrade' element.
Schema definitions for the Upgrade Element
<xs:element name="Upgrade" type="tns:UpgradeType"/>
<xs:complexType name="UpgradeType">
<xs:sequence>
<xs:element name="SupportedEnvelope" type="tns:SupportedEnvType"
minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
The Upgrade element takes one or more 'SupportedEnvelope' elements.
The schema definition of the SupportedEnvType, used in the creation of
'SupportedEnvelope' elements is shown next.
The complexType definition for the SupportedEnvelope Element
<xs:complexType name="SupportedEnvType">
<xs:attribute name="qname" type="xs:QName" use="required"/>
</xs:complexType>
An instance of the Upgrade element is shown in the example from
'What's new in SOAP 1.2".
Example // from 'What's new in SOAP 1.2
<V:Upgrade xmlns:V="http://www.w3.org/2001/12/soap-envelope">
<envelope
qname="ns1:Envelope"
xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/"/>
<envelope
qname="ns2:Envelope"
xmlns:ns2="http://www.w3.org/2001/12/soap-envelope"/>
</V:Upgrade>
The rules as stated in the SOAP 1.2 Recommendation
for dealing with the possible
SOAP/1.1 and SOAP Version 1.2
interactions are in two parts as follows:
" 1. A SOAP/1.1 node receiving
a SOAP Version 1.2 message will according
to SOAP/1.1 generate a
version mismatch SOAP fault based on a SOAP/1.1
message
construct. That is, the envelope will have a [local name] of Envelope
and a [namespace name] of
"http://schemas.xmlsoap.org/soap/envelope/".
A SOAP 1.1 node receiving a a 1.2
message might supply a SOAP 1.1 fault
message like the
following.
Sample of a SOAP 1.1 Fault
Message
<env:Envelope
xmlns:SOAP-ENV =
"http://schemas.xmlsoap.org/soap/envelope/">
env:encodingStyle =
"http://schemas.xmlsoap.org/soap/encoding/">
<env:Body>
<env:Fault>
<faultcode> env:VersionMismatch</faultcode>
<faultstring> Cannot process other than SOAP 1.1. messages
</faultstring>
<faultactor>http://OleSoap.com/getOldPublications</faultactor>
</env:Fault>
</env:Body>
<env:Envelope>
The
second part of the rule is as follows.
"
2. A SOAP Version 1.2 node receiving a SOAP/1.1 message
either: MAY process
the message as a SOAP/1.1 message (if
supported), or
MUST generate a version mismatch SOAP fault
based on a SOAP/1.1 message
construct following SOAP/1.1
semantics using a SOAP/1.1 binding to the underlying
protocol.
The SOAP fault SHOULD include an 'Upgrade' SOAP header block as
defined in the SOAP 1.2 specification indicating support for SOAP
Version 1.2. This
allows a receiving SOAP/1.1 node to correctly
interpret the SOAP fault generated by
the SOAP Version 1.2 node."
The following W3C example shows a SOAP 1.1 message with an
Upgrade element
which is hinting to what the upgrade path should
be. It has a nested SupportedEnvelope
element which shows the
version that is supported.
W3C Example
<?xml version="1.0" ?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header>
<env:Upgrade>
<env:SupportedEnvelope qname="ns1:Envelope"
xmlns:ns1="http://www.w3.org/2003/05/soap-envelope"/>
</env:Upgrade>
</env:Header>
<env:Body>
<env:Fault>
<faultcode>env:VersionMismatch</faultcode>
<faultstring>Version Mismatch</faultstring>
</env:Fault>
</env:Body>
</env:Envelope>
The following variation shows a SOAP 1.2 Fault Message that
indicates a node
supports both versions 1.1 and 1.2 with the
order indicating a preference for SOAP
1.2
W3C SOAP 1.2 Fault Message Example // showing two versions supported
<?xml version="1.0" ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
<env:Header>
<env:Upgrade>
<env:SupportedEnvelope qname="ns1:Envelope"
xmlns:ns1="http://www.w3.org/2003/05/soap-envelope"/>
<env:SupportedEnvelope qname="ns2:Envelope"
xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/"/>
</env:Upgrade>
</env:Header>
<env:Body>
<env:Fault>
<env:Code><env:Value>env:VersionMismatch</env:Value></env:Code>
<env:Reason>
<env:Text xml:lang="en">Version Mismatch</env:Text>
</env:Reason>
</env:Fault>
</env:Body>
</env:Envelope>
Handling the 'notUnderstood'
Fault
SOAP 1.2 introduces a
new form that is used to report that a Header block
has not been
understood by a receiving node. The next example from the
W3C
Primer shows how a header element that has failed to be understood
needs to be handled.
The 'Value' element of the 'Fault'
element will contain the fault code value,
'env:MustUnderstand'.
The block element that was misunderstood is
represented by a
'env:NotUnderstood' element. The name associated with
the
'env:NotUnderstood' element is namespace qualified to the original
namespace that was associated with it when the message was
received.
The following W3C example shows a Fault
message that is specified as a
'MustUnderstand' type message
showing it was the 'transaction' block that
was not understood.
W3C MustUnderstand Fault Message Example
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope>
<env:Header>
<env:NotUnderstood qname="t:transaction"
xmlns:t="http://thirdparty.example.org/transaction"/>
</env:Header>
<env:Body>
<env:Fault>
<env:Code>
<env:Value>env:MustUnderstand</env:Value>
</env:Code>
<env:Reason>
<env:Text xml:lang="en-US">Header not understood</env:Text>
<env:Text xml:lang="fr">En-tête non compris</env:Text>
</env:Reason>
</env:Fault>
</env:Body>
</env:Envelope>
The W3C Primer supplies the following
examples. The first is a sent SOAP
message and the second an
Fault message sent in response. The returned
Fault message shows
that two headers were not understood. Neither the
'Extension1' or
'Extension2' headers were understood and this is conveyed
in the
two 'NotUnderstood' elements that have these names.
W3C Primer Message Example
<?xml version="1.0" ?>
<env:Envelope xmlns:env='http://www.w3.org/2003/05/soap-envelope'>
<env:Header>
<abc:Extension1 xmlns:abc='http://example.org/2001/06/ext'
env:mustUnderstand='true'/>
<def:Extension2 xmlns:def='http://example.com/stuff'
env:mustUnderstand='true' />
</env:Header>
<env:Body>
. . .
</env:Body>
</env:Envelope>
W3C Primer's Sample of Fault Message Response
xmlns:xml='http://www.w3.org/XML/1998/namespace'>
<env:Header>
<env:NotUnderstood qname='abc:Extension1'
xmlns:abc='http://example.org/2001/06/ext' />
<env:NotUnderstood qname='def:Extension2'
xmlns:def='http://example.com/stuff' />
</env:Header>
<env:Body>
<env:Fault>
<env:Code><env:Value>env:MustUnderstand</env:Value></env:Code>
<env:Reason>
<env:Text xml:lang='en'>One or more mandatory
SOAP header blocks not understood
</env:Text>
</env:Reason>
</env:Fault>
</env:Body>
</env:Envelope>
SOAP Encoding
Graphs
A graph is
a made up of set of nodes called 'vertices'. Links that are created
between individual nodes are called 'arcs' or 'edges'. Nodes
may represent
any of a number of object types. We might think of
houses, cities or countries.
Mathematically, graphs are
comprised of both the set of vertices that are it's
nodes and the
set of edges that may connect these nodes. The set notation
for
the vertices may look like the following.
V(g1) = { A, B, C,
D, E } //
a
finite set of non-empty vertices
E(g1) = {
(A,B), (B,C), (C,D) } //
notice arcs are represented by two vertices
Directed
and Undirected Graphs
As a real example, we can
consider the two countries, England and France, and let
them
represent two nodes of a simple graph. The
'Chunnel', the tunnel under the
English channel can be considered
an arc between the two vertices. Because the
tunnel is
bi-directional this resultant graph is an undirected graph. Following
is a
simple depiction of such a graph.
Example
of an Undirected Graph
England
------------- France
or England
<------------> France
//
England and France are each a vertex linked by an arc that is
bidirectional
On the other hand, we might
consider a TV broadcast station and a farm house
representing two
vertices of a 'directed graph', where the signal is
unidirectional.
A directed graph is also sometimes called a 'digraph'. In this
case, the direction
of the link includes an arrow in the
depiction.
Example
of an Directed Graph
TV_Station
--------------> Farmhouse
//
England and France are each a vertex linked by an arc that is
bidirectional
Note that a bidirectional
arc in a directed graph is represented showing
vertices for both
directions.
Example {
(E,G), (G,E) }
The SOAP Data
Model
The SOAP Data Model views application
defined data as "directed, edge-
labeled
graphs of nodes". "An edge that originates at a graph
node is
known as an outbound edge with respect to that
graph node. An edge
that terminates at a graph node is known as
an inbound edge with
respect to that graph node."
Practically this means if a node holds a reference to another
node this
is an 'outbound edge' with respect to the container
node. The node that
is being held in the context of another node
represents an 'inbound edge'
with respect to the node that is
being held by a container node.
Edges corresponds to field
names called labels. Nodes represent the
values that are
associated with these labels. Field identifiers or 'labels'
are
called 'accessors' as the value of the node is 'accessed' via the
field name. In the following example Edge AB is said to originate
at
Node A and terminate at Node B.
Example
Node A
------ edge AB------> Node B
A
simple type may be thought of as a Node associated with a lexical
value.
An example might be <description> element that holds
a string of characters.
Simple Type
Node
------> Lexical Value
A compound type value may be
represented as a graph node with zero of
more outbound edges.
This might be a <player> element that holds an
<age>,
<position> and <batting_average> element.
Compound
Type
Node ------> Outbound_Edges *
A 'fuller' depiction of a Compound type
Node ____ edge ___ Node
|___edge___ Node
|___edge___ Node
Here is where the SOAP model theory helps us to differentiate SOAP compound types.
SOAP supplies what is called a 'struct' data type. In SOAP data
model terms this is a
"a graph node whose outbound edges are
distinguished by their labels." In other words
this is a
standard XML compound type where a set of elements nest inside other
elements. The set of elements collectively make up a datatype,
like our player element
above. What distinguishes the SOAP
'struct' from the SOAP array type is the use of
labels to
distinguish the contained sub-elements.
The SOAP specifications states that outbound edges of a 'struct'
must be labeled
while those of an 'array' must not. In practice,
this has been interpreted by applications
to mean that names given
to elements of an array have no particular meaning.
Rules Governing the Type Name
Property
The SOAP 1.2 Adjuncts Recommendation also
states the following rule.
"If the element
information item representing the graph node has an xsi:type
attribute
information item among its attributes then the
type name property of the graph node is
the value of the xsi:type
attribute information item. Otherwise if the parent element
information item of the element information item
representing the graph node has an
enc:itemType
attribute information item among its attributes then the
type name
property of the graph node is the value of the
enc:itemType
attribute information item"
//
if an element has an xsi:type attribute, then this is the type of the
element
This means that an xsi:type
attribute used inside an element within a messaging
instance
can be typed 'inplace' using this attribute. This is an inline form
we will
see used in our struct examples.
On the other
hand, if the parent element has had it's definition expanded to be
an array type by virtue of the use of the 'itemType' and
'arraySize' attributes,
then sub-elements will get their type
from the parent's 'itemType' attribute value.
//
the scenario where typing is controlled by the the container
array
These points will be made clearer as
we look at the implementations of these
types that the SOAP 1.2
Encoding Schema defines for us.
Survey
of SOAP 1.2 Encoding Types Using the SOAP 1.2 Encoding Schema
The
SOAP 1.2 Encoding types are described in detail within the
corresponding
encoding schema conveniently found at the following
web site.
SOAP 1.2 Encoding Schema URI
http://www.w3.org/2003/05/soap-encoding
The first element that is defined in the schema is an 'attributeGroup' element
called 'commonAttributes'. It defines the attributes that are globally available
to elements defined in the encoding schema. Following is an abbreviated form
of the attributeGroup definition.
The 'commonAttributes' element of the SOAP 1.2
Encoding Schema
<xs:attribute
name="id" type="xs:ID"/>
<xs:attribute
name="ref" type="xs:IDREF"/>
<!--
. . . . -->
<xs:attribute
name="nodeType" type="tns:nodeType"/>
<xs:simpleType
name="nodeType">
<xs:restriction
base="xs:token">
<xs:enumeration value="simple"/>
<xs:enumeration value="struct"/>
<xs:enumeration
value="array"/>
</xs:restriction>
</xs:simpleType>
<!--
some parts of the definition, such as the following definitions for
'arraySize' and 'itemType' have been
left out or moved -->
<xs:attribute
ref="tns:arraySize"/>
<xs:attribute
ref="tns:itemType"/>
We can create the
following table of global values from this list.
Global
SOAP Encoding Attribute Values
Attribute Name |
Type |
id |
xs:ID |
ref |
xs:IDREF |
nodeType |
simple, struct, array |
itemType |
xs:QName |
arraySize |
xs:nonNegativeInteger |
The 'id' and 'ref' attributes are typed to built-in schema
data-types. The 'nodeType'
attribute is defined as a enumeration
that can be one of 'simple', 'struct' or 'array'.
The itemType
and arraySize attributes are used in the SOAP 1.2 formula for
specifying arrays.
SOAP
Simple Element Types
In the encoding schema the
XML schema simple type definitions are wrapped
in soap-encoding
element declarations using their schema type names. They
are also
extended so they can contain any of the global attribute group. This
has
been done for all the simple built-in types defined in XML
Schema. Following is
an example from the SOAP encoding schema
that shows how this is done.
Example //
schema element definition extracted from SOAP encoding schema
<!--
Element declarations corresponding to each of the simple
types in the XML Schemas Specification.
-->
<xs:element
name="duration" type="tns:duration"/>
-
<xs:complexType name="duration">
-
<xs:simpleContent>
-
<xs:extension
base="xs:duration">
<xs:attributeGroup
ref="tns:commonAttributes"/>
//
references the global attributes into the
element
</xs:extension>
</xs:simpleContent>
</xs:complexType>
This
notation allows us to use elements that have schema types
'in-place'
in our SOAP messages for each of the simple types
defined in XML
Schema.
Simple XML
Schema Types and Associated SOAP Element Wrappers
Type Category |
Schema Simple Types |
SOAP Encoding Element Name |
String types |
string, normalizedString, token |
// same as schema names |
Integer Types |
byte, unsignedByte, |
//
except for base64Binary |
Binary Types |
base64Binary, hexBinary |
'base64' " " |
Decimal |
decimal |
" " |
Floating Point |
float, double |
" " |
Boolean |
boolean, // true, false, 1, 0 |
" " |
Time & Date |
time, dateTime, duration, date |
" " |
Calendar |
gMonth, gYear, gYearMonth, gDay, gMonthDay |
" " |
Identifiers |
Name, QName, NCName, anyURI |
" " |
Language |
language |
" " |
XML 1.0 Attribute Types |
ID, IDREF, ENTITY, ENTITIES, |
" " |
Using Simple SOAP Types in
Messages
The wrapped versions of the schema types
are easy to use
directly inside a SOAP message.
Example
<decimal > 1.2 </decimal>
There
is another form where the connection between SOAP
elements and
their XML Schema types is more explicit.
Polymorphic
Accessor
This form creates a named and typed
element that has an
initial value specified.
<rate
type=xs:double > 11.4 </rate>
Multi-Reference
Simple Types
This is the ref form we saw quite a
bit in schema examples.
Here a ref attribute is assigned an id
attributes value creating
a second accessor for the elements
value
Example //
from SOAP Version 1.2 Part 2: Adjuncts, Editor's copy
<greetingid="String-0">Hello</greeting>
<salutationref="String-0"/>
The struct Type
In SOAP a struct type is an instance complex type elements that
are created in XML Schema using the complexType element. In
this
form sub-elements are nested inside a container element.
Frequently we see the struct type represented by a schema
definition
followed by an instance representation that would be
carried in the
message. Where no namespace targeting is present
one has to
suppose that XML Schema validation will be exercised
by the SOAP
nodes somewhere behind the scenes within the SOAP
application.
In the following example a connection between the schema
element
and the instance is more overt. The target namespace is
referenced
from inside the instance. In this case schema
validation of the SOAP
messaging may proceed using standard XML
parsing techniques
from inside a receiving SOAP Node.
Schema Example from the Apache SOAP User Guide
<schema targetNamespace="http://commerce.com/PO">
<complexType name="POType">
<sequence>
<element name="item" type="xsd:string"/>
<element name="quantity" type="xsd:int"/>
<element name="description" type="xsd:string"/>
</sequence>
</complexType>
<element name="PurchaseOrder" type="POType"/>
</schema>
The instance that is associated with the schema definition
is shown next.
A 'struct' Type in an Example from the Apache
SOAP User Guide
<soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<soap:Body>
<myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO">
<item>SK001</item>
<quantity>1</quantity>
<description>Sushi Knife</description>
</myNS:PurchaseOrder>
</soap:Body>
</soap:Envelope>
The next example shows an 'inline' style
of the 'struct' datatype
which
parallels form used in SOAP encoding elements based on
built-in
schema types. In this form the xsi:type attribute
available to the XML
instance document namespace is used to show
the type of each sub-
element. In this form, the application
doesn't need to look for an
associated schema, because the schema
typing accompanies the
message.
//
How messages are encoded serves as a criteria for different
//
sorts of messaging types as we will see later with Apache
Example
of an 'inline' Form of a struct Type
<CustomerAcct
encodingStyle="http://www.w3.org/2002/06/soap-encoding">
<Name> Barry Season
</Name>// built-in type
<AccountNo
xsi:type =xs:integer >12345 </AccountNo>
// inline form
<AccountType
xsi:type ="xs:string" > Cash </AccountType>
</CustomerAcct>
SOAP Array Types
Arrays
can be built to create indexed lists of the basic simple
types or
reference types. SOAP also permits the creation of
multi-dimensional
arrays and arrays of arrays ( via references).
The array
notation has changed from SOAP 1.1 to SOAP 1.2.
The newer
definition of an array requires that an array type be
supplied as
well as an array size.
Instead of a an array expression
notation used in SOAP 1.1 where
an array form like "xs:int[99]"
is assigned to an enc:arrayType
attribute, a more orthodox syntax
has been adapted where an
schema type is assigned to an
'enc:itemType' attribute and
an non-negative integer is assigned
to an 'enc:arraySize' attribute.
The non-negative integer type is
specifically XML Schema's
built-in "xs:nonNegativeInteger"
type.
The arraySize attribute defaults to "*," a wildcard value
that defines
the array as unbounded. ( This is the value when a value is not added.
i.e. float[ ] ).
Example
of a SOAP 1.1 Array // from
Hadley's 'What's New in SOAP 1.2
<numbers enc:arrayType="xs:int[2]">
<number>3</number>
<number>4</number>
</numbers>
Example of a SOAP 1.2 Array //
from Hadley's 'What's New in SOAP 1.2
<numbers enc:itemType="xs:int" enc:arraySize="2">
<number>3</number>
<number>4</number>
</numbers>
Partially Transmitted & Sparse Arrays are Dropped in SOAP 1.2
SOAP 1.1 partially transmitted and sparse arrays have been dropped
in
SOAP
1.2. A partially transmitted array in SOAP 1.1 is created
using an 'enc:offset'
attribute. With the offset value and the
length value an array could be partially
transmitted. In the
following example only the second element with a value of
4 would
be sent.
SOAP 1.1 Partially Transmitted
Array Example
<numbers enc:arrayType="xs:int[2]" enc:offset="[1]" >
<number>4</number>
</numbers>
// the array value after the offset is sent, counting
// from an offset of 0 .offset 0 is the default
Sparse arrays are defined in SOAP 1.1 using the enc:position
attribute when
allowed values at specific positions in an array
to be transmitted.
SOAP 1.1 Sparse Array
Example
<numbers enc:arrayType="xs:int[2]" >
<number enc:position="[0]">3</number>
</numbers>
In addition to elements declared for the simple types defined in the
"XML
Schema Part2: Datatypes" specification, SOAP also
includes a declaration
for the 'Array' element. The
following sample from the W3 site shows this
element in action.
It is also useful in creating multi-reference arrays.
Example:
Array containing other arrays
//
from SOAP Version 1.2 Part 2: Adjuncts, an Editor's copy
<enc:Array xmlns:enc="http://www.w3.org/2001/12/soap-encoding"<>
xmlns:xs="http://www.w3.org/2001/XMLSchema"
enc:itemType="xs:int" enc:arraySize="2">
<enc:int>3</enc:int>
<enc:int>4</enc:int>
</enc:Array>
Multi-dimensional
arrays can be created by assigning the arraySize
attribute two
space separated integers. The " * " symbol may be
used to specify the first (but only the first) dimension of a
multi-
dimensional array. The following example creates two
arrays, each
which will have three elements.
SOAP
1.2 Multi-dimensional Array Example
<anArray
enc:itemType="xs:string" enc:arraySize=" 2 3
">
<workday> Monday </workday>
<workday>
Tuesday </workday>
<workday> Wednesday </workday>
<workday> Thursday </workday>
<workday>
Friday </workday>
<workday> Saturday </workday>
</anArray>
This creates two arrays which
could be described in Java as follows.
An
equivalent array of arrays written in Java
String
[][] workday = {
{ "Monday", "Tuesday", "Wednesday"
}
{ "Thursday", "Friday", "Saturday"
}
}
// SOAP 1.1 had many
compound forms, xs:int[3][3] , xs:int [ ][5], xs:string{2,3}
//
Interoperability problems resulted in these forms being dropped in
SOAP 1.2
Multi-Reference
Values
The following SOAP 1.2 sample
shows how the 'ref' and 'id' attributes can
be
used to constitute arrays of arrays. The first array takes
items that
reference other array types.
Example:
Array containing other arrays
//
from SOAP Version 1.2 Part 2: Adjuncts, an Editor's copy
<enc:Array xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:enc="http://www.w3.org/2001/12/soap-encoding"
enc:itemType="enc:Array" enc:arraySize="2">
<item ref="array-1"/>
<item ref="array-2"/>
</enc:Array>
<enc:Array xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:enc="http://www.w3.org/2001/12/soap-encoding"
id="array-1"
enc:itemType="xs:string" enc:arraySize="3">
<item>r1c1</item>
<item>r1c2</item>
<item>r1c3</item>
</enc:Array>
<enc:Array xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:enc="http://www.w3.org/2001/12/soap-encoding"
id="array-2"
enc:itemType="xs:string" enc:arraySize="2">
<item>r2c1</item>
<item>r2c2</item>
</enc:Array>
The following is included for reference and shows an example that makes
use of the base64 element. The commentary is quoted from the specification
and is self-explanatory.
3.3.4 Array of Bytes // from SOAP Version 1.2 Part 2: Adjuncts, an Editor's
copy
"The recommended representation of an opaque
array of bytes is the "xs:base6Binary" Example: Image with base64 encoding <picture xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
This completes a reasonably thorough look at SOAP's built-in
encoding for datatypes.
We can now put some of them into action
and do some preliminary SOAP messaging
using the Apache Axis SOAP
engine.
Apache Axis
// knowledge of
Apache is considered practical and won't be on the final exam.
//
The Java that used in Apache and that is covered in this note is also
used
// in APIs we will cover later so also will not be on
final.
Apache
Axis Installation
We are now at a good point to do
some SOAP messaging. Before we do that
we need a SOAP engine to
support the protocol. Apache provides 'Axis', an
Open Source SOAP
engine to process SOAP messages. It comes in a standard
Java
version but is also being developed for C++. The standard Java
version
is named Axis while the C++ version appends 'C++' to the
name.
Axis runs over top of Tomcat, which is Apache's Java
enabled web server.
Tomcat is an Apache web server that also
provides support for Servlets and
JSPs.
These are needed in the background for Axis to work. The final
dependency
is that Tomcat requires Java
to be installed. (As you download you may wish to
collect the
documentation for each of the following as you go.)
1)
Download JDK 1.5 and install if you haven't already done so.
2)
Add Servlet and XML APIs, usually by downloading and installing
the Java Web Services Package.
2) Download Apache Tomcat.
(Jakarta) and install.
3) Download Axis and install.
4)
Download extra packages that Axis says you need and install
them.
Test by running exercises in Apache Installation and
User Guide.
LINKS
These
links are provided to makes things convenient
Java
2 Platform Standard Edition 5.0 //
get it with or without
NetBeans
http://java.sun.com/j2se/1.5.0/download.jsp
A
recent stable version of Tomcat
http://apache.sunsite.ualberta.ca/jakarta/tomcat-5/v5.5.7/
Java
Web Services Developer Pack (JWSDP)
http://java.sun.com/webservices/downloads/webservicespack.html
//
in the installation of JWSDP it asks for an installation of a
// web server such as Tomcat
A
recent version of
Axis
http://www.apache.org/dyn/closer.cgi/ws/axis/1_2RC2/
At
the lab, Tomcat is already installed and just needs to be
started.
You can install Axis and test the installation. The only
problem is it
won't be here next week. Axis may though fit on your
G drives.
On your home or base station you should do a
permanent installation.
You can take advantage of the CD Burners
and fast downloads at
the college if your home connection is not
high speed.
Path and
Classpath
Typically you will need to add paths to
your configuration files.
Today the form that is popularly taken
is to create a 'XXX_HOME'
variable that is assigned the directory
in which each major application
rests in. Following is a
Windows example and a Unix/Linux Example.
Windows
Path Example
SET
JAVA_HOME=C:\jdk1.5.0
PATH=C:\WINDOWS;C:\WINDOWS\COMMAND;C:\%JAVA_HOME%\BIN;
Unix/Linux Path
statements
export
JWSDP_HOME=/usr/local/jwsdp-1.5
export
CATALINA_HOME=/usr/local/jakarta-tomcat-5.0.19
export
CATALINA_BASE=/usr/local/jakarta-tomcat-5.0.19
export
JAVA_HOME=/usr/local/jdk1.5.0
export
J2EE_HOME=/usr/local/j2sdkee1.3.1
export
MySQL_HOME=/usr/local/mysql-standard-4.0.16-pc-linux-i686
export
PATH=$PATH:$JAVA_HOME/bin:$J2EE_HOME/bin:$MySQL_HOME/bin:$JWSDP_HOME/jaxb/bin
export
CLASSPATH=/usr/local/j2sdkee1.3.1/lib/j2ee.jar:.
The
Axis Installation guide states "java must be able to find
axis.jar,
commons-discovery.jar, commons-logging.jar, jaxrpc.jar,
saaj.jar,
log4j-1.2.8.jar (or whatever is appropriate for your
chosen logging
implementation), and the XML parser jar file or
files (e.g., xerces.jar)."
The Xerces jar can be found in
the JWSDP download. Perhaps an
easy approach to take would be to
put it into the Axis lib directory
and then follow the recipe
supplied below in the Apache Axis
installation guide.
Apache Axis Installation Guides Directions for Setting Axis Paths For this document we assume that you have installed Axis in C:\axis. To store this information permanently in WinNT/2000/XP you will need to right click on "My Computer" and select "Properties". Click the "Advanced" tab and create the new environmental variables. It is often better to use WordPad to create the variable string and then paste it into the appropriate text field. set AXIS_HOME=c:\axis Unix users have to do something similar. Below we have installed AXIS into /usr/axis and are using the bash shell. See your shell's documentation for differences. To make variables permeate you will need to add them to your shell's startup (dot) files. Again, see your shell's documentation. set AXIS_HOME=/usr/axis To use Axis client code, you can select AXISCLASSPATH when invoking Java by entering java -cp %AXISCLASSPATH% ... or java -cp "$AXISCLASSPATH" ... depending on the platform. You may omit the quotes if your CLASSPATH doesn't have spaces in it. Also, it is probably a good time to add the AXISCLASSPATH variable to your CLASSPATH variable. This will enable you to not include the AXISCLASSPATH variable when launching the examples in this guide. This document assumes that you have NOT done this. |
Both the installation guide and the user guide have a
section on testing Axis
to confirm everything is working
correctly. From this point we continue
overviewing procedures
found in the User Guide.
Using Axis
Overview
We
can turn to the User Guide to supply a description of what Axis
is.
"Axis is essentially a SOAP engine -- a
framework for constructing SOAP processors
such as clients,
servers, gateways, etc. . . .But Axis isn't just a SOAP engine
-- it
also includes:
a simple stand-alone server,
a server which plugs into servlet engines such as Tomcat,
extensive support for the Web Service Description Language (WSDL),
emitter tooling that generates Java classes from WSDL.
some sample programs, and
a tool for monitoring TCP/IP packets. "
// historical note: Axis is
a third generation version of a IBM project that started as
"SOAP4J"
Axis
Is Java Based //
and more recently C++
That Apache is Java
centric is evident on approaching the 'Basics- Getting
Started
Section. The example is as follows. The following code is
a Java SOAP client. It is
written in Java that is an Axis
implementation of JAX-RPC, a Java API we look at
later in the
course. There are axis package imports. Everything in the client is
executed inside a main( ) method. A Service object returns a Call
object that is
used to set a target endpoint where the service is
to found and to set an operation
name. The invoke( ) method
actually calls the service at the target endpoint and
the
response is captured in a String which is printed to console.
Getting Started Example From Apache's
Axis User Guide
1 import org.apache.axis.client.Call;
2 import org.apache.axis.client.Service;
3 import javax.xml.namespace.QName;
4
5 public class TestClient {
6 public static void main(String [] args) {
7 try {
8 String endpoint =
9 "http://ws.apache.org:5049/axis/services/echo";
10
11 Service service = new Service();
12 Call call = (Call) service.createCall();
13
14 call.setTargetEndpointAddress( new java.net.URL(endpoint) );
15 call.setOperationName(new QName("http://soapinterop.org/", echoString"));
16
17 String ret = (String) call.invoke( new Object[] { "Hello!" } );
18
19 System.out.println("Sent 'Hello!', got '" + ret + "'");
20 } catch (Exception e) {
21 System.err.println(e.toString());
22 }
23 }
24 }
Output
% java samples.userguide.example1.TestClient
Sent 'Hello!', got 'Hello!'
%
The User Guide supplies the request that goes over the
wire.
Client's XML Wire Output
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:echoString xmlns:ns1="http://soapinterop.org/">
<arg0 xsi:type="xsd:string">Hello!</arg0>
</ns1:echoString>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
// Axis automatically names
the
XML-encoded arguments in the SOAP message "arg0", "arg1",
etc.
The User Guide
also shows how the parameter names can be set explicitly
by using
addParameter( ) calls on the Call object. The example shows
how
parameter names, schema type and parameter type can be
controlled.
Apache Axis Example
call.addParameter("testParam",
org.apache.axis.Constants.XSD_STRING,
javax.xml.rpc.ParameterMode.IN);
call.setReturnType(org.apache.axis.Constants.XSD_STRING);
// assignes the name
'testParam' to the first parameter on the invoke call, defines
type
// and whethre an input, output or inout parameter
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:echoString xmlns:ns1="http://soapinterop.org/">
<testParam xsi:type="xsd:string">Hello!</testParam>
</ns1:echoString>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Following is what a typical response might look like to the echoString method:
Apache Axis Sample Response Output //
self describing
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/">
<result xsi:type="xsd:string">Hello!</result>
</ns1:echoStringResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Notice that the response parameter is typed, 'xs:string'. The User Guide
states that many toolkits return 'self-describing' messages while others
do not. Consider the following example that shows this variation.
Apache Axis Sample Response Output
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/">
<result>Hello, I'm a string!</result>
</ns1:echoStringResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
To control the return type the client can use the setReturnType
on the invocation
as an indicator that the client should act as if
the element has an xsi:attribute set
to the built-in SOAP String
type.
Apache Example
// setting the return value
The call.setReturnType( org.apache.axis.Constants.XSD_STRING );
JWS Files // Java Web Services Files
<>Java enthusiasts are in for a treat with JWS files. A JWS
file is just
a Java source code file describes a set of methods.
When the Java
file is save with a .jws extension and placed in a
directory under
'webapps' under the 'axis' home directory, it is
instantly converted
into a web service!
This is
reminiscent of how JSPs or Java Server
Pages work. Converting
the source file into a web service is taken
care off by the Axis SOAP
engine.
The Apache Axis User
Guide supplies the following Java class
and the associated client.
If only the client was as simple!
Apache Sample Java Source Code
public class Calculator {
public int add(int i1, int i2) {
return i1 + i2;
}
public int subtract(int i1, int i2) {
return i1 - i2;
}
}
// copy Calculator.java <your-webapp-root>/axis/Calculator.jws
The client is more complicated than our earlier example
primarily because
it takes control of receiving argument via the
command line. It also explicitly
controls setting of parameters
and setting the return type. Otherwise it
follows the same
formula we saw earlier.
Apache Client to Call Above JWS defined
Service
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package samples.userguide.example2 ;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.utils.Options;
import javax.xml.rpc.ParameterMode;
public class CalcClient
{
public static void main(String [] args) throws Exception {
Options options = new Options(args);
String endpoint = "http://localhost:" + options.getPort() +
"/axis/Calculator.jws";
args = options.getRemainingArgs();
if (args == null || args.length != 3) {
System.err.println("Usage: CalcClient <add|subtract> arg1 arg2");
return;
}
String method = args[0];
if (!(method.equals("add") || method.equals("subtract"))) {
System.err.println("Usage: CalcClient <add|subtract> arg1 arg2");
return;
}
Integer i1 = new Integer(args[1]);
Integer i2 = new Integer(args[2]);
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpoint) );
call.setOperationName( method );
call.addParameter( "op1", XMLType.XSD_INT, ParameterMode.IN );
call.addParameter( "op2", XMLType.XSD_INT, ParameterMode.IN );
call.setReturnType( XMLType.XSD_INT );
Integer ret = (Integer) call.invoke( new Object [] { i1, i2 });
System.out.println("Got result : " + ret);
}
}
Deploying web services as JWS files is
convenient but is limited in how the service
can be configured. It
also requires Java source code which may not be available.
Axis supplies the WSDD or Web Service Deployment Descriptor to
provide flexible
deployment of web services. The following is an
example of such a service.
Apache Axis WSDD Sample
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="MyService" provider="java:RPC">
<parameter name="className" value="samples.userguide.example3.MyService"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment>
The deployment element signals that this is a WSDD deployment and defines
the 'java' namespace. It defines the service, the provider, ( 'java:RPC' which
is built into axis) and indicates a Java RPC service. The class name and the
allowed methods are specified as parameters.
We will look more at Axis details after we cover WSDL.
Exercise // reference: the Axis Installation Guide and first 6 pages of the User Guide
The main objective of the exercise
is to get Tomcat running with the Axis SOAP
engine executing.
Once Axis is installed, it needs to be tested. First start Tomcat
by
going to the Tomcat Home Directory and then to the bin directory.
Example cd
jakarta-tomcat-5.0.19/bin
Depending on whether you are using
Windows or Linux you will need to
start Tomcat.
Example
sh ./startup.sh //
Unix / Linux
Example
startup // Windows .bat
file
1) Do Step 4 in the Axis Installation
Guide. ( The section is paraphrased here. )
a) Navigate to the start page of the webapp, usually
http://127.0.0.1:8080/axis/
// port may differ.
You should now see an Apache-Axis start page. If you
do not, then the
webapp is not actually
installed, or the appserver is not running.
b) Follow the 'happy axis' link that verifies that needed and
optional libraries
are present. The URL is something like
http://localhost:8080/axis/happyaxis.jsp
<>If any of the needed libraries are missing, Axis will not
work. You must find
all the needed libraries
//
The User guide states that if you see nothing but an internal server
error and an
// exception trace, then you probably have multiple
XML parsers on the CLASSPATH
// (or AXISCLASSPATH), and this is
causing version confusion. Eliminate the extra
// parsers,
restart the app server and try again.
2)
Add the Java Source code for the Calculator service to a directory
under your
Axis installation. Compile and run the
associated client code and test the service.