February 2002Discuss
this article
Interoperability is one of the main promises of Web
services. Web services are designed to be independent of the
underlying operating system and programming language. In this
article we will introduce basic web services interoperability
issues. We will focus on the two most popular platforms - Java
and Microsoft .NET.
Introduction
Web services interoperability can be divided into two base
categories: SOAP interoperability and WSDL interoperability.
In our previous articles we learned that SOAP is a very
high-level protocol that mandates the structure of XML
documents exchanged over some transport protocol. That's quite
a vague definition. The vagueness of this definition makes
SOAP extremely extensible and versatile, but it also makes
interoperability a bit challenging. At a basic level, we start
our quest to achieve interoperability at the transport
protocol level. Both parties involved in a message exchange
must agree to use the same transport protocol, such as HTTP,
SMTP, or JMS. But transport protocol compatibility doesn't
necessarily ensure interoperability. There are other issues
that affect interoperability. One example is data type
encoding. An encoding style defines how programmatic data
types are encoded in XML. The SOAP specification does not
mandate any particular encoding style, and developers are free
to use any encoding style they want. In theory there are
virtually unlimited choices of encoding styles that are
mutually incompatible. Fortunately there is a standard
convention. Section 5 of the SOAP specification defines an
encoding style, and it has became the de facto standard for
SOAP encoding. This encoding provides the basis for the
automated SOAP interoperability tests that are periodically
carried out by the major SOAP solutions vendors. You can see
these test results online at http://soap.systinet.net/interop/soap/index.html
More and more we're finding that WSDL lies at the heart of
Web services interoperability. WSDL is the description
language for Web services. Usually a WSDL document is
automatically generated by Web services framework tools (e.g.,
WASP WSDLCompiler) from the code written in a particular
programming language. Developers can use the WSDL document to
generate client-side stubs or proxies, which provide
convenient access to Web services. Thus the key to enabling
seamless Web services interoperability is the ability of one
Web services framework to consume the WSDL documents generated
by other frameworks. The WSDL interoperability effort is just
taking off. You can see further details at http://soap.systinet.net/interop/wsdl/index.html.
Although there are still some interoperability issues to be
resolved, the vendors are progressing very quickly, and we can
expect delivery on the promise of Web services
interoperability very soon.
How to not get trapped
The following subchapters give you some basic tips on how
to write interoperable Web services using today's Web services
frameworks. These tips may significantly ease your life as
well as the lives of other developers who will use your Web
services. Hopefully some of those tips will be outdated soon.
Keep your types simple - avoid advanced XML Schema
constructs
The XML Schema standard is very complex and difficult to
implement. Moreover, XML Schema processing is quite time
consuming, so many frameworks sacrifice full XML Schema
support for performance. Some advanced XML Schema constructs
(e.g., choice) are quite hard to express in a programming
language, and few Web services frameworks support them. So the
key success factor in Web services interoperability is to use
basic datatypes, such as primitive datatypes, arrays, and
structures. As a best practice, decompose the complex types in
your interfaces into simple and clean interfaces with basic
datatypes. Also avoid using specific techniques (e.g. INOUT
parameter passing) that aren't widely supported.
Provide XML Schema definitions for all your types
One common problem in today's frameworks is their limitied
ability to import multiple XML Schema and WSDL documents. It's
always a good idea to provide complete XML Schema and WSDL
definitions in one WSDL file rather than importing them from
various locations. Specifically, the Microsoft .NET framework
is sensitive to XML Schema import functions.
Example: When you find that you need to include
multiple WSDL and XML Schema files in a .NET service, you'll
find it easier to pass the XML Schema definitions together
with the WSDL definition to the commandline MS .NET WSDL
compiler rather than trying to import the schemas into the
WSDL file: wsdl.exe /language:CS /protocol:SOAP
MyService.wsdl MySchema.xsd JavaCollections.xsd
Multiple WSDL bindings
Some frameworks (e.g., MS .NET) generate multiple WSDL
bindings that allow you to access a Web service through
multiple protocols (e.g., HTTP GET, HTTP POST, and SOAP). The
client-side framework needs to know which binding to use, so
we need to specify further parameters (usually the fully
qualified name of the service and the name of the WSDL port)
when generating the programming language bindings from the
WSDL document.
Example: We will later run the
com.systinet.demos.weather.WeatherClient Java client
to access the MS .NET weather service that is available on
the XMethods
site. Notice that the client must use a slightly different
lookup method to specify a fully qualified service name (as a
javax.wsdl.QName) and WSDL port name: lookup("http://www.vbws.com/services/weatherretriever.asmx?WSDL",
new javax.wsdl.QName("http://tempuri.org/",
"WeatherRetriever"), "WeatherRetrieverSoap", WeatherRetrieverSoap.class)
Default document style with literal encoding
Some Web services frameworks, including MS .NET, generate,
by default, a document style Web service, using literal
encoding. Although the Web service uses document/literal, the
.NET framework makes the service appear to be RPC style to
.NET clients. This isn't necessarily so for other Web service
frameworks, and many users may find it difficult to access the
Web service using an RPC style client. So if you're writing an
RPC Web service, force your framework to generate the RPC
style WSDL.
Example: Use the [SoapRpcService] directive in
your MS .NET RPC Web service implementations:
<%@ WebService Language="C#" Class="MSNetStockService" %>
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Services.Description;
[SoapRpcService]
public class MSNetStockService {
[WebMethod]
public double getQuote(string symbol) {
if(symbol == "SUNW") {
return 10;
}
if(symbol == "BEAS") {
return 11;
}
if(symbol == "MSFT") {
return 50;
}
return 0;
}
}
Use unique SOAPActions for your methods
If you start your Web service development with a WSDL
document definition, consider using unique SOAPAction
attributes for all your methods in the WSDL binding. Some
frameworks rely on SOAPAction when routing SOAP messages to
the Web service implementation's methods.
Example: Consider the following WSDL binding
fragment for the previously mentioned MS .NET Web service:
<binding name="MSNetStockServiceSoap" type="tns:MSNetStockServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" />
<operation name="getQuote">
<soap:operation soapAction="http://tempuri.org/getQuote" style="rpc" />
<input>
<soap:body use="encoded" namespace="http://tempuri.org/"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body use="encoded" namespace="http://tempuri.org/"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>
Code Examples
Now we'll show a few Web services interoperability
examples. We will use a simple banking application that is
capable of keeping track of customers, accounts, and account
balances. We will also use the MS .NET weather service that is listed on
the XMethods site as a real-life example of
Internet Web service access, so you'll need to be connected to
the Internet while running this demo.
NOTE: If you haven't already downloaded the software
used to create the tutorial examples, please refer to the installation chapter in Part One. You'll also need to download the
demo
sources. We assume that you've unpacked this archive into
the c:\wasp_demo directory. All Java sources mentioned in the
tutorial examples can be found in the src subdirectory of the
unpacked demo
sources archive. They all reside in the com.systinet.demos
package. Similarly all scripts used in the demo are located in
the bin subdirectory. You don't need to download and use the
software to understand these articles, but we strongly
recommend it.
Accessing a Microsoft .NET service from Java
We'll start with the Java client/.NET service example. As
we mentioned earlier, we will access the weather service listed on the XMethods site.
Click on the link and try the service online using the MS .NET
invocation framework. Next look at the WSDL document for this service. You'll
notice that it defines three bindings (WeatherRetrieverSoap,
WeatherRetrieverHttpGet, and WeatherRetrieverHttpPost).
Now let's create a Java client for this service. Run the
run_weather_client.bat script that's located in the
bin directory of the demo
sources archive. Please note that we're using a
lookup method that specifices the fully qualified
service name and the WSDL port. This lookup method allows us
to specify that we want to use the SOAP binding. lookup("http://www.vbws.com/services/weatherretriever.asmx?WSDL",
new javax.wsdl.QName("http://tempuri.org/",
"WeatherRetriever"), "WeatherRetrieverSoap", WeatherRetrieverSoap.class)
Calling a Java service from a Microsoft .NET client
The opposite scenario is pretty straightforward. First
start the Web service runtime with the
startserver.bat command, and then compile and deploy
our simple Bank Web service by invoking the
deploy.bat command. Now we're ready to show three
different MS SOAP clients accessing our service.
NOTE: You need to use MS IE 6.0 or higher to run
this demo.
First we will run a MS JavaScript SOAP Client.
Invoke the run_web_client.bat script. Specify an SSN
number (you can use 001-0001-01, 002-0002-02 or 003-0003-03),
and click the Get Accounts button, which populates
the accounts combobox. Choose an account in the combobox and
retrieve the account balance by clicking the Get
Balance button. Look at the JavaScript code in
src\msjsclient.html for further details. The code is
very self-explanatory.
NOTE: You'll need to download and install the MS SOAP Toolkit 2.0 in order to successfully
complete the next example. You'll also need MS Excel on your
machine.
Now let's see the same functionality accessed from
Microsoft Excel (using Visual Basic). Open the
src\Bank.xls spreadsheet and use the same steps
described in the previous example to navigate the application.
You can find the SOAP client code in the Visual Basic Editor
(Tools->Macro->Visual Basic Editor) in the Sheet1
module.
NOTE: You'll need to download and install the MS .NET Framework SDK to run the C# part of
this example
The last example demonstrates how to access our Java Web
service from a C# client. Run the run_csharp.bat
script to generate a C# static proxy from the service WSDL and
to compile and run the client application. This example is
going one step further than our previous examples in that it
passes a Transfer structure from C# to Java. The
previous examples pass only simple data types. Notice the
simple XML Schema definition of the Transfer type (it includes
the Balance element):
<xsd:schema targetNamespace="http://idoox.com/wasp/tools/java2wsdl/output/com/systinet/demos/bank/">
<xsd:complexType name="Transfer">
<xsd:sequence>
<xsd:element name="type" type="xsd:string"/>
<xsd:element name="accountNumberBeneficiary" type="xsd:string"/>
<xsd:element name="comment" type="xsd:string"/>
<xsd:element name="balance" type="ns0:Balance"/>
<xsd:element name="amount" type="xsd:double"/>
<xsd:element name="timestamp" type="xsd:dateTime"/>
<xsd:element name="accountNumber" type="xsd:string"/>
<xsd:element name="transferID" type="xsd:long"/>
<xsd:element name="commentBeneficiary" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Balance">
<xsd:sequence>
<xsd:element name="changed" type="xsd:dateTime"/>
<xsd:element name="transfer" type="ns0:Transfer"/>
<xsd:element name="comment" type="xsd:string"/>
<xsd:element name="balance" type="xsd:double"/>
<xsd:element name="accountNumber" type="xsd:string"/>
<xsd:element name="transferID" type="xsd:long"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
The .NET WSDL compiler will generate the appropriate
structures in C#. See the stub in the
src/ms/JavaService.cs for more details. Run the Java
client by invoking the run_java_client.bat script,
and you'll notice that it does the same thing.
NOTE: Both clients share the same Web service, and
both clients make withdrawals from the same account. So if you
run the demo multiple times, you can easily get out of funds.
Then you'll get the TransferProcessingException that
says something like 'Insufficient funds'. One nice thing
you'll notice is that C# is able to transparently rethrow the
exception with the same message on the client side. Restart
the Web services runtime using the startserver.bat to
renew your funds.
Review
In this part of the Web services tutorial we learned how to
write interoperable Web services. All examples were focused on
the integration of MS .NET and Java. We demonstrated that Web
services technology gives us the opportunity to pick the best
technology for each particular piece of our system.
Specifically, we can use the MS .NET framework on the client
side to enable easy integration with common Office
technologies, while still using the powerful and portable Java
model for scalable server-side applications.
As we've seen today, a typical Web service application can
easily support heterogeneous operations. One thing we haven't
addressed yet, though, is heterogeneous Web service security.
Next time we'll show how you to manage heterogeneous security
using single sign-on. See you then.
PRINTER
FRIENDLY VERSION
|