Using SOAP and WSDL


While many of the more advanced features of the emerging Web services architecture are still being built into many of the platforms, support for SOAP and WSDL in most vendors' Web services toolkits is widespread and makes binding to and using Web services straightforward. In this section, we investigate how a typical application server and can be used to deploy our simple banking example, and how it can be later consumed by a client application. The overall architecture can be seen in Figure 3-37.

Figure 3-37. Cross-platform banking Web service example.

graphics/03fig13.jpg

The architecture for this sample is typical of Web services applications that routinely combine a variety of platforms. In Figure 3-37, we use Microsoft's .Net and Internet Information Server to host the service implementation, but we use the Java platform and the Apache AXIS Web service toolkit to consume this service and drive the application.

Service Implementation and Deployment

The implementation of our banking service is a straightforward C# class, and is shown in Figure 3-38.

Figure 3-38. A simple bank Web service implementation.
 using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Web; using System.Web.Services; [WebService(Namespace="http://bank.example.org")] public class BankService : System.Web.Services.WebService {   [WebMethod]   public string openAccount(string title,                            string surname,                            string firstname,                            string postcode,                            string telephone)   {     BankEndSystem bes = new BackEndSystem();     string accountNumber = bes.processApplication(title,                                                   surname,                                                   firstname,                                                   postcode,                                                   telephone);     return accountNumber;   } } 

Most of the work for this service is done by some back-end banking system, to which our service delegates the workload. Our service implementation just acts as a kind of gateway between the Web service network to which it exposes our back-end business logic, and the back-end systems themselves to which it delegates work it receives from Web services clients. This pattern is commonplace when exposing existing systems via Web services, and makes good architectural sense since the existing system does not have to be altered just to add in Web service support.

The key to building a successful Web service, even one as simple as our bank account example, is to ensure that the orthogonal issues of service functionality and deployment are kept separate. That is, do not allow the implementation of your system to change purely because you intend to expose its functionality as a Web service.

It is a useful paradigm to treat your Web services as "user interfaces" through which users (in most cases other computer systems) will interact with your business systems. In the same way that you would not dream of putting business rules or data into human user interfaces, then you should not place business rules or data into your Web service implementations. Similarly, you would not expect that a back-end business system would be updated simply to accommodate a user interface, and you should assume that such mission-critical systems should not be altered to accommodate a Web service deployment.


