35.3. Annotate SEI for JAX-WS

Overview

To use the JAX-WS frontend, an SEI must be annotated using standardised JAX-WS annotations. The annotations signal to the Web services tooling that the SEI uses JAX-WS and the annotations are also used to customize the mapping from Java to WSDL. Here we only cover the most basic annotations—for complete details of JAX-WS annotations, see Developing Applications Using JAX-WS from the Apache CXF library.
Note
It sometimes makes sense also to annotate the service implementation class (the class that implements the SEI)—for example, if you want to associate an implementation class with a specific WSDL serviceName and portName (there can be more than one implementation of a given SEI).

Minimal annotation

The minimal annotation required for an SEI using the JAX-WS frontend is to prefix the interface declaration with @WebService. For example, the CustomerService SEI could be minimally annotated as follows:
// Java
package com.fusesource.demo.wsdl.customerservice;

import javax.jws.WebService;
 
@WebService
public interface CustomerService {
  ...
}
If you run the Java-to-WSDL utility on this interface, it will generate a complete WSDL contract using the standard default style of code conversion.

@WebService annotation

Although it is sufficient to specify the @WebService annotation without any attributes, it is usually better to specify some attributes to provide a more descriptive WSDL service name and WSDL port name. You will also usually want to specify the XML target namespace. For this, you can specify the following optional attributes of the @WebService annotation:
name
Specifies the name of the WSDL contract (appearing in the wsdl:definitions element).
serviceName
Specifies the name of the WSDL service (a SOAP service is defined by default in the generated contract).
portName
Specifies the name of the WSDL port (a SOAP/HTTP port is defined by default in the generated contract).
targetNamespace
The XML schema namespace that is used, by default, to qualify the elements and types defined in the contract.

@WebParam annotation

You can add the @WebParam annotation to method arguments in the SEI. The @WebParam annotation is optional, but there are a couple of good reasons for adding it:
  • By default, JAX-WS maps Java arguments to parameters with names like arg0, ..., argN. Messages are much easier to read, however, when the parameters have meaningful names.
  • It is a good idea to define parameter elements without a namespace. This makes the XML encoding of requests and responses more compact.
  • To enable support for WSDL OUT and INOUT parameters.
You can add @WebParam annotations with the following attributes:
name
Specifies the mapped name of the parameter.
targetNamespace
Specifies the namespace of the mapped parameter. Set this to a blank string for a more compact XML encoding.
mode
Can have one of the following values:
  • WebParam.Mode.IN(default) parameter is passed from client to service (in request).
  • WebParam.Mode.INOUT—parameter is passed from client to service (request) and from the service back to the client (in reply).
  • WebParam.Mode.OUT—parameter is passed from service back to the client (in reply).

OUT and INOUT parameters

In WSDL, OUT and INOUT parameters represent values that can be sent from the service back to the client (where the INOUT parameter is sent in both directions).
In Java syntax, the only value that can ordinarily be returned from a method is the method's return value. In order to support OUT or INOUT parameters in Java (which are effectively like additional return values), you must:
  • Declare the corresponding Java argument using a javax.xml.ws.Holder<ParamType> type, where ParamType is the type of the parameter you want to send.
  • Annotate the Java argument with @WebParam, setting either mode = WebParam.Mode.OUT or mode = WebParam.Mode.INOUT.

Annotated CustomerService SEI

The following example shows the CustomerService SEI after it has been annotated. Many other annotations are possible, but this level of annotation is usually adequate for a WSDL-first project.
// Java
package com.fusesource.demo.wsdl.customerservice;

import javax.jws.WebParam;
import javax.jws.WebService;
 
@WebService(
  targetNamespace = "http://demo.fusesource.com/wsdl/CustomerService/",
  name = "CustomerService",
  serviceName = "CustomerService",
  portName = "SOAPOverHTTP"
)
public interface CustomerService {

    public com.fusesource.demo.customer.Customer lookupCustomer(
 @WebParam(name = "customerId", targetNamespace = "")
        java.lang.String customerId
    );

    public void updateCustomer(
 @WebParam(name = "cust", targetNamespace = "")
        com.fusesource.demo.customer.Customer cust
    );

    public void getCustomerStatus(
 @WebParam(name = "customerId", targetNamespace = "")
        java.lang.String customerId,
 @WebParam(mode = WebParam.Mode.OUT, name = "status", targetNamespace = "")
        javax.xml.ws.Holder<java.lang.String> status,
 @WebParam(mode = WebParam.Mode.OUT, name = "statusMessage", targetNamespace = "")
        javax.xml.ws.Holder<java.lang.String> statusMessage
    );
}