O'Reilly logo

Java Web Services: Up and Running by Martin Kalin

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

A First Example

The first example is a SOAP-based web service in Java and clients in Perl, Ruby, and Java. The Java-based web service consists of an interface and an implementation.

The Service Endpoint Interface and Service Implementation Bean

The first web service in Java, like almost all of the others in this book, can be compiled and deployed using core Java SE 6 (Java Standard Edition 6) or greater without any additional software. All of the libraries required to compile, execute, and consume web services are available in core Java 6, which supports JAX-WS (Java API for XML-Web Services). JAX-WS supports SOAP-based and REST-style services. JAX-WS is commonly shortened to JWS for Java Web Services. The current version of JAX-WS is 2.x, which is a bit confusing because version 1.x has a different label: JAX-RPC. JAX-WS preserves but also significantly extends the capabilities of JAX-RPC.

A SOAP-based web service could be implemented as a single Java class but, following best practices, there should be an interface that declares the methods, which are the web service operations, and an implementation, which defines the methods declared in the interface. The interface is called the SEI: Service Endpoint Interface. The implementation is called the SIB: Service Implementation Bean. The SIB can be either a POJO or a Stateless Session EJB (Enterprise Java Bean). Chapter 6, which deals with the GlassFish Application Server, shows how to implement a web service as an EJB. Until then, the SOAP-based web services will be implemented as POJOs, that is, as instances of regular Java classes. These web services will be published using library classes that come with core Java 6 and, a bit later, with standalone Tomcat and GlassFish.

Example 1-1 is the SEI for a web service that returns the current time as either a string or as the elapsed milliseconds from the Unix epoch, midnight January 1, 1970 GMT.

Example 1-1. Service Endpoint Interface for the TimeServer

package ch01.ts;  // time server

import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

/**
 *  The annotation @WebService signals that this is the
 *  SEI (Service Endpoint Interface). @WebMethod signals 
 *  that each method is a service operation.
 *
 *  The @SOAPBinding annotation impacts the under-the-hood
 *  construction of the service contract, the WSDL
 *  (Web Services Definition Language) document. Style.RPC
 *  simplifies the contract and makes deployment easier.
*/
@WebService
@SOAPBinding(style = Style.RPC) // more on this later
public interface TimeServer {
    @WebMethod String getTimeAsString();
    @WebMethod long getTimeAsElapsed();
}

Example 1-2 is the SIB, which implements the SEI.

Example 1-2. Service Implementation Bean for the TimeServer

package ch01.ts; 

import java.util.Date;
import javax.jws.WebService;

/**
 *  The @WebService property endpointInterface links the
 *  SIB (this class) to the SEI (ch01.ts.TimeServer).
 *  Note that the method implementations are not annotated
 *  as @WebMethods.
*/
@WebService(endpointInterface = "ch01.ts.TimeServer")
public class TimeServerImpl implements TimeServer {
    public String getTimeAsString() { return new Date().toString(); }
    public long getTimeAsElapsed() { return new Date().getTime(); }
}

The two files are compiled in the usual way from the current working directory, which in this case is immediately above the subdirectory ch01. The symbol % represents the command prompt:

% javac ch01/ts/*.java

A Java Application to Publish the Web Service

Once the SEI and SIB have been compiled, the web service is ready to be published. In full production mode, a Java Application Server such as BEA WebLogic, GlassFish, JBoss, or WebSphere might be used; but in development and even light production mode, a simple Java application can be used. Example 1-3 is the publisher application for the TimeServer service.

Example 1-3. Endpoint publisher for the TimeServer

package ch01.ts;

import javax.xml.ws.Endpoint;

/**
 * This application publishes the web service whose
 * SIB is ch01.ts.TimeServerImpl. For now, the 
 * service is published at network address 127.0.0.1.,
 * which is localhost, and at port number 9876, as this
 * port is likely available on any desktop machine. The
 * publication path is /ts, an arbitrary name.
 *
 * The Endpoint class has an overloaded publish method.
 * In this two-argument version, the first argument is the
 * publication URL as a string and the second argument is
 * an instance of the service SIB, in this case
 * ch01.ts.TimeServerImpl.
 *
 * The application runs indefinitely, awaiting service requests.
 * It needs to be terminated at the command prompt with control-C
 * or the equivalent.
 *
 * Once the applicatation is started, open a browser to the URL
 *
 *     http://127.0.0.1:9876/ts?wsdl
 *
 * to view the service contract, the WSDL document. This is an
 * easy test to determine whether the service has deployed
 * successfully. If the test succeeds, a client then can be
 * executed against the service.
*/
public class TimeServerPublisher {
    public static void main(String[ ] args) {
      // 1st argument is the publication URL
      // 2nd argument is an SIB instance
      Endpoint.publish("http://127.0.0.1:9876/ts", new TimeServerImpl());
    }
}

