WSDL Basics and Why it Learning?

WSDL Basics LearningIn this blog, you'll learn the basics of creating a Web Services Description Language (WSDL) file by hand. Our goal in this blog is to provide you with some best practices and quickly get you up to speed with the language. If you're already comfortable with WSDL, you can safely skip this article. If you're a WSDL/XML Schema purist, then reading this blog will only upset you, because we won't take the time to cover the esoteric capabilities of the language here.

WSDL is a nontrivial language. To express the depth and breadth of the language fully is beyond the scope of my blog. In this bloge note, we'll focus on a WSDL format that's most amenable to creating highly interoperable web services: document-centric and unencoded (also known as bare or literal encoding). Don't worry if these terms are meaningless to you now. By the end of this article, they'll make perfect sense.


Table of contents[Show]


 

Why Learn About WSDL?

We can just use the Java annotations to have WorkSpace Studio generate a WSDL file for you. This is a handy feature, especially when learning how to write web services in Java. WorkSpace Studio also provides the ability to generate code in the other direction: to generate Java code from a WSDL file.

You should be aware of the subtle differences in these approaches. They both have their strengths and their weaknesses. We've heard it proposed that if you're a Java-centric shop, you should just use the WSDL-generation feature and not worry about the details of WSDL creation and syntax. This is patent nonsense.

We remember the days when the C language was introduced to the personal computing world. At the time, BASIC was the dominant language. Some vendors created BASIC-to-C language converters, making the claim that you didn't need to waste time learning C; you could continue to write your BASIC programs and then push a button to convert the programs into C. These programs did work, especially for very small projects, but they weren't viable in the long run. By using this code-generation approach, you rob yourself of the ability to use more powerful, language-specific capabilities. As a result, you guarantee that you'll write mediocre software at best. The one saving grace of these BASIC-to-C converters was that they did work as a learning tool to help BASIC programmers understand how to write C programs.

We live in an increasingly web service-oriented world. WSDL is the language of web services, and it will serve you well to become conversant in WSDL, especially if you're striving to create excellent systems. You can fall into a subtle mental trap when you generate WSDL from your Java code: you might find yourself generating Java API–oriented web services. If you look at the world through Java-colored glasses, the work you produce will be similarly colored; if you look at the world through the prism of web services, your work will naturally become more service-oriented. It's vital to adopt the new mindset as soon as possible.

 

WSDL Basics

Listing 1 shows a sample WSDL file for a simple web service that returns customer information based on the ID of the customer. Even though it describes a simple service, the sample WSDL includes all the necessary principles that you need to understand. We'll use this listing as a reference throughout our discussion on WSDL basics.

Listing 1. A Basic WSDL File

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

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.alsb.com/Sample/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Sample"
targetNamespace="http://www.alsb.com/Sample/">

<wsdl:types>

   <xsd:schema targetNamespace="http://www.alsb.com/Sample/">
      <xsd:complexType name="Customer">
         <xsd:sequence>
            <xsd:element name="customerID" type="xsd:int" minOccurs="1"/>
            <xsd:element name="firstName" type="xsd:string" minOccurs="1"/>
            <xsd:element name="lastName" type="xsd:string" minOccurs="1"/>
         </xsd:sequence>
      </xsd:complexType>

      <xsd:complexType name="CustomerQuery">
         <xsd:sequence>
            <xsd:element name="customerID" type="xsd:int" minOccurs="1"/>
         </xsd:sequence>
      </xsd:complexType>

      <!--  Map our types into elements  -->
      <xsd:element name="getCustomer" type="tns:CustomerQuery"/>
      <xsd:element name="getCustomerResponse" type="tns:Customer"/>

   </xsd:schema>

</wsdl:types>

<wsdl:message name="GetCustomerRequest">
   <wsdl:part element="tns:getCustomer" name="customerQuery" />
</wsdl:message>

