Web services is a big, fast-moving topic and the subject of many other fine O’Reilly books. However, because we have already covered so many of the basic networking concepts (and we’ll cover XML in detail in Chapter 24), we would be shirking our duties if we didn’t provide an introduction to this important area of application development. We conclude this chapter on client-side web communications with a small example of invoking a web service.
In contrast to regular web applications intended to be visited by web browsers, web services are application-level APIs intended to be invoked by other application components. The primary distinction from other types of interapplication communications mechanisms is that they use web standards and XML to maximize cross-platform interoperability. We will leave the analysis of when exactly this is important and the cost versus benefits tradeoffs out of our discussion here. But the value in this idea should be evident from the explosion of web-based business applications in the past few years. Web services allow web-based applications to provide well-defined, cross-platform interfaces for other web-based applications.
The term web services means different things to different people and has spawned many (too many) new standards in recent years. In fact, there are so many web service standards named with the prefix “WS” now that they are collectively known as “WS-*” (affectionately referred to as WS “splat” or WS “death star”). However, the original concept is simple: web services take the ubiquitous, universally understood, and easily implemented HTTP transaction and marry it with XML to define a standard for invoking application services over the Web. The process is a type of remote procedure call in which HTTP plays its traditional role as the basic communication provider and XML adds a “business envelope” in which structured data is passed. This RPC-style web service interaction defines both the basic structure of an invocation request and also a set of XML encodings for marshaling the primitive data types, allowing data parameters and results to be exchanged in a truly cross-platform way. In contrast, another form of web services—termed “document style”—places more emphasis on the exchange of application-specific XML documents than on RPC-style data marshaling and unmarshaling. We will concentrate on RPC-style web services because they currently provide the tightest coupling to Java.
A key component of web services technology is the Web Services Description Language (WSDL). Using this standard, a structured XML document describes a web service, the individual functions (methods) it offers, and the XML data types for their respective arguments and return values. WSDL is a type of interface definition language (IDL) and plays that role for web services. However, a WSDL document can also specify the service location and other features that are not traditionally part of the service definitely.
For the client-side web services developer, the WSDL document describing a service contains all of the information needed to generate the client-side code used to invoke the service from Java or any other language. As we’ll see in our example, it is not even necessary to have an understanding of WSDL to use the service. One can simply generate the client-side interfaces and use them from a Java language viewpoint. We’ll see in Chapter 15 that we can generate the WSDL document for a new service directly from our own Java code as well.
The Java JAX-WS Java API for XML Web Services comes bundled with Java 6 and later and contains all of the tools necessary to use, create, and work with web services in Java. It’s even possible to deploy web services for testing in simple scenarios using out-of-the-box tools. As you might imagine, Java web services make extensive use of the JAXP APIs for working with XML. JAX-WS adds the classes necessary for remote calls, as well as the development-time wsimport and wsgen tools. The wsimport tool reads a WSDL description file and generates the required Java interface and implementation classes to invoke it. The wsgen tool reads Java code containing web service annotations and can generate WSDL and other deployment-related files.
There are many application servers that provide their own mechanisms for deploying web services and generating client-side code. The Apache CXF project is another popular Java web services alternative that can work with JAX-WS and other standards.
This example shows just how easy it is to use a web service from client-side code. We’re going to create a client for a web-based weather lookup service. The service accepts a U.S. zip code as an argument and returns the city, state, and weather conditions as a result. Please note that the server-side component of this example is hosted by a company called cdyne.com, which is a professional web services provider. Because this is a third-party site, we cannot guarantee that it will remain active. If for any reason this service disappears, don’t fret—we’ll build our own example in Chapter 15, where we implement a simple web service ourselves.
All that we need to get started is the web service WSDL description file. You can view the weather service at the WSDL website. It’s an XML file that defines a set of operations and data types for arguments and results. The file is not intended to be human readable, and should make more sense after we discuss XML in Chapter 24.
When wsimport completes, you should find a
new directory tree named com/cdyne/ws/weatherws
that contains compiled Java classes for the temperature service client
interface and an implementation. The wsimport command has many useful
options: you may wish to use the
-keep option to retain the generated source
code for the client classes so that you can store the source with your
application. There is also a
option that lets you override the generated Java package name.
The generated code contains a class called
Weather that represents the overall service
and an interface called
that represents various ports or groups of methods
on the service, among other implementation classes. (The “port” is WSDL
terminology for a group of functions on a web service.) If you retain
the soure code (with
-keep) and take
a look at it, you’ll see that the generated classes use Java annotations
to identify the service elements. The
Weather class is marked with
WeatherSoap interface is marked
Furthermore, the methods of the
WeatherSoap interface are marked with
annotations add metadata to the code to identify the service and capture
the information needed from the WSDL to map to the service XML. We’ll
discuss web service annotations more when we build and deploy the server
side of a web service in the next chapter. We’ll also see annotations
used in analogous ways when we discuss XML binding with JAXB in Chapter 24.
Our client application can now use these classes to invoke the service. The following code looks up the current weather in the 63132 zip code:
"%s, %s : %s : Temperature: %s, Wind: %s"
Remember that you need to either add the compiled service classes to your classpath or compile the generated source files along with the example code. If you run it, you should see output like the following. Note that although this service has returned the values as strings, in general, web service bindings to Java would allow elements like the temperature to be returned as numeric types.