Chapter 2. SOAP 1.2 Web Service Standards

List and describe the encoding types used in a SOAP message.

[Note]

The SOAP encoding style is based on a simple type system that is a generalization of the common features found in type systems in programming languages, databases and semi-structured data. A type either is a simple (scalar) type or is a compound type constructed as a composite of several parts, each with a type. This is described in more detail below. This section defines rules for serialization of a graph of typed objects. It operates on two levels. First, given a schema in any notation consistent with the type system described, a schema for an XML grammar may be constructed. Second, given a type-system schema and a particular graph of values conforming to that schema, an XML instance may be constructed. In reverse, given an XML instance produced in accordance with these rules, and given also the original schema, a copy of the original value graph may be constructed.

There are following SOAP encoding types:

  • Simple Types:

    • Strings

    • Enumerations

    • Array of Bytes

  • Compound Types:

    • Arrays

    • Structures

Simple Types

For simple types, SOAP adopts all the types found in the section "Built-in datatypes" of the "XML Schema Part 2: Datatypes" Specification, both the value and lexical spaces. Examples include: boolean (true, false, 0 or 1), byte, short, int, long, float, double, string (java.lang.String), decimal (java.math.BigDecimal), date (java.util.GregorianCalendar), dateTime (java.util.Date), SOAP-ENC:base64 (byte []).

The following examples are a SOAP representation of these primitive data types:

					
<element name="age" type="int"/>
<element name="height" type="float"/>
<element name="displacement" type="negativeInteger"/>
<element name="color">
  <simpleType base="xsd:string">
    <enumeration value="Green"/>
    <enumeration value="Blue"/>
  </simpleType>
</element>

<age>45</age>
<height>5.9</height>
<displacement>-450</displacement>
<color>Blue</color> 

					

Strings

The datatype "string" is defined in "XML Schema Part 2: Datatypes" Specification. Note that this is not identical to the type called "string" in many database or programming languages, and in particular may forbid some characters those languages would permit. (Those values must be represented by using some datatype other than xsd:string.) A string MAY be encoded as a single-reference or a multi-reference value. The containing element of the string value MAY have an "id" attribute. Additional accessor elements MAY then have matching "href" attributes. For example, two accessors to the same string could appear, as follows:


<greeting id="String-0">Hello</greeting>
<salutation href="#String-0"/>

					
However, if the fact that both accessors reference the same instance of the string (or subtype of string) is immaterial, they may be encoded as two single-reference values as follows:

<greeting>Hello</greeting>
<salutation>Hello</salutation>

					
Schema fragments for these examples could appear similar to the following:

