|
|
Many Web service developers are interested in implementing services using JAX-WS as it is the Java standard for Web Services. If you are trying to use JAX-WS support in WSO2 Web Services Application Server (WSO2 WSAS), this article will provide the necessary foundation for you by starting from the basics and going through code first and contract first development approaches in JAX-WS. This article will be followed by some more articles which will describe more advanced topics on service development and also the client side usage of JAX-WS standards.
The Java API for XML-Based Web Services (JAX-WS) 2.x specification [1] defines a standard set of APIs and conventions for supporting Web services in the Java platform. JAX-WS standard provides an easy way of developing Web services for Java users with a high level of portability. It is defined using Java annotations without using any deployment descriptors. Most Java Web services developers around the world have moved towards JAX-WS due to it's simplicity and portability.
The Java API for XML-Based RPC (JAX-RPC) 1.1 specification [2] was a standard set of APIs for RPC oriented Web services for Java. After the Web services world moved away from RPC, JAX-WS 2.0 specification was defined on top of JAX-RPC 1.1. And also the Java Architecture for XML Binding (JAXB) 2.0 specification [3] was defined in parallel to standardize the data binding functionalities. JAX-WS delegates all data binding aspects to JAXB.
WSO2 Web Services Application Server (WSO2 WSAS) 3.x [4] supports many ways of developing Web services. JAX-WS is also among them. JAX-WS support is implemented by enhancing the underlying Apache Axis2 [5] JAX-WS implementation. WSO2 Web Services Application Server (WSO2 WSAS) management console can be used to deploy and configure JAX-WS services just like any other service type.
JAX-WS development is completely dependent on Java annotations which are defined in JSR-181 [6] (Web Services Metadata for the Java Platform), JAX-WS and JAXB specifications. 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 these annotations and build the service according to his requirements. Let's have a look at the most important annotations and their member-value pairs which are used in developing JAX-WS services.
name - Name of the portType in WSDL 1.1 [7] targetNamespace - The XML namespace used for the WSDL serviceName - Name of the service in WSDL 1.1. This is not allowed on endpoint interfaces. portName - Name of the 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.
operationName - Name of the operation matching the particular method action - The action for this operation exclude - Used to leave a method out of the Web Service interface
name - Name of the parameter. This property relates to the style (document or rpc) of the operation and the mappings are somewhat complex. partName - Name of the 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
name - Name of the return value. This property relates to the style (document or rpc) of the operation and the mappings are somewhat complex. partName - Name of the 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
style - DOCUMENT or RPC use - LITERAL or ENCODED parameterStyle - WRAPPED or BAREJAX-WS 2.x supports the following combinations
Java to WSDL or code first approach is one of the two main development models when it comes to Web services. In this approach, development starts from the code or the service implementation and the Web service engine generates the WSDL for the developer. POJO (Plain Old Java Object) development with Apache Axis2 [10] is one such example. Similarly, almost all Web service engines support POJO development in their own ways. But it doesn't provide enough control for the developer over the generated WSDL. If the code changes at some point, the generated WSDL can also be changed and that is not recommended in Web services development. In other words, the contract should not be changed after the deployment of the service.
JAX-WS provides a perfect answer for this problem through its usage of annotations. The developer can write his POJO service in the same way as earlier and use the annotations to control the structure of the WSDL. JAX-WS runtime will generate the WSDL according to these annotations. After clearly defining the WSDL interface through annotations, implementation can be changed without affecting the generated WSDL contract. Therefore, JAX-WS is the standard development technique when it comes to POJO development.
Now let's move onto some sample POJO services using JAX-WS.
Sample 01
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. And also if some method should be mapped into a one way operation, you have to use the @Oneway annotation. The sample code for this simple POJO is shown below.
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;
}
}
You can just compile this class and create a jar archive and deploy it in WSO2 Web Services Application Server (WSO2 WSAS). Please refer to deployment section of this article for more details on how to deploy. After deploying it, you can see the generated WSDL 1.1 file just by clicking on the WSDL 1.1 link in front of our SimpleSampleService.
Sample 02
Now lets have a look at a somewhat complex sample which contains most of the annotations described above. This StudentMarksService contains two operations called 'computeAverage' and 'computeHighestMarks'. Both these methods gets a Student object as a parameter. You can see how we can customize the WSDL service interface using the annotations. The sample code for this sample is shown below.
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;
}
}
Just create the jar archive and deploy the service to see the generated WSDL 1.1 file. You can check whether the WSDL elements are correctly generated according to our annotations.
Note : The deployable jar archives for both these samples can be found under attachments and you can just deploy those into WSO2 Web Services Application Server (WSO2 WSAS). And also, you can use some tool like SOAP UI [11] to invoke these services. And also try to use different customizations using annotations to have a better understanding.
WSDL to Java or contract first approach is the other well known Web service development model. Here the WSDL contract is used to generate the service skeleton and other binding classes through the usage of some WSDL to Java tool. When it comes to JAX-WS, 'wsimport' tool which is shipped with the JDK, can be used for this purpose. It will generate 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.
Now let's move on to a WSDL to Java sample using JAX-WS.
Sample 01
Here I'm going to create the same StudentMarksService above with the generated WSDL. You can see that the JAX-WS generated WSDLs in WSO2 Web Services Application Server (WSO2 WSAS) contains a schema import. In order to make it simple, I've included the schema in the WSDL itself just by removing the schema import and pasting the schema under the 'types' section. You can have a look at the 'StudentMarksService.wsdl' which can be found under attachments.
First of all, we have to generate the code using the 'wsimport' tool. You can use the following command on the console to easily generate the code. Create a folder (Ex: wsdl2java) to place your generated source files.
wsimport -s wsdl2java StudentMarksService.wsdl
Now we have the generated Java files. Next step is to write the service implementation class. Just use your favorite IDE 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 shown below.
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;
}
}
Now 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 (find the completed jar archive under attachments). Finally deploy the service and invoke it.
After implementing your JAX-WS service using one of the above mentioned approaches, you can easily deploy it in WSO2 Web Services Application Server (WSO2 WSAS). Here are the steps to follow.

In this article, first we discussed the JAX-WS standards with basic annotations. After that we moved into Java to WSDL and WSDL to Java development approaches using JAX-WS with comprehensive samples. Finally we discussed how to deploy JAX-WS artifacts in WSO2 Web Services Application Server (WSO2 WSAS).
Although this article provides the foundation for JAX-WS development, there are many more areas defined in the JAX-WS specification. We'll be discussing more advanced topics in the next steps in this series of articles. In addition to that, there will be some articles on client side usage of JAX-WS as well.
[1] JAX-WS 2.2 specification
[2] JAX-RPC 1.1 specification
[3] JAXB 2.2 specification
[4] WSO2 Web Services Application Server (WSO2 WSAS)
[5] Apache Axis2
[6] JSR 181 specification
[7] WSDL 1.1 specification
[8] Contract first article – Part 1
[9] Contract first article – Part 2
[10] Apache Axis2 POJO guide
[11] SOAP UI
[12] jaxws-rt.jar
[13] jaxws-tools.jar
Isuru Suriarachchi, Senior Software Engineer, WSO2, isuru AT wso2 DOT com.