You are on page 1of 45

Using XML Schemas

Effectively in WSDL Design

Software Development Conference and Expo


March 19, 2004

Chris Peltz (chris.peltz@hp.com)


Justin Murray (justin.murray@hp.com)

HP Software Global Business Unit


Introduction
• Developers creating more sophisticated web services

• Many different approaches to design of WSDL

• This
presentation identifies best practices in the use of
XML Schemas in a web services design

Learning objective
You will learn techniques to improve portability,
reusability, and interoperability in your web
services design
Agenda

• XML Schema design styles

• Using XML namespaces effectively

• Extending import to enhance WSDL reusability

• Managing interoperability with XML Schemas


Design styles for reusability and portability
• Many different ways to define XML Schemas
• Design choice can impact WSDL design and generation
of implementation classes
• Let’s consider the following simple XML document…

<?xml version="1.0" encoding="UTF-8"?>


<QuoteRequest>
<CustomerDetails Id="12345" Name="Hewlett-Packard Co.“
ContactEmail="buyer@hp.com"/>
<PartList>
<PartItem SupplierPartSKU="12345“ PartDescription="part1“
Quantity="2" QuotedPrice="0.0" />
<PartItem SupplierPartSKU="67899“ PartDescription="part2“
Quantity="5" QuotedPrice="0.0" />
</PartList>
</QuoteRequest>
One Solution
• Schema could be defined as one monolithic structure
– Russian Doll design
– Components embedded within other components
– Nested components are limited in their scope
– No dependencies on other components
Code example
<element name="QuoteRequest">
<complexType>
<choice maxOccurs="unbounded">
<element name="CustomerDetails">
<complexType>
<attribute name="CustId" type="string"/>
<attribute name="CustName" type="string"/>
<attribute name="CustEmail" type="string"/>
</complexType>
</element>
<element name="PartList">
<complexType>
<sequence>
<element maxOccurs="unbounded" minOccurs="0"name="PartItem">
<complexType>
<attribute name="SKU" type="string"/>
<attribute name="Descr" type="string"/>
<attribute name="Qty" type="integer"/>
</complexType>
</element>

Problem #1
• Several ambiguities in the schema
– Can impact generation of helper classes on some platforms

• Complex types are currently not named

• Some platforms may generate “anonymous” class names


– This can decrease readability and maintainability of code
– Clients may not be able to consume the generated WSDL
Problem #2
• Schema elements are not very reusable

• What if you wanted the PartList to be used in the


response?
– This approach would create two identical PartList structures

• Problems arise in generation of implementation classes


– Platform may generate error on name collision, or
– Platform may assign PartList1 and PartList2 for uniqueness

A better approach is to refactor the schema…


Refactor the Schema: Step 1
• Refactor the same type used multiple times
– E.g., both PartList and PartItem are used by both SOAP
request and response documents

• Steps:
– Separate complexType with name of PartListType
– Define an element of type PartListType with name PartList

QuoteRequest QuoteResponse

PartList PartListType PartList


Refactor the Schema: Step 2
• Refactor a type with slightly different uses
– E.g., both request and response have a concept of an
owner (either Supplier or Customer)

• Steps:
– Create a common type called, OwnerDetailsType
– CustomerDetails and SupplierDetails can reference this type

QuoteRequest QuoteResponse

CustomerDetails OwnerDetails SupplierDetails


A Better Solution
• Consider refactoring to increase reusability
– Organize components as individual type definitions
– Reference types using namespace prefixes
– Often referred to as Venetian Blind design
Venetian Blind Pattern - Code example
<complexType name="OwnerDetails">
<attribute name="CustId" type="string"/>
<attribute name="CustName" type="string"/>
<attribute name="CustEmail" type="string"/>
</complexType>
<complexType name="PartItemType">
<attribute name="SKU" type="string"/>
<attribute name="Descr" type="string"/>
<attribute name="Qty" type="int"/>
<attribute name="QuotedPrice" type="float"/>
</complexType>
<complexType name="PartListType">
<sequence>
<element name="PartItem" type="supReq:PartItemType“ maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="QuoteRequestType">
<sequence>
<element name="CustomerDetails" type="supReq:OwnerDetails"/>
<element name="PartList" type="supReq:PartListType"/>
</sequence>
</complexType>
<element name="QuoteRequest" type="supReq:QuoteRequestType"/>
Key benefits of the Venetian Blind design

