Developing JAX-WS Services
JAX-WS is the Java API for XML-Based Web Services. It provides a simple method of developing Web services with a high level of portability and is defined using Java annotations without any deployment descriptors. JAX-WS 2.0 specification (http://jcp.org/aboutJava/communityprocess/mrel/jsr224/index3.html) is defined on top of the JAX-RPC 1.1 (http://jcp.org/aboutJava/communityprocess/final/jsr101/index2.html), which defines a standard set of APIs for RPC oriented Web services for Java. RPC is not widely used anymore. JAX-WS also delegates all data binding aspects to JAXB (http://jcp.org/aboutJava/communityprocess/mrel/jsr222/index2.html).
JAX-WS development is dependent on Java annotations defined in JSR-181 (Web Services Metadata for the Java Platform), JAX-WS and JAXB. These annotations are used to let the JAX-WS runtime know about the nature of the Web service interface. The developer can customize the Web service interface using annotations and build the service according to his requirements.
Use WSO2 Developer Studio to easily develop your JAX-WS/JAX-RS Application. It will generate the needed Web application structure and you only have to concentrate on annotations and the business logic.
JAX-WS Annotations
Listed below are the most important annotations and their member-value pairs.
@WebService
Used to mark a Java class when implementing a Web service or to mark a Java interface as defining a Web service interface.
- name - Name of the wsdl:portType in WSDL 1.1 (http://www.w3.org/TR/wsdl).
- targetNamespace - The XML namespace used for the WSDL
- serviceName - Name of the wsdl:service in WSDL 1.1. This is not allowed on endpoint interfaces.
- portName - Name of the wsdl:port in WSDL 1.1. This is not allowed on endpoint interfaces.
- wsdlLocation - A URL which points to an already existing WSDL
- endpointInterface - Complete name of the endpoint interface, when the interface and the implementation are separated. This is not allowed on endpoint interfaces.
@WebMethod
Used to customize a method which is exposed as a Web service operation.
- operationName - Name of the wsdl:operation matching the particular method
- action - The action for this operation
- exclude - Used to leave a method out of the Web Service interface
@Oneway
This annotation can be used to indicate that the given method maps to a one way operation. It has only an input message and no output message.
@WebParam
Used to customize the mapping of an individual method parameter to a Web service message part and XML element.
- name - Name of the parameter. This property relates to the style (document or rpc) of the operation.
- partName - Name of the wsdl:part which represents this parameter
- targetNamespace - XML namespace for this parameter
- header - If true, the parameter is pulled from a message header rather than the message body
@WebResult
Used to customize the mapping of the return value to a Web service message part and XML element.
- name - Name of the return value. This property relates to the style (document or rpc) of the operation.
- partName - Name of the wsdl:part which represents the return value
- targetNamespace - XML namespace for the return value
- header - If true, the return value is in a message header, rather than the message body
@SOAPBinding
Specifies the mapping of the Web service onto the SOAP message protocol.
- style - DOCUMENT or RPC
- use - LITERAL or ENCODED
- parameterStyle - WRAPPED or BARE
JAX-WS 2.x supports the following combinations:
- DOCUMENT/LITERAL/WRAPPED (default)
- DOCUMENT/LITERAL/BARE
- RPC/LITERAL/WRAPPED
There are two main Web service development models. They are:
- Java to WSDL (code first) approach
- WSDL to Java (contract first) approach
Java to WSDL Development Model with JAX-WS
In this approach, development starts from the code or the service implementation and the Web service engine generates the WSDL for the developer. The developer can write his POJO service and use annotations to control the structure of the WSDL. The JAX-WS runtime generates the WSDL according to these annotations used. The advantage of using annotations is that the Web service implementation can be changed without affecting the generated WSDL contract. Therefore, JAX-WS is the standard development technique when it comes to POJO development.
Some sample POJO services using JAX-WS are as follows:
Sample 1:
This simple example uses the @WebService annotation to convert a simple POJO into a Web service. When you use this annotation, all the public methods in the class become operations in the service by default. If you want to exclude a particular method, you have to specify it using the 'exclude' property of the @WebMethod annotation. Also, if some method should be mapped into a one way operation, you have to use the @Oneway annotation. The sample code of this POJO is as follows:
package org.wso2.jaxws.sample01; import javax.jws.WebService; import javax.jws.Oneway; import javax.jws.WebMethod; @WebService public class SimpleSample { public String echo(String echoInput) { return echoInput; } @Oneway public void ping(String pingInput) { System.out.println("Ping : " + pingInput); } @WebMethod(exclude = true) public String hideMethod(String hideInput) { return "Hiding : " + hideInput; } }
Sample 2:
This sample service (StudentMarksService) contains two operations called 'computeAverage' and 'computeHighestMarks'. Both these methods get a Student object as a parameter. The sample code is as follows, showing how you can customize the WSDL service interface using annotations.
StudentMraksService.java class package org.wso2.jaxws.sample02; import javax.jws.WebService; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.soap.SOAPBinding; @WebService( name = "StudentMarks", serviceName = "StudentMarksService", targetNamespace = "http://wso2.org/jaxws/sample02" ) @SOAPBinding( style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED ) public class StudentMarksService { @WebMethod( operationName = "computeAverage", action = "urn:getAverage" ) @WebResult( name = "average", targetNamespace = "http://wso2.org/jaxws/sample02" ) public double getAverage( @WebParam(name = "student", targetNamespace = "http://wso2.org/jaxws/sample02") Student student) { double totalMarks = 0; for (int i = 0; i < student.getMarks().length; i++) { totalMarks += student.getMarks()[i]; } return totalMarks / student.getMarks().length; } @WebMethod( operationName = "computeHighestMarks", action = "urn:getHighestMarks" ) @WebResult( name = "highest", targetNamespace = "http://wso2.org/jaxws/sample02" ) public int getHighestMarks( @WebParam(name = "student", targetNamespace = "http://wso2.org/jaxws/sample02") Student student) { int highest = 0, temp; for (int i = 0; i < student.getMarks().length; i++) { temp = student.getMarks()[i]; if (temp > highest) { highest = temp; } } return highest; } }
Student.java class package org.wso2.jaxws.sample02; public class Student { private String name; private int age; private int[] marks; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int[] getMarks() { return marks; } public void setMarks(int[] marks) { this.marks = marks; } }
You can simply compile these sample classes, create .jar archives and deploy them in a running Carbon instance.
WSDL to Java Development Model with JAX-WS
In this method, the WSDL contract is used to generate the service skeleton and other binding classes through the usage of some WSDL to Java tool (Look under the Tools section for more information). The tool generates the Service Endpoint Interface (SEI) and the JAXB binding classes according to the WSDL and the schema. Service developer only has to write the service class by implementing the SEI.
A WSDL to Java sample using JAX-WS is as follows:
Sample 1:
The same "StudentMarksService" mentioned above is used here.
First, generate the code using some WSDL to Java tool. Create a folder (Ex: wsdl2java) to place your generated source files. Next step is to write the service implementation class. Use some IDE (e.g., Developer Studio) and create a project using the generated classes. Then write the service class by implementing the SEI. Use the @WebService annotation to map the properties according to your WSDL and make sure you point to your WSDL file using the 'wsdlLocation' property. Service class is as follow:
package org.wso2.jaxws.sample02.service; import org.wso2.jaxws.sample02.StudentMarksPort; import org.wso2.jaxws.sample02.Student; import javax.jws.WebService; @WebService( serviceName = "StudentMarksService", portName = "StudentMarksPort", targetNamespace = "http://wso2.org/jaxws/sample02", endpointInterface = "org.wso2.jaxws.sample02.StudentMarksPort", wsdlLocation = "StudentMarksService.wsdl" ) public class StudentMarksImpl implements StudentMarksPort { public double computeAverage(Student student) { double totalMarks = 0; for (int i = 0; i < student.getMarks().size(); i++) { totalMarks += student.getMarks().get(i); } return totalMarks / student.getMarks().size(); } public int computeHighestMarks(Student student) { int highest = 0, temp; for (int i = 0; i < student.getMarks().size(); i++) { temp = student.getMarks().get(i); if (temp > highest) { highest = temp; } } return highest; } }
Compile your project and create the .jar
archive to be deployed. Note that you have to include your WSDL file at the root level of your .jar
archive.
For more information on these operation styles, see the following articles on non JAX-WS contract-first development with Apache Axis2.
For more information on writing JAX-WS annotated Web Services, go to: http://axis.apache.org/axis2/java/core/docs/jaxws-guide.html