Chapter 16. Web Services [DRAFT(1.0)]

Table of Contents

16.1. J2EE Web Services Concepts & Features
16.1.1. Client, WSDL, and Server
16.1.2. WSDL Styles: Literal, Encoded, RPC, Document, and Wrapped
16.1.3. Services and Ports
16.1.4. Namespaces
16.1.5. The JAX-RPC Mapping File
16.2. A Sample Web Service
16.2.1. The Service Endpoint Interface
16.2.2. The WSDL
16.2.3. The Client Service Interface
16.2.4. The JAX-RPC Mapping File
16.3. Serving Web Services from Geronimo
16.3.1. The webservices.xml Configuration File
16.3.2. Servlet-based Web Services
16.3.3. Session Bean based Web Services
16.4. Web Services Clients in Geronimo
16.4.1. Adding a Web Service Reference to a J2EE Component
16.4.2. Customizing the Service Reference
16.4.3. Authenticating to a Web Service
16.4.4. Packaging and Deployment
16.4.5. Accessing the Service

J2EE 1.4 includes several options for providing or consuming web services:

In addition, J2EE 1.4 includes the full suite of Java web services APIs, so custom application logic may manually create or process SOAP messages.

Generally speaking, a number of files are required in order to interface Java code with Web Services:

While many products offer shortcuts to create web services, Geronimo supports only portable J2EE web services. On the up side, this means that web services applications developed for Geronimo should run in any application server. On the down side, it means that there are no shortcuts; there is a somewhat painful amount of configuration necessary to get portable J2EE web services running. This chapter describes techniques for building J2EE web services clients and servers, and deploying them in Geronimo. It does not cover the detailed syntax for standard J2EE web service configuration files, but does provide comprehensive examples to work from.

[Note]Note

The J2EE web services features in J2EE 1.4 are based on JAX-RPC and a variety of configuration files, which all together is somewhat cumbersome and difficult to deal with. The web services features in Java EE 5 use the more friendly JAX-WS API, as well as leveraging annotations to ease configuration. It's hard not to look forward to Java EE, but Geronimo 1.x only supports J2EE 1.4.

16.1. J2EE Web Services Concepts & Features

There are several important things to understand about web services, and the J2EE implementation of web services.

16.1.1. Client, WSDL, and Server

Web services are ultimately defined by WSDL files. Both the client and server must agree on the same WSDL in order to communicate. However, it is not always convenient to write WSDL from scratch.

To speed development or expose existing application functionality as web services, it may be most convenient to start with a Java interface representing the web service (which either a client or a server can use), and then use a tool to generate WSDL from that. One down side of this approach is, it tends to generate Java-looking WSDL, with message or operation names starting with "get" and using a lower-case first letter, and so on. This isn't terribly onerous, but a more agnostic web service might avoid some of those idiosyncrasies.

[Warning]Warning

A bigger problem with starting from a Java interface is that there are many tools to generate WSDL from that, and they often default to non-portable styles of output. For more discussion of WSDL styles, see the next section -- and be prepared to configure any tools to produce better output.

To develop the most portable web services, it's often better to start by writing the WSDL, and then generate the necessary Java interfaces from that (or use the JAX-RPC mapping file to map the portable WSDL to existing Java interfaces). It's not always as easy to write WSDL from scratch, but it's certainly easier to produce more ideal WSDL that way.

Geronimo simply works with the interfaces, WSDL, and mapping files, so it doesn't matter to Geronimo which was created first, and they must all be present for a service (or service client) to be deployed.

16.1.2. WSDL Styles: Literal, Encoded, RPC, Document, and Wrapped

Generally speaking, there are 5 possible styles of WSDL and SOAP that may be used for any given web service: RPC/Encoded, RPC/Literal, Document/Encoded, Document/Literal, and Document/Literal wrapped. Note that the RPC vs. Document distinction only affects the construction of SOAP messages for a given request/response interface; it does not have any implications for how synchronous or fine-grained the web services API is (though the terms document and RPC are unfortunately used to describe that as well). In other words, it's still possible to represent a largely RPC-style API with Document-style WSDL, or to represent a largely document-style API with RPC-style WSDL.