A refactored XML schema design


offers the following three benefits:

1. The generated implementation class names can


better reflect the XML schema types they represent
2. It maximizes the potential for reuse by defining type
definitions and referencing them in the elements
Agenda

• XML Schema design styles

• Using XML namespaces effectively

• Extending import to enhance WSDL reusability

• Managing interoperability with XML Schemas


An overview of namespaces
• Namespaces provide a scoping mechanism for XML
– Similar to how package works in Java
– Useful if same names are used across multiple schemas
– Lack of namespaces causes ambiguity in references

• One strategy: define each type in different document


using namespaces to distinguish them

• targetNamespace
– Specifies what namespace the types will be bound to
– Prefixes are used to reference these types in the message
Code example

<schema
targetNamespace=http://acme.com/supplier/RequestTypes
xmlns=http://www.w3.org/2001/XMLSchema
xmlns:supReq="http://acme.com/supplier/RequestTypes”>

<sequence>
<element name="CustomerDetails"
type="supReq:OwnerDetails"/>
<element name="PartList"
type="supReq:PartListType"/>
</sequence>
Versioning Web services
• Version control important in Web services design
– How do you maintain multiple version of the same service?
– How can clients control what version they are accessing?

• Many different ways to enforce version control:


– Change the schema
version attribute 1.1
– Create a complex type


to manage the version
Use namespaces to manage
versioning in XML schemas
client
? 1.2

1.3
Using namespaces to manage versioning
• Advantage of using namespaces:
– Each appears as a completely different namespace
– XML schema itself is enforcing the version control

<schema
targetNamespace=
"http://acme.com/supplier/requestTypes_v1" ...

<schema
targetNamespace=
"http://acme.com/supplier/versions/1.0/requestTypes"
Leveraging common types
• XML schemas don’t have to be defined in a single file

•A schema may be built from a set of common types


– Want to leverage types for both the request and response
– A new XSD common file could contain these types

• QuoteRequest schema can then reference these elements


QuoteRequest.xsd CommonTypes.xsd
OwnerDetails
QuoteRequestType reference
PartListType
Code example for the CommonTypes Schema
<schema targetNamespace=http://acme.com/supplier/quoteCommon
xmlns:qc=http://acme.com/supplier/quoteCommon >
<complexType name="OwnerDetails">
<attribute name="CustId" type="string" use="required"/>
<attribute name="CustName" type="string" use="required"/>
<attribute name="CustEmail" type="string" use="required"/>
</complexType>
<complexType name="PartItemType">
<attribute name="SKU" type="string" use="required"/>
<attribute name="Descr" type="string" use="required"/>
<attribute name="Qty" type="int" use="required"/>
<attribute name="QuotedPrice" type="float" use="optional"/>
</complexType>
<complexType name="PartListType">
<sequence>
<element type="qc:PartItemType" maxOccurs="unbounded"/>
</sequence>
</complexType>
</schema>
Importing the common types
• The schema for the quote request can import and
reference the common types

• To tie everything together…


– Define an additional namespace, common, for these types
– Reference common types with the newly defined name
• common prefix
– Reference other types in the current schema using the
targetNamespace
• supReq prefix
Code example
defining the
shorthand tags

<schema targetNamespace=http://acme.com/supplier/types
xmlns:supReq=http://acme.com/supplier/types
xmlns:common="http://acme.com/supplier/quoteCommon”>
<import namespace=http://acme.com/supplier/QuoteCommon importing the
schemaLocation=”http://acme.com/supplier/commontypes.xsd”/> schema
<complexType name="QuoteRequestType">
<sequence>
<element type="common:DocumentInfoType” name=”DocumentInfo"/>
<element type="common:OwnerDetails” name=CustomerDetails"/>
<element type="common:PartListType" name=”PartList”/>
</sequence> referencing a
</complexType> common type
<element name="QuoteRequest“ type="supReq:QuoteRequestType">
</element>
</schema>
Agenda

• XML Schema design styles

• Using XML namespaces effectively

• Extending import to enhance WSDL reusability

• Managing interoperability with XML Schemas


Why use WSDL Import?
WSDL includes a robust import mechanism
to enable web services to be built in a modular fashion