Once compiled, the publisher can be executed in the usual way:

% java ch01.ts.TimeServerPublisher

How the Endpoint Publisher Handles Requests

Out of the box, the Endpoint publisher handles one client request at a time. This is fine for getting web services up and running in development mode. However, if the processing of a given request should hang, then all other client requests are effectively blocked. An example at the end of this chapter shows how Endpoint can handle requests concurrently so that one hung request does not block the others.

Testing the Web Service with a Browser

We can test the deployed service by opening a browser and viewing the WSDL (Web Service Definition Language) document, which is an automatically generated service contract. (WSDL is pronounced “whiz dull.”) The browser is opened to a URL that has two parts. The first part is the URL published in the Java TimeServerPublisher application: http://127.0.0.1:9876/ts. Appended to this URL is the query string ?wsdl in upper-, lower-, or mixed case. The result is http://127.0.0.1:9876/ts?wsdl. Example 1-4 is the WSDL document that the browser displays.

Example 1-4. WSDL document for the TimeServer service

<?xml version="1.0" encoding="UTF-8"?>
<definitions 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:tns="http://ts.ch01/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    targetNamespace="http://ts.ch01/" 
    name="TimeServerImplService">
  <types></types>

  <message name="getTimeAsString"></message>
  <message name="getTimeAsStringResponse">
    <part name="return" type="xsd:string"></part>
  </message>
  <message name="getTimeAsElapsed"></message>
  <message name="getTimeAsElapsedResponse">
    <part name="return" type="xsd:long"></part>
  </message>
  
  <portType name="TimeServer">
    <operation name="getTimeAsString" parameterOrder="">
      <input message="tns:getTimeAsString"></input>
      <output message="tns:getTimeAsStringResponse"></output>
    </operation>
    <operation name="getTimeAsElapsed" parameterOrder="">
      <input message="tns:getTimeAsElapsed"></input>
      <output message="tns:getTimeAsElapsedResponse"></output>
    </operation>
  </portType>

  <binding name="TimeServerImplPortBinding" type="tns:TimeServer">
    <soap:binding style="rpc" 
                  transport="http://schemas.xmlsoap.org/soap/http">
    </soap:binding>
    <operation name="getTimeAsString">
      <soap:operation soapAction=""></soap:operation>
      <input>
        <soap:body use="literal" namespace="http://ts.ch01/"></soap:body>
      </input>
      <output>
        <soap:body use="literal" namespace="http://ts.ch01/"></soap:body>
      </output>
    </operation>
    <operation name="getTimeAsElapsed">
      <soap:operation soapAction=""></soap:operation>
      <input>
        <soap:body use="literal" namespace="http://ts.ch01/"></soap:body>
      </input>
      <output>
        <soap:body use="literal" namespace="http://ts.ch01/"></soap:body>
      </output>
    </operation>
  </binding>

  <service name="TimeServerImplService">
      <port name="TimeServerImplPort" binding="tns:TimeServerImplPortBinding">
      <soap:address location="http://localhost:9876/ts"></soap:address>
    </port>
  </service>
</definitions>

Chapter 2 examines the WSDL in detail and introduces Java utilities associated with the service contract. For now, two sections of the WSDL (both shown in bold) deserve a quick look. The portType section, near the top, groups the operations that the web service delivers, in this case the operations getTimeAsString and getTimeAsElapsed, which are the two Java methods declared in the SEI and implemented in the SIB. The WSDL portType is like a Java interface in that the portType presents the service operations abstractly but provides no implementation detail. Each operation in the web service consists of an input and an output message, where input means input for the web service. At runtime, each message is a SOAP document. The other WSDL section of interest is the last, the service section, and in particular the service location, in this case the URL http://localhost:9876/ts. The URL is called the service endpoint and it informs clients about where the service can be accessed.

The WSDL document is useful for both creating and executing clients against a web service. Various languages have utilities for generating client-support code from a WSDL. The core Java utility is now called wsimport but the earlier names wsdl2java and java2wsdl were more descriptive. At runtime, a client can consume the WSDL document associated with a web service in order to get critical information about the data types associated with the operations bundled in the service. For example, a client could determine from our first WSDL that the operation getTimeAsElapsed returns an integer and expects no arguments.

The WSDL also can be accessed with various utilities such as curl. For example, the command:

% curl http://localhost:9876/ts?wsdl

also displays the WSDL.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required