34.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, whereParamType
is the type of the parameter you want to send. - Annotate the Java argument with
@WebParam
, setting eithermode = WebParam.Mode.OUT
ormode = 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 ); }