<element name="greeting" type="SOAP-ENC:string"/>
<element name="salutation" type="SOAP-ENC:string"/>

					
(In this example, the type SOAP-ENC:string is used as the element's type as a convenient way to declare an element whose datatype is "xsd:string" and which also allows an "id" and "href" attribute. See the SOAP Encoding schema for the exact definition. Schemas MAY use these declarations from the SOAP Encoding schema but are not required to.)

Enumerations

Enumeration as a concept indicates a set of distinct names. A specific enumeration is a specific list of distinct values appropriate to the base type. For example the set of color names ("Green", "Blue", "Brown") could be defined as an enumeration based on the string built-in type. The values ("1", "3", "5") are a possible enumeration based on integer, and so on. "XML Schema Part 2: Datatypes" supports enumerations for all of the simple types except for boolean. The language of "XML Schema Part 1: Structures" Specification can be used to define enumeration types. If a schema is generated from another notation in which no specific base type is applicable, use "string". In the following schema example "EyeColor" is defined as a string with the possible values of "Green", "Blue", or "Brown" enumerated, and instance data is shown accordingly:


<element name="EyeColor" type="tns:EyeColor"/>

<simpleType name="EyeColor" base="xsd:string">
   <enumeration value="Green"/>
   <enumeration value="Blue"/>
   <enumeration value="Brown"/>
</simpleType>

<Person>
   <Name>Mikalai Zaikin</Name>
   <Age>34</Age>
   <EyeColor>Brown</EyeColor>
</Person>
									
					

Array of Bytes

An array of bytes MAY be encoded as a single-reference or a multi-reference value. The rules for an array of bytes are similar to those for a string. In particular, the containing element of the array of bytes value MAY have an "id" attribute. Additional accessor elements MAY then have matching "href" attributes. The recommended representation of an opaque array of bytes is the 'base64' encoding defined in XML Schemas, which uses the base64 encoding algorithm. However, the line length restrictions that normally apply to base64 data in MIME do not apply in SOAP. A "SOAP-ENC:base64" subtype is supplied for use with SOAP:


<picture xsi:type="SOAP-ENC:base64">
  aG93IG5vDyBicm73biBjb3cNCg==
</picture>
									
					

Polymorphic Accessor

Many languages allow accessors that can polymorphically access values of several types, each type being available at run time. A polymorphic accessor instance MUST contain an "xsi:type" attribute that describes the type of the actual value. For example, a polymorphic accessor named "cost" with a value of type "xsd:float" would be encoded as follows:


<cost xsi:type="xsd:float">29.95</cost>
									
					
as contrasted with a cost accessor whose value's type is invariant, as follows:

<cost>29.95</cost>
									
					

Compound types

A "struct" is a compound value in which accessor name is the only distinction among member values, and no accessor has the same name as any other.

An "array" is a compound value in which ordinal position serves as the only distinction among member values.

Structures

The members of a Compound Value are encoded as accessor elements. When accessors are distinguished by their name (as for example in a struct), the accessor name is used as the element name. Accessors whose names are local to their containing types have unqualified element names; all others have qualified names. The following is an example of a struct of type "book":


<book>
  <author>Mikalai Zaikin</author>
  <title>SCDJWS 5.0 Study Guide</title>
  <intro>This is a certification guide</intro>
</book>

					
And this is a schema fragment describing the above structure:

<xsd:element name="book">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="author" type="xsd:string" />
      <xsd:element name="title" type="xsd:string" />
      <xsd:element name="intro" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>
									
					

Arrays (SOAP 1.2)

Array encodings have been revised and simplified in the latest SOAP 1.2 specification.

ArrayType elements are derived from a generic nodeType element.

Now arrays have two attributes:

  • itemType is the the type of the array (String, int, XML complex type).

  • arraySize - The array's dimensions are represented by each item in the list of sizes (unspecified size in case of the asterisk). The number of items in the list represents the number of dimensions in the array. The asterisk, if present, MUST only appear in the first position in the list.

    The default value of the arraySize attribute information item is "*", that is by default arrays are considered to have a single dimension of unspecified size.


<xs:attribute name="arraySize" 	type="tns:arraySize" />

<xs:attribute name="itemType" type="xs:QName" />
 
<xs:attributeGroup name="arrayAttributes">
  <xs:attribute ref="tns:arraySize" /> 
  <xs:attribute ref="tns:itemType" /> 
</xs:attributeGroup>

					

SOAP 1.1 array:


<numbers enc:arrayType="xs:int[2]">
  <number>3</number>
  <number>4</number> 
</numbers>
					
					

SOAP 1.2 array:


<numbers enc:itemType="xs:int" enc:arraySize="2">
  <number>3</number>
  <number>4</number> 
</numbers>
					
					

Arrays (SOAP 1.1)

In SOAP 1.1 arrays are defined as having a type of "SOAP-ENC:Array" or a type derived there from. Arrays are represented as element values, with no specific constraint on the name of the containing element (just as values generally do not constrain the name of their containing element). Arrays can contain elements which themselves can be of any type, including nested arrays. New types formed by restrictions of SOAP-ENC:Array can also be created to represent, for example, arrays limited to integers or arrays of some user-defined enumeration. The representation of the value of an array is an ordered sequence of elements constituting the items of the array. Within an array value, element names are not significant for distinguishing accessors. Elements may have any name. In practice, elements will frequently be named so that their declaration in a schema suggests or determines their type. As with compound types generally, if the value of an item in the array is a single-reference value, the item contains its value. Otherwise, the item references its value via an "href" attribute. The following example is a schema fragment and an array containing integer array members:


<element name="myFavoriteNumbers" type="SOAP-ENC:Array"/>

<myFavoriteNumbers SOAP-ENC:arrayType="xsd:int[3]">
   <number>1</number> 
   <number>2</number> 
   <number>3</number> 
</myFavoriteNumbers>
									
					
In that example, the array "myFavoriteNumbers" contains several members each of which is a value of type xsd:int. This can be determined by inspection of the SOAP-ENC:arrayType attribute. Note that the SOAP-ENC:Array type allows unqualified element names without restriction. These convey no type information, so when used they must either have an xsi:type attribute or the containing element must have a SOAP-ENC:arrayType attribute. Naturally, types derived from SOAP-ENC:Array may declare local elements, with type information. As previously noted, the SOAP-ENC schema contains declarations of elements with names corresponding to each simple type in the "XML Schema Part 2: Datatypes" Specification. It also contains a declaration for "Array". Using these, we might write:

<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:int[3]">
   <SOAP-ENC:int>1</SOAP-ENC:int>
   <SOAP-ENC:int>2</SOAP-ENC:int>
   <SOAP-ENC:int>3</SOAP-ENC:int>
</SOAP-ENC:Array>
									
					
Arrays can contain instances of any subtype of the specified arrayType. That is, the members may be of any type that is substitutable for the type specified in the arrayType attribute, according to whatever substitutability rules are expressed in the schema. So, for example, an array of integers can contain any type derived from integer (for example "int" or any user-defined derivation of integer). Similarly, an array of "address" might contain a restricted or extended type such as "internationalAddress". Because the supplied SOAP-ENC:Array type admits members of any type, arbitrary mixtures of types can be contained unless specifically limited by use of the arrayType attribute.

Array values may be structs or other compound values. For example an array of "my:order" structs :


<SOAP-ENC:Array SOAP-ENC:arrayType="my:order[2]">
   <order>
       <product>Melon</product>
       <price>0.99</price>
   </order>
   <order>
       <product>Apple</product>
       <price>1.49</price>
   </order>
</SOAP-ENC:Array>
									
					
Arrays may have other arrays as member values. The following is an example of an array of two arrays, each of which is an array of strings:

<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[][2]">
  <item href="#array-1"/>
  <item href="#array-2"/>
</SOAP-ENC:Array>

<SOAP-ENC:Array id="array-1" SOAP-ENC:arrayType="xsd:string[3]">
  <item>row1column1</item>
  <item>row1column2</item>
  <item>row1column3</item>
</SOAP-ENC:Array>

<SOAP-ENC:Array id="array-2" SOAP-ENC:arrayType="xsd:string[2]">
  <item>row2column1</item>
  <item>row2column2</item>
</SOAP-ENC:Array>
									
					
Arrays may be multi-dimensional. In this case, more than one size will appear within the asize part of the arrayType attribute:


<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[2,3]">
  <item>row1column1</item> 
  <item>row1column2</item> 
  <item>row1column3</item> 
  <item>row2column1</item> 
  <item>row2ccolumn2</item> 
  <item>row2column3</item> 
</SOAP-ENC:Array>
									
					

NOTE: According to WS-I BP 1.1 you MUST NOT use soapenc:Array type for array declarations or soapenc:arrayType attribute in the type declarations (for both SOAP envelope and WSDL):

In a DESCRIPTION, declarations MUST NOT extend or restrict the soapenc:Array type.

In a DESCRIPTION, declarations MUST NOT use wsdl:arrayType attribute in the type declaration.

In a DESCRIPTION, elements SHOULD NOT be named using the convention ArrayOfXXX.

An ENVELOPE MUST NOT include the soapenc:arrayType attribute. 					
					

Mapping between XML Schema types and SOAP Java types

When a message part is defined using one of the XML Schema primitive types, the generated parameter's type is mapped to a corresponding Java native type. The same pattern is used when mapping elements that are defined within the scope of a complex type. The resulting field is of the corresponding Java native type.

The table below lists the mapping between XML Schema primitive types and Java native types:

Table 2.1. XML Schema Primitive Type to Java Native Type Mapping

XML Schema typeSOAP Java type
xsd:stringjava.lang.String
xsd:integerjava.math.BigInteger
xsd:intint
xsd:longlong
xsd:shortshort
xsd:decimaljava.math.BigDecimal
xsd:floatfloat
xsd:doubledouble
xsd:booleanboolean
xsd:bytebyte
xsd:QNameQName
xsd:dateTimeXMLGregorianCalendar
xsd:base64Binarybyte[]
xsd:hexBinarybyte[]
xsd:unsignedIntlong
xsd:unsignedShortint
xsd:unsignedByteshort
xsd:timeXMLGregorianCalendar
xsd:dateXMLGregorianCalendar
xsd:gXMLGregorianCalendar

Wrapper Classes

Mapping XML Schema primitive types to Java primitive types does not work for all possible XML Schema constructs. Several cases require that an XML Schema primitive type is mapped to the Java primitive type's corresponding wrapper type. These cases include:

  1. An element element with its nillable attribute set to true as shown:

    
    <element name="count" type="xsd:int" nillable="true" />
    
    								

  2. An element element with its minOccurs attribute set to 0 and its maxOccurs attribute set to 1, or its maxOccurs attribute not specified, as shown:

    
    <element name="count" type="xsd:int" minOccurs="0" />
    
    								

  3. An attribute element with its use attribute set to optional, or not specified, and having neither its default attribute nor its fixed attribute specified, as shown:

    
    <element name="date">
      <complexType>
        <sequence/>
        <attribute name="count" type="xsd:int" use="optional" />
      </complexType>
    </element>
    
    								

Table below shows how XML Schema primitive types are mapped into Java wrapper classes in these cases:

Table 2.2. Primitive Schema Type to Java Wrapper Class Mapping

XML Schema typeSOAP Java type
xsd:intjava.lang.Integer
xsd:longjava.lang.Long
xsd:shortjava.lang.Short
xsd:floatjava.lang.Float
xsd:doublejava.lang.Double
xsd:booleanjava.lang.Boolean
xsd:bytejava.lang.Byte
xsd:unsignedBytejava.lang.Short
xsd:unsignedShortjava.lang.Integer
xsd:unsignedIntjava.lang.Long
xsd:unsignedLongjava.math.BigInteger

NOTE: Element that is nillable, meaning that the element CAN BE EMPTY without causing a validation error. For each of the XML schema built-in types that map to a Java primitive, there is a corresponding Java primitive wrapper that can be used if a nillable="true" attribute is specified.

Example of mapping XML Schema-Java class

XML Schema:


<schema>
  <complexType name="Address">
    <sequence>
      <element name="street" nillable="true" type="xsd:string"/>  
      <element name="city" nillable="true" type="xsd:string"/>
      <element name="state" nillable="true" type="xsd:string"/>
      <element name="zip" type="xsd:int"/>    
    </sequence>
  </complexType>
</schema>
					
					
Java class:
public class Address {
	public String street;
	public String city;
	public String state;
	public int zip;
} 
					
NOTE: Since zip is not nillable, it can be primitive, otherwise it would be:

XML Schema:


<schema>
  <complexType name="Address">
    <sequence>
      <element name="street" nillable="true" type="xsd:string"/>  
      <element name="city" nillable="true" type="xsd:string"/>
      <element name="state" nillable="true" type="xsd:string"/>
      <element name="zip" nillable="true" type="xsd:int"/>    
    </sequence>
  </complexType>
</schema>
					
					
Java class:
public class Address {
	public String street;
	public String city;
	public String state;
	public Integer zip;
} 
					

In XML Schema, we can use nillable attribute to indicate that whether the element's content could be nil, as in <xsd:element name="birthDate" type="xsd:date" nillable="true"/>. If the content of an element is nil, we can use xsi:nil attribute to signal the processor, as in <birthDate xsi:nil="true" /> and this element must not contain any content.

More examples on nillable attribute. Consider following XML Schema:

					
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
  <xsd:element name="rootElement" nillable="true"> 
    <xsd:complexType> 
      <xsd:sequence> 
        <xsd:element name="myElement" type="xsd:string"/> 
      </xsd:sequence> 
    </xsd:complexType> 
  </xsd:element> 
</xsd:schema>
 					
					
VALID:

<rootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
	<myElement>I am valid</myElement> 
</rootElement> 
					
					
VALID:

<rootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:nil="true"  /> 
					
					
INVALID (when xsi:nil is true, the element MUST BE EMPTY):

<rootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:nil="true"> 
	<myElement>I am NOT valid</myElement> 
</rootElement> 
					
					
INVALID (element rootElement MUST have myElement child and xsi:nil has not been set to true):

<rootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /> 
					
					

Mapping arbitrary XML content to Java

The <xsd:any/> element is an element that represents arbitrary XML content within an XML document. It is what its name indicates: any kind of XML. This lets you create complex type definitions in an XML Schema without describing what the exact structure of certain parts of the complex type is. Here is an example that shows the definition of a type called Order. It contains two regular elements and one <xsd:any/> element:

					
<schema elementFormDefault="qualified"   
   xmlns="http://www.w3.org/2001/XMLSchema">

   <complexType name="Order">
      <sequence>
         <element name="date" nillable="true" type="xsd:dateTime"/>
         <element name="customer" nillable="true" type="xsd:string"/>
         <xsd:any maxOccurs="unbounded"/>
      </sequence>
   </complexType>
</schema>
					
					
An instance of this type can contain any number of additional XML elements without violating the schema definition. You can add additional information to an Order element without defining its format in the schema. The JAX-RPC 1.1 specification defines that <xsd:any/> element is mapped to the SAAJ's javax.xml.soap.SOAPElement interface. This means that the Service Endpoint Interface [SEI] will contain a parameter or return value of type javax.xml.soap.SOAPElement for each place in the schema where <xsd:any/> was used and, respectively, javax.xml.soap.SOAPElement[] if the maxOccurs attribute is bigger than 1. Therefore, a JAX-RPC tool will generate the following class from the sample schema above:
public class Order implements java.io.Serializable {
    private java.util.GregorianCalendar date;
    private java.lang.String customer;
    private javax.xml.soap.SOAPElement[] _any;
    ...
}
					
This approach can be usefule when your Web service uses some data that you don't want to be mapped into a Java class, but rather want to let the JAX-RPC engine hand it to the implementation in its XML form. The implementation could then parse it or simply pass it on as XML for further processing in the backend application. Similarly, you can create a client proxy that lets you pass in a SOAPElement rather than a mapped Java object.

Professional hosting     Belorussian informational portal         Free SCWCD 1.4 Study Guide     Free SCDJWS 1.4 Study Guide     SCDJWS 1.4 Quiz     Free IBM Certified Associate Developer Study Guide     IBM Test 000-287. Enterprise Application Development with IBM WebSphere Studio, V5.0 Study Guide     SCDJWS 5.0 Quiz