• Three important considerations:


1. Define the XML Schemas independent from the WSDL
2. Separate your WSDL into modular components
3. Leverage import to tie everything together

• Key benefits of this approach:


– Easier to manage and maintain
– Fits model where XSD/WSDL are created independently
– Addresses situations where XML schemas already exist
– Increases reusability of schemas across projects
Best practices for importing schemas
• Can use either xsd:import or wsdl:import

• WS-I basic profile recommends:


– Use wsdl:import to import WSDL documents
– Use xsd:import to import XML schemas

• Here is an incorrect way of referencing schemas:

<definitions
targetNameSpace=”http://acme.com/supplier/definitions”…>
<wsdl:import
namespace=”http://acme.com/supplier/types”
location=”http://acme.com/supplier/types.xsd”/>
And the correct way…

<definitions
targetNameSpace=”http://acme.com/supplier/definitions”…>
<types>
<xsd:schema
targetNamespace=”http://acme.com/supplier/types” …>
<xsd:import namespace=http://acme.com/supplier/types
schemaLocation=
”http://acme.com/supplier/types.xsd”/>
</xsd:schema>
</types>
Building modular WSDL
• Use import to separate WSDL into modular components:

• WSDL organized into the following three components:


– XML schemas are placed in the 1st file
– WSDL message abstractions are placed in a 2nd file
– Service binding are placed in a 3rd file
Building modular WSDL
• How import is leveraged here:
– Service bindings would import the message definitions
• Uses <wsdl:import> to import definitions
– Message definitions would import the schemas
• Uses <xsd:import> to import definitions

• Overall, this approach can greatly improve component


reusability
– e.g., could provide multiple service bindings or URL
locations for the same WSDL operations
Code example
<definitions
targetNameSpace=”http://acme.com/supplier/definitions”
xmlns:types=”http://acme.com/supplier/types”>

<types>
<xsd:schema …>
<xsd:import …>
</xsd:schema>
</types>

<message name=”GetQuoteRequest”>
<part name=”QuoteRequest”
element=”types:QuoteRequest”/>
</message>
</definitions>
Referencing imported types
• Next important design question:
– How to properly reference schema types within the WSDL?

• Most common approach:


– Reference types in WSDL input and output message parts

• In our example:
– Define a request for quote for a supplier
• QuoteRequest type in types.xsd file
– Import that file in the WSDL using xsd:import
– Reference the type within the <message><part> section
Managing namespaces with WSDL
Generally a good practice to specify a
different namespace for the imported schema types
• <import> requires that either the:
– Namespace of imported file is different
– Namespace of imported file is not specified (unqualified)

• Use <xsd:include> if namespaces are the same


– <xsd:include> can be used when combining schemas

• WSDL 1.2 introduces <wsdl:include> tag


– Works similar to xsd:include
– Allows a single WSDL namespace across components
The importance of tools
•A good tool can help in creation of schemas and WSDL
– Recommend combination of XML Spy and CapeClear
– These tools can provide great value in design process

Altova XMLSPY

CapeClear WSDL Editor


Agenda

• XML Schema design styles

• Using XML namespaces effectively

• Extending import to enhance WSDL reusability

• Managing interoperability with XML Schemas


Introduction
• Choice of platform can impact interoperability
– Certain XML types and structures may not be compatible
• What if the language doesn’t support a data type?
• What if multiple platforms interpret a type differently?

• We will next look at:


– Interoperability issues with simple types
– Use of arrays and hashtables across J2EE
.NET and Java
– Use of dates in Java
– Problems in mapping certain .NET
XML schema structures
Working with basic types
• Use of char type
– e.g., the Java char type
– No mechanism to map this type to an XML schema

• Use of unsigned numerical types


– e.g., <xs:unsignedInteger>
– Java currently does not support unsigned types

• Use of data type restrictions


– e.g., restricting a number between –180 and 180
– Most platforms don’t support restrictive subclassing

• Use of decimal and floating point numbers


– Each platform may support precision differently
Working with complex types
• Use of Arrays
– Nested or multi-dimensional arrays can pose a challenge
– ArrayList and Vector Java types might not be compatible
with the client platform
– Use literal arrays to avoid any potential portability
problems

– These problems can occur when you try to go from the