<wsdl:message name="GetCustomerResponse">
   <wsdl:part element="tns:getCustomerResponse" name="customer"/>
</wsdl:message>

<wsdl:portType name="Sample">
   <wsdl:operation name="getCustomer">
      <wsdl:input message="tns:GetCustomerRequest" />
      <wsdl:output message="tns:GetCustomerResponse" />
   </wsdl:operation>
</wsdl:portType>

<wsdl:binding name="SampleSOAP" type="tns:Sample">
   <soap:binding style="document"
      transport="http://schemas.xmlsoap.org/soap/http" />

   <wsdl:operation name="getCustomer">
      <soap:operation
         soapAction="http://www.alsb.com/Sample/Customer" />
         <wsdl:input>
            <soap:body use="literal" />
         </wsdl:input>
         <wsdl:output>
            <soap:body use="literal" />
      </wsdl:output>
   </wsdl:operation>

</wsdl:binding>

<wsdl:service name="Sample">
   <wsdl:port binding="tns:SampleSOAP" name="SampleSOAP">
   <soap:address location="http://www.alsb.com/" />
   </wsdl:port>
</wsdl:service>

</wsdl:definitions>

 

XML Namespaces

Before we get too far into our discussion of WSDL, we'll take a moment to discuss XML namespaces. The namespace concept is used extensively both by WSDL and XML Schema. Namespaces can make reading a WSDL file difficult unless you understand what a namespace is and how it affects the document.

A namespace is a way to categorize or group element, data type, and attribute names within an XML document. This is especially handy when combining multiple XML vocabularies into a single document. An XML namespace is analogous to a Java package or a C# namespace keyword. Namespaces help to protect against naming collisions. Let's examine a concrete example of a naming collision and learn how XML namespaces help. Examine both Listing 2 and Listing 3 and notice the difference in how the Address data types are defined.

Listing 2.Shipping.xsd Snippet

<xsd:complexType name="Address">
   <xsd:sequence>
      <xsd:element name="street" type="xsd:string" minOccurs="1"/>
      <xsd:element name="city" type="xsd:string" minOccurs="1" maxOccurs="1'"/>
      <xsd:element name="state" type="xsd:string" minOccurs="1" maxOccurs="1"/>
      <xsd:element name="zipCode" type="xsd:string" minOccurs="1" maxOccurs="1"/>
   </xsd:sequence>
</xsd:complexType>

Listing 3. Customer.xsd Snippet

<xsd:complexType name="Address">

   <xsd:sequence>
      <xsd:element name="street1" type="xsd:string" minOccurs="1" maxOccurs="1"/>
      <xsd:element name="street2" type="xsd:string" minOccurs="1" maxOccurs="1"/>
      <xsd:element name="street3" type="xsd:string" minOccurs="1" maxOccurs="1"/>
      <xsd:element name="city" type="xsd:string" minOccurs="1" maxOccurs="1'"/>
      <xsd:element name="state" type="xsd:string" minOccurs="1" maxOccurs="1"/>
      <xsd:element name="zipCode" type="xsd:string" minOccurs="1" maxOccurs="1"/>
   </xsd:sequence>

</xsd:complexType>

Both Address types are valid, but their structure varies significantly. If you try to use both these schemas in an Order web service, there will be a naming conflict because they share the same name. To correct this problem, you would declare two namespaces: one for each of the schemas that you want to use. The following XML snippet shows how to declare a namespace:

xmlns:shp="http://www.alsb.com/shipping/"

In this case, the namespace you declare is http://www.alsb.com/shipping. This namespace uses the prefix of shp to represent the namespace. A namespace is defined by a URI string, not the prefix. You can think of the prefix as a variable that holds the namespace "value." Alternatively, you can think of a namespace prefix as a pointer that represents a namespace. For example, Listing 4 shows what might appear to be two namespace declarations. In reality, it is a single namespace referred to by two different namespace prefixes. The string is the namespace, not the prefix.