A major constraint on this decision is the fact that the Web Services Interoperability organization (WS-I) has standardized on the Literal styles (as opposed to the Encoded styles), which means that those are the most likely to be portable across languages and web services stacks, and should always be used where possible..

The next major constraint is that Document-style WSDL cannot effectively represent overloaded operations (two operations with the same name but different argument types).

Finally, the Document/Literal wrapped has additional flexibility in mapping arguments and return types compared to other options, including better support for arrays.

Add that all up, and the formula for the best WSDL typically looks like this:

  1. If there are no overloaded methods (or overloaded Java methods can be mapped to distinctly-named WSDL operations), go with Document/Literal wrapped.

  2. Otherwise, go with RPC/Literal.

  3. Only look at the other styles if you specifically need something they offer over these two.

[Tip]Tip

For a lengthier discussion of the various WSDL styles and their advantages and disadvantages, see the IBM DeveloperWorks article Which style of WSDL should I use?

Once again, Geronimo can take any style so long as you successfully create WSDL, interfaces, and a JAX-RPC mapping file, but sticking with Document/Literal wrapped can make it a lot easier to get there.

16.1.3. Services and Ports

According to the standard JAX-RPC programming model, a client first acquires a Service reference, and from that Service, gets a Port. Somewhat confusingly, the Port is what you normally think of as a web service client -- the interface that is the Java representation of the web service API. For example, if you deploy a Stateless Session Bean as a web service, the Service Endpoint Interface for the session bean defines the methods available for web services clients. But to that client, that interface is known as the Port, not the Service.

This make a little more sense looking at the WSDL, where a Port defines available operations, and a Service binds the port to a particular URL and SOAP format. Still, the word "service" is clearly overused.

Example 16.1. JAX-RPC Client Code

A typical JAX-RPC client gets first a service and then a port. A J2EE client gets the service from JNDI, so the code might look like this:

TestService service = (TestService)
               new InitialContext().lookup("java:comp/env/...");
Test port1 = service.getTestPort();
port1.someBusinessMethod();
Test port2 = service.getTestPort(new URL("http://..."));
port2.someBusinessMethod();

16.1.4. Namespaces

Web services rely heavily on XML namespaces, where all the service components in the WSDL are associated with a namespace, certain elements in the message payload may be associated with a namespace, and the JAX-RPC mapping file must identify elements in the WSDL file using their namespace.

The first thing to realize when creating a web service is that the namespace is essentially arbitrary. Often namespaces are identified by http://... URLs, but in fact they must only be URIs which can be much more free-form. For example "aaron-stuff" is a valid namespace. If you do use an HTTP URL, it does not actually need to point to anything valid, and specifically, it does not need to point to a location where the web service or WSDL can be found.

One of the trickier parts of the JAX-RPC mapping file is figuring out which values need to be prefixed by a namespace identifier and which don't. The examples later in this chapter may help.

16.1.5. The JAX-RPC Mapping File

One of the most unfortunate aspects of J2EE Web Services is that they rely on a JAX-RPC mapping file to link the Java client or server interfaces to individual components in the WSDL file. This is unfortunate because there are two styles of JAX-RPC mapping file content, lightweight and heavyweight, and lightweight files can only be used in strictly limited scenarios (among the many restrictions, only for RPC/Encoded WSDL, with the simplest arguments and return types). This means that heavyweight JAX-RPC mapping files are nearly always needed, and they are extremely complex and error-prone.

Where possible, the best case is to use a tool to generate either the WSDL from the Java interfaces or the Java interfaces from the WSDL, and generate a JAX-RPC mapping file at the same time. Geronimo does not ship with such a tool, but there are some out there. Unfortunately the Apache Axis tools do not generate JAX-RPC mapping files, but the Sun Java Web Services Developer Pack tools can.

[Tip]Tip

Remember to configure any tool to produce Document/Literal wrapped output (often simply by setting a flag or configuration option to enable "wrapped").