Professional Documents
Culture Documents
Annotations
Bruce Tiffany
Advisory Software Engineer, Web Services for WebSphere Functional Test
IBM
Dustin Amrhein
Staff Software Engineer, Web Services for WebSphere Application Server Development
IBM
Jeff Barrett
Advisory Software Engineer, Web Services for WebSphere Application Server
Development
IBM
November, 2007
This article describes how you can use Java™ annotations in your source code to develop
and deploy a Web service endpoint for the WebSphere® Application Server V6.1 Web
Services Feature Pack.
Introduction
The WebSphere Application Server V6.1 Feature Pack for Web Services allows
developers to create and deploy Web services with the Java API for XML Web Services
(JAX-WS) programming model. JAX-WS simplifies the creation of Web services from
existing Java source code.
In this article, you’ll learn how to use Java annotations to develop and deploy a Web
service endpoint, how the annotations affect the resulting WSDL, and how to develop
and deploy simple applications with command line tools.
• Some Java data types don’t map symmetrically to XML and back. Selecting
different types or closely examining Java Architecture for XML Binding (JAXB)
2.0 (used by Java API for XML Web Services (JAX-WS) for XML-to-Java
mapping) may help. When you develop services starting from WSDL, you can
customize the schema more flexibility in JAXB type mapping.
• Data, not code, is exchanged between the client and service. Your design should
emphasize data exchange, not behavior exchange. Subtleties of polymorphism
and inheritance can be challenging to preserve over the wire.
• Methods that depend on overloading or case sensitivity are more likely to need
customization.
package example1;
import javax.jws.WebService;
@WebService
public class HelloWorld{
public String sayHello(String input){
return("Hello, " + input);
}
}
In this example, the @WebService annotation declares the class as a Web service. There
is no interface. The run-time produces the WSDL and related schema files. The
deployment tools generate other necessary classes. The only thing you need to supply is
the implementation class and some deployment information.
The deployment process is decsribed later in this article. The service and client for this
example are included in the sample code provided for download with this article.
While the run-time generates a WSDL 1.1 file, you may want to supply the WSDL file
with the service. For Web service implementations that use complex schema types there
may be a tangible performance benefit when supplying the WSDL document. If you
supply a WSDL file, the run-time checks that the implementation class operations,
parameters, and bindings match those in the WSDL.
You can use the JAX-WS wsgen tool with the –wsdl flag to create a WSDL file. Edit the
WSDL file to add your own customizations, then package the WSDL with your
application.
To include WSDL and use an interface in the example above, you’d need to change the
annotation to something like:
@WebService(wsdlLocation=”WEB-INF/wsdl/HelloWorldService.wsdl”,
endpointInterface=”simple.HelloWorldIf”)
If you use an endpoint interface, it too must have an @WebService annotation. This is
shown in Example 2 in the downloadable samples.
There are four additional parameters on the @WebService annotation:
• The name attribute is the name of the service.
• The serviceName attribute maps to the <wsdl:service> element.
• The portName attribute maps to the <wsdl:port> element.
• The targetNamespace element maps to the target namespace of the WSDL
document.
@WebService(name=”HelloWorld”, serviceName=”HelloWorldService”,
portName=”HelloWorldPort”, targetNamespace=”http://com.myexample”)
• If you used an endpoint interface, you cannot use this annotation in the
implementation class.
• If there is no endpoint interface, and the annotation is not present in the class, all
public methods are exposed.
• If the annotation is used only to exclude methods from the service, only the
annotated methods are affected.
• If the annotation is present anywhere in the class in any other form, only the
annotated methods are exposed and all un-annotated methods are excluded.
You may want to use this annotation to customize method names to adhere to a supplied
WSDL contract, prevent methods from being exposed by the implementation, and
provide an action attribute for the method, which is useful when the service exposes a
SOAP binding.
If your implementation contains a public method that should not be accessible through
the service, you can block it with the exclude parameter:
@WebMethod(exclude=”true”).
For example, the service for the class below exposes operations a, b and c.
package simple;
import javax.jws.WebService;
@WebService
public class HelloWorld3{
public String a(String input){ return("Hello, " + input); }
public String b(String input){ return("Hello, " + input); }
public String c(String input){ return("Hello, " + input); }
You can customize the name of the operation in the WSDL as shown below:
@WebMethod(operationName=addInt)
public int add(int a, int b)
@WebMethod()
public int add(int a, float b)
The annotation shown above changes the WSDL operation name from add to addInt.
This can be useful in resolving problems due to WSDL limitations with respect to
operation overloading or case-sensitive names.
Finally, you can customize the WSDL soap action attribute with the action
parameter; for example: @WebMethod(action=”doSomething”). Actions are placed in
the request message header, as shown below. The use of actions is often application-
specific.
<binding>
<soap:binding />
<operation name=”add”>
<soap:operation action=”doSomething”>
…
</soap:operation>
…
</operation>
…
</binding>
The caller gets an exception if the JAX-WS server run-time doesn’t acknowledge the
caller’s inbound request. Once acknowledgement is received, the call returns, and the
operation runs asynchronously. A subsequent failure is not detectable by the caller.
JAX-WS also provides ways to implement asynchronous calls that do return data, but
those are not discussed in this article.
The code snippet below shows a simple class that invokes a time-consuming operation
using @Oneway to avoid waiting for completion.
package simple;
import javax.jws.WebService;
import javax.jws.Oneway
@WebService
public class Sample5{
@Oneway
public void recordSale(String sku, int quantity){ // lengthy
operation here. }
}
Example 3 in the downloadable samples shows the use of the @WebMethod and @Oneway
annotations.
This annotation is not usually required when starting from Java, but you can use it to
customize the namespace or element name of the fault element in the WSDL if
needed.
Because of the way Java exceptions are mapped into fault data, exception names and
methods usually differ between the service and the client. When an exception is
converted to a fault and sent to the client, a bean is created containing some of the fields
from the service-side exception. The bean is then wrapped in another exception class for
the client-side. Here are some of the differences:
If you need to pass more information back to the client than just the exception message,
you can add additional bean getter and setter methods to the server-side exception,
and the getters can be used at the client.
JAX-WS wraps requests, responses, and faults in JAXB beans. You can use these
annotations to customize the name, target namespace, and class name of the generated
JAXB beans and to resolve conflicts if needed. You can resolve conflicts by providing
custom values for the name, target namespace, or class name of the generated JAXB
beans.
As in the earlier example of compensating for an overloaded method, you can change the
bean className, as well as the operationName so the service works correctly.
@WebMethod()
public int add(int a, float b)
@WebServiceProvider
public class HelloProvider implements Provider<SOAPMessage>{
public SOAPMessage invoke(SOAPMessage requestMessage) {…}
}
The @WebServiceProvider annotation has the same parameters (with the same
correspondence to WSDL) as the @WebService annotation, with the exception of the
endpointInterface and name parameters.
This file causes the service to be deployed with defaults inferred from the annotations. In
this convenient form, the same file can be used for any service. For more information on
the customization supported, see Customizing URL patterns in the web.xml file for JAX-
WS applications in the WebSphere Application Server Information Center.
5. Deploy the WAR file and start the application through the Application Server
administrative console as you would any other WAR file:
• Select Applications =>Install new application.
• Enter the path to your WAR file.
• Enter a context root (the value used was example1.
• Click Next on each page, then click Finish, then Save.
• Select the checkbox to the left of the application and click Start.
Note that the WSDL file was generated during deployment. You can retrieve it by
appending ?wsdl to the URL.
Develop and deploy a client
1. Run \AppServer\bin\wsimport against the wsdl file to produce the necessary
generated classes, as shown:
C:\tmp\simple\client>wsimport -s .
http://localhost:9080/simple/HelloWorldService/?wsdl
package simple;
import javax.jws.*;
public class HelloWorldClient{
public static void main(String [] args){
HelloWorld myPort =
new HelloWorldService().getHelloWorldPort();
System.out.println("invoking service");
String result = myPort.sayHello("hi server");
System.out.println("service returned: " + result); }
}
C:\tmp\simple\client>java -cp
client_classpath samples.example1.HelloWorldClient
invoking service
service returned: Hello, hi server
Note that in the example above, the URL of the WSDL file is fixed in the client-side
classes that were generated by the wsimport tool. With a minor change, you can supply
the URL as an argument to the client, as shown below:
…
// replace line 5 in prior example
System.out.println("using supplied wsdl url: "+ args[0]);
try{
url =new URL(args[0]);
} catch( Exception e){
e.printStackTrace();
}
QName qn = new QName("http://example1.samples/", "HelloWorldService");
myPort = new HelloWorldService(url, qn ).getHelloWorldPort();
…
You can use this same general deployment process for all the samples in this article.
package simple;
import javax.jws.WebService;
@WebService
public class HelloWorld extends HelloUser {
package simple;
public class HelloUser {
In this example it seems obvious that the Web service endpoint represented by the
HelloWorld class would expose two methods: sayHello and sayHelloUser. However,
this is not the case. The Web service endpoint actually exposes a single method:
sayHello. In order for a JAX-WS Web service implementation class to inherit methods
from its super class, the super class must also be annotated with the @WebService
method. In the example below, the HelloWorld Web service exposes the sayHello and
sayHelloUser methods.
package simple;
import javax.jws.WebService;
@WebService
public class HelloWorld extends HelloUser {
package simple;
import javax.jws.WebService;
@WebService
public class HelloUser {
JSR-181 also provides users with a mechanism to prevent an inherited method from
being exposed as a Web service operation on the child class implementation. Consider
the following implementation and super class:
package simple;
import javax.jws.WebService;
@WebService
public class HelloWorld extends HelloUser {
package simple;
import javax.jws.WebService;
@WebService
public class HelloUser {
In this example, the Web service implementation class HelloWorld exposes three
operations available to clients: sayHello, sayHelloUser, and sayHelloToAll. If you
don’t want to expose the sayHelloToAll method as part of the HelloWorld
implementation, you can use the @WebMethod annotation as follows:
@WebMethod(exclude="true")
public void sayHelloToAll() { return "Hello All!"; } // hidden
This prevents the sayHelloToAll method from being exposed as part of the HelloWorld
Web service endpoint. Another way to prevent the s sayHelloToAll method from being
exposed is to annotate the HelloUser class as follows:
package simple;
import javax.jws.WebService;
@WebService
public class HelloUser {
@WebMethod
public void sayHelloUser(String userName)
{ return "Hello: " + userName; } // exposed
In this example, since the sayHelloUser method is annotated with @WebMethod, it is the
only method exposed by the HelloUser class, thus it is the only method from the
HelloUser class that is exposed by the HelloWorld child class.
Web service inheritance is slightly different in the case where the implementation class
uses a Service Endpoint Interface (SEI). Take the following example:
package simple;
import javax.jws.WebService;
@WebService(endpointInterface="simple.HelloUserSEI")
public class HelloWorld extends HelloUser {
package simple;
import javax.jws.WebService;
@WebService
public class HelloUser {
package simple;
import javax.jws.WebService;
@WebService
public interface HelloUserSEI {
public void sayHello(); // exposed
}
In the case above, it might seem like the HelloUser Web service would expose three
methods: sayHello, sayHelloUser, and sayHelloToAll. However, the SEI is used to
define the contract of the HelloWorld Web service, and as such, only the sayHello
method is actually exposed.
The @HandlerChain annotation
JAX-WS supports the use of handlers that can be invoked before and after a service runs.
You can use the @HandlerChain annotation on a service endpoint to point to a
configuration file, which in turn defines the handler classes and the sequence in which to
run them. You can also use handlers with JAX-WS clients. In addition to using
annotations, you can also do configuration with binding customizations and JAX-WS
APIs (only on the client), as described in Chapters 8 and 9 of the JSR-224 specification.
The only valid annotation parameter for JAX-WS is the path to the handler configuration
file. Below is a simple echo service with attached handlers defined in handlers.xml:
package samples.example5;
import javax.jws.HandlerChain;
import javax.jws.WebService;
@WebService
@HandlerChain(file="handlers.xml")
public class HandlersDemo {
public String echo(String input) {
return("server replies: "+input);
}
}
The file handlers.xml is packaged with the application and its location as specified in the
file parameter is relative to the class file carrying the HandlerChain annotation:
<?xml version="1.0" encoding="UTF-8"?>
<jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee">
<jws:handler-chain name="SimpleChain">
<jws:handler>
<jws:handler-class>
samples.example5.RubberStampHandler
</jws:handler-class>
</jws:handler>
</jws:handler-chain>
</jws:handler-chains>
The configuration file above declares a handler class RubberStampHandler that will run
before and after each call to each service method in the class.
Example 5 in the downloadable samples demonstrates this use of a handler.
Input parameters, which are those marked as IN or INOUT, are included in the input
message. Output parameters, which are those marked as OUT or INOUT, are included in
the output message. Note that output parameters use JAX-WS Holder<T> types
(javax.xml.ws.Holder<T>) in order to return values. Also note that output parameters
that are primitives are mapped to the associated “boxed” class for use with Holder<T>.
For example, an output parameter of type int is mapped to Holder<Integer>.
The default values for this annotation are affected by the settings of the @SoapBinding
annotation, described in the next section. The @SoapBinding annotation settings for the
message use and parameter style affect the name-related attributes on this annotation. See
JSR 181 for more information. Other default values are independent of the
@SoapBinding annotation. By default the return value is sent in the SOAP body rather
than the SOAP header.
The default values are a message style of DOCUMENT, a message use of LITERAL, and a
message parameter style of WRAPPED.
For a detailed discussion of SOAP message style, use and parameter style, including
examples of WSDL and SOAP messages illustrating the various combinations, see the
developerWorks article Which style of WSDL should I use?
Below is a brief and extremely simplified overview of the SOAP message semantics
related to message style and message parameter style values. Note that the following
overview, except as noted for DOCUMENT/BARE, does not consider header parameters or
return values. For more information on header parameters and for the various parameter
types of IN, OUT, and INOUT see the @WebParam annotation. For more information on
header return values, see the @WebResult annotation.
• The element in an input message has the same name as the operation. This is
called the operation element. That element can contain child elements that
correspond to the IN and INOUT parameters for the operation.
• The element in an output message has the same name as the operation appended
with “Response”. That element can contain a child element corresponding to a
return value (if any) as the first element, followed by elements for the INOUT and
OUT parameters.
• Note that the parameter parameterStyle does not affect RPC. RPC uses the
default value of WRAPPED. The input and output messages contain a single
element based on the operation name and that element may contain one or more
child elements for parameters and the return value.
• The element in an input message has the same name as the operation. That
operation element can contain child elements that correspond to the IN and INOUT
parameters for the operation.
• The element in an output message has the same name as the operation appended
with “Response”. That element can contain a child element corresponding to the
the return value (if any) as the first element, followed by elements the INOUT and
OUT parameters.
• The element in an output message has the same name as the operation appended
with “Response” for a return value. If the operation is a void and has no return
value, the message will have the same name as the single non-header output
parameter, which can be of type OUT or INOUT.
The @SoapBinding annotation is only valid for binding types of SOAP 1.1 or SOAP 1.2,
either with or without MTOM enabled. See the @BindingType annotation for
information on the type of the binding.
The default value if this annotation is a binding of SOAP 1.1 over HTTP without MTOM
enabled. Valid values for bindings and the enablement of MTOM are defined as constants
as follows:
Note that if WSDL is not provided with the endpoint, it will be generated only for
endpoints bound to SOAP 1.1; WSDL will not be generated for endpoints bound to
SOAP 1.2 or XML. That means that if an endpoint is deployed without WSDL, it must be
bound to SOAP 1.1 in order to be able to generate WSDL in response to a ?WSDL request.
Endpoints that are deployed with WSDL are not restricted to the SOAP 1.1 binding in
order to respond to a ?WSDL request, because the WSDL was provided with the endpoint
and does not need to be generated.
1. To change the binding from the default SOAP 1.1 over HTTP to either SOAP 1.2
over HTTP or XML over HTTP do the following:
• For dynamic ports, which are ports that are added using
Service.addPort(QName portName, String bindingId, String
endpointAddress), the binding is specified as the second parameter when the
port is added. Note that the values used to set the binding are the same constants
described above as valid values for the @BindingType annotation.
• For non-dynamic ports, the WSDL must be provided and the binding extensibility
element in the WSDL must indicate the type of binding, either the SOAP 1.2 or
HTTP (that is, XML over HTTP), via its namespace. Values for WSDL binding
extensibility namespace are as follows: (Note that these values are different from
the values used on the @BindingType annotation and for the Service.addPort
method described above.)
• SOAP 1.1 (default): http://schemas.xmlsoap.org/wsdl/soap/
• SOAP 1.2: http://schemas.xmlsoap.org/wsdl/soap12/
• HTTP (which indicates a binding type of XML over HTTP):
http://schemas.xmlsoap.org/wsdl/http/
<definitions
targetNamespace="http://jaxws.axis2.apache.org/proxy/soap12"
...
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/">
...
<binding name="EchoBinding" type="tns:Echo">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
2. To enable MTOM on the service requester, the Binding instance is obtained from
the Proxy or the Dispatch, then MTOM is enabled on that instance via
binding.setMTOMEnabled(true). For examples of enabling MTOM on both the
endpoint and the service requester, see the section Enabling MTOM for JAX-WS
Web services in the WebSphere Application Server Information Center.
Summary
In this article, you’ve learned how you can use annotations to construct and customize
Web services starting from Java using the WebSphere Application Server V6.1 Feature
Pack for Web Services. Using this approach to Web service development allows you
focus on the Java code and reduces or eliminates the need to customize deployment
descriptors and WSDL files.
Resources
• JSR 224: Java API for XML-Based Web Services (JAX-WS) 2.0: Get the
specification.
• JSR 181: Web Services Metadata for the java Platform: Get the specification.
• JSR 222: Java Architecture for XML Binding (JAXB) 2.0: Get the specification.
• IBM WebSphere Application Server V6.1 Feature Pack for Web Services:
Download the Feature Pack and documentation.
• Application Server Toolkit Update for Web Services Feature Pack: Download the
Web Services Feature Pack update to the Application Server toolkit.