Listing 4. Two Prefixes Can Represent the Same Namespace

xmlns:shp="http://www.alsb.com/shipping/"
xmlns:foo="http://www.alsb.com/shipping/"

Note that the URI doesn't need to point to anything in particular or even be a URL. It's simply a string within the document. The xmlns: that appears before the prefix is simply the notation that tells the XML parser that an XML namespace is about to be declared.

Listing 5 shows how namespaces allow you to use two different data types with the same name (Address, in this case) in the same WSDL file. The <CustomerAddress> element takes the form of the <Address> type that you defined in Listing 3, while the <ShippingAddress> takes the form of the <Address> type you defined in Listing 2.

Listing 5. The Order.wsdl Snippet

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

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
      xmlns:tns="http://www.alsb.com/Sample/"
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Sample"
      xmlns:shp="http://www.alsb.com/shipping/"
      xmlns:customer="http://www.alsb.com/customer/"
      targetNamespace="http://www.alsb.com/order/">
   <wsdl:types>
      <xsd:schema targetNamespace="http://www.alsb.com/customer/">
         <xsd:element name="CustomerAddress" type="customer:Address>
         <xsd:element name="ShippingAddress" type="shp:Address>
         …
      </xsd:schema>
   </wsdl:types>

</wsdl:definitions>

 

If you've been paying close attention, you might be wondering how these namespaces map to the data types; how does the computer know that a customer:Address has the definition that you provided in Listing 3? The answer is that it doesn't. You need to provide that mapping in a separate XML import statement when you import the Customer.xsd schema.

You'll find that namespaces are used frequently in XML Schema and WSDL documents. Knowing how to use them is critical for understanding these documents.

 

The Default Namespace

Every element and attribute in an XML document or XSD belongs to a namespace. The default namespace is the namespace applied to all nodes in the document that don't have an explicit namespace associated with them. Defining a default namespace is similar to defining a namespace with a prefix; you just don't define a prefix. There can be only one default namespace for each element. There's a fair bit of subtle detail to that last sentence, so let's explore it further.

Listing 6 shows how to define a default namespace for an entire WSDL file. Namespaces are inherited by each subelement in an XML document. Because this is a WSDL document, it's a common practice to define the WSDL namespace as the default namespace. As a result, the WSDL-specific elements don't need to have a namespace prefix. You can see this in action in Listing 6. The <types> element has no namespace prefix defined for it, so the XML parser uses the default namespace, whereas the <schema> elements all have the xsd: prefix explicitly defined, because the <schema> element isn't part of the WSDL namespace.

Listing 6. Defining and Using a Default Namespace

 

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

<wsdl:definitions name="Sample"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.alsb.com/order/">

<types>
   <xsd:schema targetNamespace="http://www.alsb.com/customer/e">
      <xsd:element name="CustomerAddress" type="customer:Address>
      <xsd:element name="ShippingAddress" type="shipping:Address>
      …
   </xsd:schema>
</types>

ou can override default namespaces in subelements. This allows you to simplify your documents (at least for human readers) by providing a new default namespace in a section of the document where that new namespace is commonly used. You see an example of this in Listing 7. The elements <definitions> and <types> are both part of the WSDL namespace. Because <definitions> declares the WSDL namespace as its default namespace, it doesn't need to specify a namespace prefix. Furthermore, the child <types> element inherits the default namespace of its parent <definitions> element.

However, the <schema> and <element> tags are part of the XML Schema namespace, yet they don't have a namespace prefix in their tags. This is because the default namespace is overridden by the <schema> element: it declares its own default namespace, and this new default namespace is inherited by its child <element> tags.

Listing 7. Overriding the Default Namespace

<definitions
name="DefaultNamespaceSample"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="foo"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="foo">

<types>
   <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="foo">
      <element name="Response" type="xsd:string"/>
      <element name="Request" type="xsd:string"/>
   </schema>