Java code to the WSDL. This creates more binding to a
programming language. Better to go from WSDL to
language.
Code example
Java Implementation
public orderfields[] getOrdersByID(String ID) {
orderfields[] orderArray = null;
LinkedList orderList = EJB.getOrdersbyID(ID);
orderArray = getArray(orderList)
return (orderArray); }

Generated XML Schema


<s:complexType name="orderfields">
<s:sequence>
<s:element name="orderNbr“ type="s:long" />
<s:element name="partPrice“ type="s:float" />
</s:sequence>
</s:complexType>

.NET Client Invocation


WebReference1.orderfields[] ordersResult =
orders.getOrdersByID(userName);
Interoperability challenges with Dates
• Dates are represented in a number of ways:
– In XML, can use xsd:datetime to represent a date
– In Java, can use either java.util.Date or java.util.Calendar

• Choice can impact interoperability


– Use of either Java type will map to xsd:datetime
– JAX-RPC will map xsd:datetime to java.util.Calendar
– Any use of java.util.Date might not be understood by client
Java Service WSDL Java Client

java.util.Date ??
xsd:datetime java.util.Calendar
java.util.Calendar
Mapping XML Schema structures
• Problems can occur in mapping certain XML Schema
constructs to a specific programming language:
– The <CHOICE> keyword is not supported in JAX-RPC
– No Java constructs to represent:
• Schema annotations
• Default values
• Optional attributes

• Key problem:
– Server-side bindings will not contain these constructs
– Constructs will also be lost in WSDL if platform dynamically
generates WSDL
• May need to force use of static WSDL file
Code example
Before:

<xs:element name="CustomerDetails">
<xs:annotation>
<xs:documentation>comments
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="CustId“
type="xs:integer“ After:
use="optional" default="9999"/>
<xs:element
</xs:complexType>
name="CustomerDetails">
</xs:element>
<xs:complexType>
<xs:attribute name="CustId”
type="xs:integer“>
</xs:complexType>
</xs:element>
Final thoughts around interoperability
• Make use of XML Schemas
– Clearly, there are pitfalls to avoid
– Much to be gained in reusability and portability

• Test your web services for interoperability


– Validate how the service will work on other platforms
– Minimize issues with comprehensive test suites
– Consider tools such as Parasoft SOAPTest for this

• Pay close attention to WS-I


– Specific recommendations to encourage use of schemas
What is WS-I?
WS-I is an open industry effort chartered to
promote web services interoperability
across platforms, applications, and languages

• Key objectives:
– Establish profiles showing how specifications work together
– Does not create standards, only guides their use

• Basic Profile 1.0 finalized in Aug ’03


– Focus on SOAP 1.1, WSDL 1.1, and UDDI 1.2
– Discourages use of certain features (e.g., SOAP encoding)
– Develop testing tools to validate conformance to BP 1.0
– Create supply-chain management same application
A few guidelines from WS-I
• Use WSDL 1.1 to describe web services interface

• Use standard fault tags for SOAP faults


– <faultcode>, <faultstring>, <faultactor>, <detail>

• Use XML Schemas as type system for WSDL

• Under various import options:


– Use wsdl:import to import WSDL components
– Use xsd:import to import XML Schemas

• Reference WSDL part elements correctly:


– Incorrect: <part name=“body” element=“xsd:string”>
– Correct: <part name=“body” element=“tns:request”>

• WSDL binding should be either rpc-literal or doc-literal


Summary
1. Use a modular schema design
• Maximizes reuse
In the end…
• Simplifies code generation
2. Use namespaces effectively the proper use of
• Simplifies external references XML Schemas
• Can enforce version control can greatly improve:
3. Leverage import features • reusability
• Provides great reusability • flexibility
• Use tools appropriately • maintainability
4. Focus on interoperability • portability
• All types aren’t supported
• Add testing methodology of your web services
Managing namespaces
• Two main choices for importing schemas:
– Imported schema has own namespace (qualified)
– Imported schema shares namespace (unqualified)
• Choice typically based on:
– Readability of schemas
– XML Schema ownership
– Personal preference
• Controlled by elementFormDefault attribute:

<schema targetNamespace=http://acme.com/supplier/quoteCommon
xmlns:qc=http://acme.com/supplier/quoteCommon
elementFormDefault="qualified“
attributeFormDefault="unqualified">

You might also like