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
// includes a wildcard * notation



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,
 short, unsignedShort
 integer,
 positiveInteger, negativeInteger,
 nonNegativeInteger, nonPositiveInteger,
 int, unsignedInt,
 long, unsignedLong

 // except for base64Binary
 // which has been reduced
 // to 'base64'


                  "  " 
                  "  " 

 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,
 NMTOKEN, NMTOKENS, NOTATION

                  "  " 



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[ ] ). 


The following two examples from Hadley's 'What's New in SOAP 1.2'
shows the difference between SOAP 1.1 array encoding and that of
SOAP 1.2. In both cases, the SOAP recommendation states that
the name of sub-elements is not significant.


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>
<>

Multiple Dimensional Arrays

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"
type defined in XML Schemas[4][5], which uses the base64 encoding algorithm defined
in MIME[16]. However, the line length restrictions that normally apply to base64 data in
MIME do not apply in SOAP. A "enc:base64" subtype is supplied for use with SOAP."

Example: Image with base64 encoding

<picture xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:enc="http://www.w3.org/2001/12/soap-encoding"
xsi:type="enc:base64" >
aG93IG5vDyBicm73biBjb3cNCg
</picture>
.




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
set AXIS_LIB=%AXIS_HOME%\lib
set AXISCLASSPATH=%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery.jar;
%AXIS_LIB%\commons-logging.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\saaj.jar;
%AXIS_LIB%\log4j-1.2.8.jar;%AXIS_LIB%\xml-apis.jar;%AXIS_LIB%\xercesImpl.jar

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
set AXIS_LIB=$AXIS_HOME/lib
set AXISCLASSPATH=$AXIS_LIB/axis.jar:$AXIS_LIB/commons-discovery.jar:
$AXIS_LIB/commons-logging.jar:$AXIS_LIB/jaxrpc.jar:$AXIS_LIB/saaj.jar:
$AXIS_LIB/log4j-1.2.8.jar:$AXIS_LIB/xml-apis.jar:$AXIS_LIB/xercesImpl.jar
export AXIS_HOME; export AXIS_LIB; export AXISCLASSPATH

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:

// 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);
}
}

WSDD Custom Deployment // deploying via descriptors

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.