</types>

Some people feel this makes the resulting XML easier to read. Other folks argue that it makes it harder to read, especially if you don't know which tag belongs in which namespace. You'll need to decide for yourself how you want to use namespaces in your XML. Just as with the old arguments about where to place the curly braces in your C, C++, and Java code, it's a matter of style and personal preference.

The Target Namespace

Aside from a default namespace, you can define a target namespace. Initially, we found this confusing. Like all things technical, it becomes simple once you understand its usage. In your WSDL and XML Schema files, you're often creating new data types. These new types should belong to a namespace. Technically, you can define new elements that don't belong to a namespace, but remember that you're concerned with real-world usage here, not every fringe usage. You should always define a target namespace.

Listing 7 shows the targetNamespace attribute in action. The <schema> element defines a targetNamespace with the value "foo". Nested inside the <schema> element are two element definitions: Request and Response. These new elements are created as members of the "foo" namespace. For example, the proper way to use the Request element in an XML document is as follows:

<Response xmlns="foo">Some string here</Response> 

Alternatively, you could do the following:

<ParentElement xmlns:tns="foo"
   <tns:Response>Some string here</tns:Response>
</ParentElement >

Caution Earlier, we mentioned that XML namespaces are analogous to Java and C# package names. It's true that they're similar in many ways, but it's important to know where they're different. When you create a package name in a Java application, you're creating a namespace that affects the organization of software within the scope of that application. When you're defining an XML namespace, you may be creating a namespace that will affect the organization of data types and services throughout your entire organization! As a result, it's important to consider carefully how you'll organize and manage namespaces as a company.

 

WSDL Definitions

A WSDL file is composed of five sections contained by the <definitions> root element:

  • <types>: You define the data types used by your WSDL here. Data types in a WSDL are expressed as XML Schema elements.
  • <portType>: This is the abstract interface definition of your web service. It's similar to an interface definition in Java or C#. If you want a quick understanding of the functionality provided by a web service, this is the section of the WSDL to read.
  • <message>: This section defines the format of the messages (think documents) that the web service uses.
  • <binding>: This section describes how the portType is mapped into a concrete expression of data formats and protocols.
  • <service>: This section contains a collection of port elements. This allows you to specify the fact that a web service might live on multiple endpoints.

The <types> Section

WSDL files use XML Schema to define data types. Therefore, learning some basics of XML Schema will be our first topic. XML Schema is a large topic. To facilitate things, we'll assume that you have a basic understanding of object-oriented principles. With that background in mind, we'll focus on how to map object-oriented concepts into XML Schema data types. Traditionally, XML Schema files use the .xsd file extension.

Native Data Types

XML Schema provides for a fair number of native data types (also known as primitives) that you can use in your schemas: strings, integers, dates, times, and so on. Using a native data type is pretty simple. For example, declaring an object of type string looks like the following:

<element name="MyString" type="xsd:string" />

 

You can find a complete list of these native data types at this link.

Custom Data Types

Let's move to the next level and create some data types that are much more useful. For this example, you'll create a Customer data type. Your customer has the attribute's first name, last name, and customer ID. Listing 8 shows how you would define the customer object.

Listing 8. The Customer Type Definition

 

<xsd:complexType name="Customer">

   <xsd:sequence>
      xsd:<element name="customerID" type="xsd:int" minOccurs="1" />
      <xsd:element name="firstName" type="xsd:string" minOccurs="1" />
      <xsd:element name="lastName" type="xsd:string" minOccurs="1" />
   </xsd:sequence>

</xsd:complexType>

As you can see, you define the Customer object as a complexType. This is roughly equivalent to defining a Customer class in Java or C++/C#. You name the complex type using the name attribute.

Note It's possible to define data types as being anonymous within a named element. This isn't a good practice within the XSD file itself. This type of design pattern is acceptable within the WSDL file, though. Name your complex types in your XSD files, and then refer to them via <element> tags within your WSDL.

