Using Web Services

 < Free Open Study > 



Let's look at a typical problem that can be solved using web services. Consider a company that offers online financial information, including the latest currency exchange rates. This exchange rate information is used by customers within a travel voucher processing system. Such a system has a single use case: to get the exchange rate between one country's currency and US dollars.

The client system initiates the action by generating an HTTP request and providing the standard two-letter country code. The server system will respond with a single floating point number that represents the exchange rate between the requested country's currency and US dollars (this number will be expressed in currency units per dollar). The initial implementation must support the Canadian Dollar, the Japanese Yen, the British Pound, the Euro, and the Mexican Peso. It should return a value of 1.0 for the US Dollar.

Although it is simple, this example models a number of real-world business situations and it could be generalized to address a number of similar challenges. For example, instead of exchange rates, the service could return stock quotes based on a ticker symbol, or it could return a product price based on stock number.

The following code implements a class that meets the requirements of our system:

    import java.util.Hashtable;    public class ExchangeRate {      private Hashtable rate_table;      public ExchangeRate() {        rate_table = new Hashtable(6);        rate_table.put("CA", new Double(1.562600));   //Canada        rate_table.put("EU", new Double(1.090394));   //Euro        rate_table.put("JP", new Double(120.435000)); //Japan        rate_table.put("MX", new Double(9.589000));   //Mexico        rate_table.put("UK", new Double(0.676133));   //United Kingdom        rate_table.put("US", new Double(1.000000));   //United States      } 

The getExchangeRate() method is the method that we will expose as a web service. This method looks up the country code and returns the exchange rate. If the country requested is not found the component returns a zero value. In a real system, we would probably look up the exchange result from a database, or even another web service:

      public double getExchangeRate(String country_code) {        Object obj = rate_table.get(country_code);        double rval = 0;        if (obj != null) {            rval = ((Double)obj).doubleValue();        }        return rval;      }    } 

The SOAP Request

Our interest is in using SOAP over HTTP. SOAP has always been expected to work within an HTTP framework and although SOAP can be used as a one-way protocol, it easily accommodates HTTP. We'll examine an example of a SOAP HTTP request for our Exchange Rate service. We won't have to generate these SOAP requests ourselves, that will be done by tools that we'll be introduced to shortly. Note that a SOAPAction attribute has been added to the HTTP request headers:

    POST /soap/servlet/rpcrouter HTTP/1.0    Host: localhost    Content-Type: text/xml; charset=utf-8    Content-Length: 464    SOAPAction: "" 

The envelope contains the body and the optional header. The attributes of the envelope are used to identify namespaces (xsi and xsd in this case). The envelope must have an attribute that associates it with the http://schemas.xmlsoap.org/soap/envelope/ namespace. An optional encoding style can also be included:

    <?xml version='1.0' encoding='UTF-8'?>    <SOAP-ENV:Envelope        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"        xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"        xmlns:xsd="http://www.w3.org/1999/XMLSchema"> 

The SOAP body contains the information needed to execute our RPC. The first element in the body provides the information about how to handle the request. This element is associated with, or bound to, an implementation on the server. In our case it will be associated with the getExchangeRate() method. The xmlns attribute establishes a namespace for our service and the encodingStyle attribute determines how the arguments will be represented (or marshaled):

      <SOAP-ENV:Body>        <ns1:getExchangeRate          xmlns:ns1="SoapExchangeRate"          SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 

A server must parse and extract the parameters by their names. The parameter name forms an element, the contents of which is the value of the argument. The type of the argument is determined by the attributes and are based on schema data types that are referenced in the envelope:

          <country xsi:type="xsd:string">JP</country>        </ns1:getExchangeRate>      </SOAP-ENV:Body>    </SOAP-ENV:Envelope> 

Apart from the SOAPAction header, this is an ordinary HTTP request. The actual SOAP message is contained the body of the request. The SOAPAction header provides the intent of the message - it allows servers and firewalls to determine how to handle, filter, or route the SOAP request appropriately. This header can have a value of an empty pair of quotes (as shown above), or could be followed by a URI. The empty quotes mean that the URI information is carried in the HTTP request URI.

The SOAP Response

The response header is a normal HTTP response header. Apache SOAP (which we will use shortly) adds a cookie, which can be used to support complex systems in which state needs to be maintained between RPCs. However, this is an optional feature that is not supported by all servers and clients:

    HTTP/1.1 200 OK    Content-Type: text/xml; charset=utf-8    Content-Length: 485    Date: Wed, 14 Dec 2001 19:33:27 GMT    Server: Apache Tomcat/4.0 (HTTP/1.1 Connector)    Set-Cookie: JSESSIONID=6186631705A6F044B5E057B361A50893;Path=/soap 

The SOAP response is a SOAP message that follows the same rules as we laid out for the SOAP request. Of course, the values and elements within this document reflect the new message being sent:

    <?xml version='1.0' encoding='UTF-8'?>    <SOAP-ENV:Envelope        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"        xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"        xmlns:xsd="http://www.w3.org/1999/XMLSchema">      <SOAP-ENV:Body>        <ns1:getExchangeRateResponse          xmlns:ns1="SoapExchangeRate"          SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">          <return xsi:type="xsd:double">120.435</return>        </ns1:getExchangeRateResponse>      </SOAP-ENV:Body>    </SOAP-ENV:Envelope> 

The Error Response

If an error occurs during the processing of the SOAP request, the server must issue an HTTP 500 Internal Server Error response, which must also include a message with a SOAP fault element that indicates the SOAP processing error. A <SOAP-ENV:Fault> element, included in the body of the response, details the fault that occurred. The error that resulted in this error response was generated by passing three arguments to our server instead of the one or two arguments supported by ExchangeRate:

    HTTP/1.1 500 Internal Server Error    Content-Type: text/xml; charset=utf-8    Content-Length: 578    Date: Wed, 14 Dec 2001 20:22:48 GMT    Server: Apache Tomcat/4.0 (HTTP/1.1 Connector)    Set-Cookie: JSESSIONID=A9C7A201A43594C4A9237205E46184E5;Path=/soap    <?xml version='1.0' encoding='UTF-8'?>    <SOAP-ENV:Envelope         xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"         xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"         xmlns:xsd="http://www.w3.org/1999/XMLSchema">      <SOAP-ENV:Body>        <SOAP-ENV:Fault>          <faultcode>SOAP-ENV:Server</faultcode>          <faultstring>             Exception while handling service request:             ExchangeRate.getExchangeRate(java.lang.String,java.lang.String,             java.lang.String) -- no signature match          </faultstring>          <faultactor>/soap/servlet/rpcrouter</faultactor>        </SOAP-ENV:Fault>      </SOAP-ENV:Body>    </SOAP-ENV:Envelope> 

The client can use the fault code to help it deal with the fault. There are a few standard codes that have already been defined:

Fault Code

Reason for Fault

VersionMismatch

The processing party found an invalid namespace for the SOAP Envelope.

MustUnderstand

An immediate child element of the SOAP Header, that was either not understood or not obeyed by the processing party, contained a SOAP mustUnderstand attribute with a value of 1.

Client

Indicates that the message was incorrectly formed or did not contain the appropriate information in order to succeed. For example, the message could lack the proper authentication or payment information. The message will not succeed without change.

Server

Indicates that the message could not be processed for reasons not directly attributable to the contents of the message itself, but rather to the processing of the message. For example, processing could include communicating with an upstream processor that didn't respond. The message may succeed at a later point in time.

The fault string is intended to be understood by end users and the fault actor should identify what part of the system caused the fault. In this case, our message identified the Apache rcprouter servlet. A <detail> element can be used to allow the service to provide detailed error information. For example, if we handled invalid country names as an error we could include detailed information in this section.



 < Free Open Study > 



Professional Java Servlets 2.3
Professional Java Servlets 2.3
ISBN: 186100561X
EAN: 2147483647
Year: 2006
Pages: 130

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