When deployed into our Web services platform (in this example, Microsoft's IIS with ASP.Net), the associated WSDL description of the service is generated by inspection of the implementation's interface and made available to the Web. The resultant WSDL[10] is shown in Figure 3-39.

[10] The WDSL description generated by ASP.Net is richer than that shown here since it also includes HTTP GET and HTTP POST bindings. However, we are predominantly interested in SOAP as the Web services transport, and so the HTTP bindings have been removed.

It is important to bear in mind, that although the WSDL shown in Figure 3-39 is intricate and lengthy for a simple service, the effort required to build it is practically zero because of tool support. The only issue that this should raise in the developer's mind is that their chosen platform and tools should handle this kind of work on their behalf. WSDL should only be handcrafted where there a specific need to do something intricate and unusual that tool support would not facilitate.

Binding to and Invoking Web Services

Once the service has been deployed and its endpoint known by consumers, clients can bind to it by using their client-side Web services toolkits to create proxies. A proxy is a piece of code that sits between the client application and the network and deals with all of the business of serializing and deserializing variables from the client's program into a form suitable for network transmission and back again. The client application, therefore, never has to be aware of any network activity and is simpler to build.

Figure 3-39. Bank service auto-generated WSDL description.
 <?xml version="1.0" encoding="utf-8"?> <definitions   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"   xmlns:xs="http://www.w3.org/2001/XMLSchema"   xmlns:bank="http://bank.example.org"   targetNamespace="http://bank.example.org"   xmlns="http://schemas.xmlsoap.org/wsdl/">   <types>     <xs:schema elementFormDefault="qualified"        targetNamespace="http://bank.example.org">       <xs:element name="openAccount">         <xs:complexType>           <xs:sequence>             <xs:element minOccurs="0" maxOccurs="1"                name="title" type="xs:string"/>             <xs:element minOccurs="0" maxOccurs="1"                name="surname" type="xs:string"/>             <xs:element minOccurs="0" maxOccurs="1"                name="firstname" type="xs:string"/>             <xs:element minOccurs="0" maxOccurs="1"                name="postcode" type="xs:string"/>             <xs:element minOccurs="0" maxOccurs="1"                name="telephone" type="xs:string"/>           </xs:sequence>         </xs:complexType>       </xs:element>       <xs:element name="openAccountResponse">         <xs:complexType>           <xs:sequence>             <xs:element minOccurs="0" maxOccurs="1"                name="openAccountResult" type="xs:string"/>           </xs:sequence>         </xs:complexType>       </xs:element>       <xs:element name="string" nillable="true"          type="xs:string"/>     </xs:schema>   </types>   <message name="openAccountSoapIn">     <part name="parameters" element="bank:openAccount"/>   </message>   <message name="openAccountSoapOut">     <part name="parameters"      element="bank:openAccountResponse"/>   </message>   <portType name="BankServiceSoap">     <operation name="openAccount">       <input message="bank:openAccountSoapIn"/>       <output message="bank:openAccountSoapOut"/>     </operation>   </portType>   <binding name="BankServiceSoap"    type="bank:BankServiceSoap">     <soap:binding          transport="http://schemas.xmlsoap.org/soap/http"          style="document"/>     <operation name="openAccount">       <soap:operation            soapAction="http://bank.example.org/openAccount"            style="document"/>       <input>         <soap:body use="literal"/>       </input>       <output>         <soap:body use="literal"/>       </output>     </operation>   </binding>   <service name="BankService">     <port name="BankServiceSoap"      binding="bank:BankServiceSoap">       <soap:address           location="http://localhost/dnws/BankService.asmx"/>     </port>   </service> </definitions> 

In our example, the serialization and deserialization is to SOAP from Java and back again, and is handled by a proxy generated by the Apache AXIS WSDL2Java tool. This tool parses WSDL at a given location and generates a proxy class which allows client code to communicate with that service. For example, the proxy code generated by this tool when it consumed our bank example service is shown in Figure 3-40.

Figure 3-40. Apache AXIS auto-generated proxy for the bank Web service.
 /**  * This file was auto-generated from WSDL  * by the Apache Axis WSDL2Java emitter.  */ package org.example.bank; import java.lang.String; public class BankServiceSoapStub                 extends org.apache.axis.client.Stub                 implements org.example.bank.BankServiceSoap {   // Data members removed for brevity   public BankServiceSoapStub()                           throws org.apache.axis.AxisFault {      this(null);   }   // Other constructors removed for brevity   private org.apache.axis.client.Call createCall()                             throws java.rmi.RemoteException {       // Implementation removed for brevity       return _call;     }     catch (java.lang.Throwable t) {       throw new org.apache.axis.AxisFault("Failure trying" +                                " to get the Call object", t);     }   }   public String openAccount(String title, String surname,                             String firstname,                             String postcode,                             String telephone)                             throws java.rmi.RemoteException {      // Implementation removed for brevity   } } 

The proxy class shown in Figure 3-40 allows the client of the Web service to call its functionality with a call as simple as the likes of:

 bankAccountService.openAccount("Mr", "Aneurin", "Bevan",                               "ABC 123", "0207 123 4567") 

without having to worry about the fact that on the wire, the proxy has sent a SOAP message that looks like that shown in Figure 3-41 below:

Figure 3-41. Proxy generated SOAP message.
 <?xml version="1.0" encoding="utf-8" ?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">   <soap:Body>     <openAccount xmlns="http://bank.example.org">       <title>Mr</title>       <surname>Bevan</surname>       <firstname>Aneurin</firstname>       <postcode>ABC 123</postcode>       <telephone>0207 123 4567</telephone>     </openAccount>   </soap:Body> </soap:Envelope> 

At the receiving end, the bank service's SOAP server will retrieve this SOAP from the network and turn it into something meaningful (in our case C# objects) before passing it to the service implementation. The service implementation grinds away at its task, producing some result in its own proprietary format before passing it back to the underlying Web services platform to serialize its results into the appropriate network format (i.e., a SOAP message) and return it to the caller. At this point the service invocation has finished and the resources used during the execution of that service can be freed.

Where's the Hard Work?

For simple interactions, there isn't any hard work for the developer to do because SOAP toolkits are sufficiently advanced enough to automate this. For example, we didn't have to worry about the style of SOAP encoding or how the marshalling occurred in any of our bank account examples, even though we crossed networks, servers, and even languages and platforms.

Though it may seem from these examples that Web services is an automation utopia, it is not. While it is true that for the majority of cases, simple interactions can be automated (though auto-generation of WSDL from service implementation code and auto-generation of proxies from WSDL descriptions), this is about as far as toolkits have advanced.

Given that this book extends beyond this third chapter, it is safe to assume that we're going to have to roll up our shirt sleeves at some point and patch the gaps that the current set of Web services toolkits inevitably leaves. It is in these subsequent chapters where we will find the hard work!



Developing Enterprise Web Services. An Architect's Guide
Developing Enterprise Web Services: An Architects Guide: An Architects Guide
ISBN: 0131401602
EAN: 2147483647
Year: 2003
Pages: 141

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net