Next, you add properties to your Customer data type. In XML Schema, add the properties using the <sequence> tag. The <sequence> tag means that a series of elements or types will follow, in a specific sequence. In this example, you have three properties in this sequence: customerID, firstName, and lastName.

Although you use the <sequence> tag to define a sequence of object attributes, you can use two other tags here, depending on your needs: the <choice> and <all> tags. You use those tags when defining more complicated data types. For our purposes, a <complexType> will always contain a <sequence> of attributes.

Notice that each of the attributes in your Customer data type is defined as an element. You use the <element> tag when referring to an existing data type. In the case of our attributes, the existing data types are of type string and int. Inside the Customer data type, you can also reference other custom data types. For example, you can create an Address data type and then use it within your Customer data type, as shown in Listing 9.

Listing 9. Nesting Complex Data Types

<xsd:complexType name="Customer">

   <xsd:sequence>
   <xsd:element name="customerID" type="xsd:int" minOccurs="1" />
      <xsd:element name="firstName" type="xsd:string" minOccurs="1" />
      <xsd:element name="lastName" type="xsd:string" minOccurs="1" />
      <xsd:element name="homeAddress" type="Address"/>
   </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="Address">

   <xsd:sequence>
      <xsd:element name="street" type="xsd:string" minOccurs="1" />
      <xsd:element name="city" type="xsd:string" minOccurs="1" />
      <xsd:element name="state" type="xsd:string" minOccurs="1" />
      <xsd:element name="postalCode" type="xsd:string" minOccurs="1" />
   </xsd:sequence>

</xsd:complexType>

 

minOccurs and maxOccurs

You might have noticed that all the listings so far use the minOccurs attribute in the element definitions. This specifies the minimum number of times the element can occur within the sequence. By setting the minOccurs value to 1, you're specifying that the element must occur at least once in the sequence. If you set the value to 0, then you're specifying that the element is optional.

The complement to minOccurs is the maxOccurs attribute. It specifies the maximum number of times the element can occur in the sequence. The maxOccurs value must be a positive integer, or it might be the specified as "unbounded" to indicate that there's no limit on the number of times it might occur. These attributes are often used in conjunction. For example, the combination of minOccurs="1" and maxOccurs="1" specifies that the element must appear only once. The default value of both minOccurs and maxOccurs is "1".

Importing XML Schemas

As mentioned previously, you can import existing schemas into your XML or WSDL documents. This is an excellent way to reuse these assets, allowing you to make broad changes to your enterprise definitions in a centralized manner. Importing a schema into your WSDL file is done within the <types> section. The general format of an import statement is as follows:

<import namespace="[the URI to the namespace]" schemaLocation= 

"[file path or URI to your .XSD file]" />

 For example, in your WSDL, if you wanted to use the customer.xsd and the shipping.xsd schemas, you would use the following import statements:

<xsd:import namespace="http://www.alsb.com/customer/"

schemaLocation="customer.xsd" />

<xsd:import namespace="http://www.alsb.com/shipping/"

schemaLocation="shipping.xsd" />

Notice that the URI for the namespace matches exactly the URIs you used in Listing 5 when you defined the namespaces. Now, when you declare an element to be of type customer:Address or shp:Address, the web service is able to determine exactly which Address definition to use.

The <message> Section

A message describes the abstract form of the input, output, or fault messages. Messages are composed of one or more <part> elements. The <part> elements describe the composition of the <message>.

Because you're using the document-centric style of WSDL, the <part> elements of the <message> must refer to data structures using the element attribute. For document-centric WSDL, it's common practice to use the operation name as the name of the request message and to append Response to the operation name and use that as the name of the response message. Listing 10 demonstrates this naming approach with the GetCustomerResponse message.

Listing 10. Sample Document-Style Message Definition

 

<wsdl:message name="GetCustomerResponse">

   <wsdl:part element="tns:getCustomerResponse" name="customer"/>

</wsdl:message>

The <portType> Section

The <portType> section of the WSDL file describes the abstract interface of the web service. Listing 11 provides an example of a simple portType definition. This section of the WSDL is often compared to an abstract Java interface because it defines, at a high level, how the operations of the service work (that is, what arguments are expected and what results are returned).

Listing 11. An Example of the <portType>

<wsdl:portType name="CustomerPortType">

   <wsdl:operation name="findCustomer">
      <wsdl:input message="tns:findCustomer" />
      <wsdl:output message="tns:findCustomerResponse" />
   </wsdl:operation>

</wsdl:portType>

 

The <portType> element is made up of <operation> elements. The <operation> elements, in turn, are composed of <input> and <output> elements that map directly to the <message> elements. The <operation> elements might also contain <fault> elements to indicate the SOAP faults that the operation might throw. However, for the purposes of our crash course, you'll ignore the <fault> element.

The <binding> Section

The <binding> section is used to define how the <portType> (that is, the abstract interface of the web service) is bound to a transport protocol and an encoding scheme. A single portType may be bound to many transports and encoding scheme combinations. The most commonly used encoding scheme and transport protocol combination these days is SOAP over HTTP. The most common bindings other than HTTP/SOAP are HTTP/POST and HTTP/GET, especially when dealing with web services that were developed before HTTP/SOAP gained popularity.

As you can see from Listing 12, the <binding> is mapped to a <portType>. Each operation of the <portType> is defined in the binding, including the mapping of the operation's input and output to specific message types.

Listing 12. An Example of the HTTP/SOAP Binding

 

<wsdl:binding name="CustomerServiceSOAP" type="tns:CustomerPortType">

   <soap:binding style="document"
      transport="http://schemas.xmlsoap.org/soap/http" />

   <wsdl:operation name="findCustomer">
      <soap:operation soapAction="" style="document" />
         <wsdl:input>
            <soap:body parts="findCustomer" use="literal" />
         </wsdl:input>
         <wsdl:output>
            <soap:body parts="findCustomerResponse" use="literal" />
         </wsdl:output>
   </wsdl:operation>

</wsdl:binding>

 

The <service> Section

A service is simply a collection of <port> elements. A WSDL might contain multiple <service> definitions, one for every distinct binding type that's supported by the web service.

A <port> describes the physical locations of a binding. Listing 13 shows a sample web service that exists at a single SOAP address endpoint. If you are using SOAP for your web services, then there can be only a single <soap:address> entry for each port.

Note The term endpoint is commonly used when discussing web services. An endpoint is simply a URI that points to a location where a service exists.

Listing 13. Sample <service> and <port> Tags

<wsdl:service name="CustomerService">

   <wsdl:port binding="tns:CustomerServiceSOAP" name="CustomerServiceSOAP">
      <soap:address location="http://server1:7001/customer/CustomerService" />
   </wsdl:port>

</wsdl:service>

That's it for the basics of WSDL. Like many technical topics, it's conceptually simple. Also, like many technical topics, "the devil is in the details." Fortunately, this technology has existed long enough for some best practices to emerge.

Вас заинтересует / Intresting for you:

WordPress optimization: minimu...
WordPress optimization: minimu... 3448 views Fortan Wed, 13 Nov 2019, 12:45:25
Protovis: Definition and Short...
Protovis: Definition and Short... 2461 views Светлана Комарова Tue, 08 Oct 2019, 10:51:24
Selecting a Web Hosting for yo...
Selecting a Web Hosting for yo... 1534 views Masha Mon, 27 Aug 2018, 19:06:22
Nginx: Blocking by IP list
Nginx: Blocking by IP list 2234 views Андрей Васенин Thu, 26 Nov 2020, 17:44:45
Comments (0)
There are no comments posted here yet
Leave your comments
Posting as Guest
×
Suggested Locations