Implementing Web Services using JAX-WS
Previously, I wrote a post describing the use of Apache Axis to create and consume Web Services from Java. In this post, I will describe how to use JAX-WS to create and consume web services. I used Glassfish application server for this application. The Web service and the Web Service client are both web applications.

The Service
  1. Create a dynamic web project in Eclipse
  2. Create the Web Service End point
    import javax.jws.WebMethod;
    import javax.jws.WebService;
    @WebService
    public class JaxWsService {
    @WebMethod
    public String sayHello(String message) {
    System.out.println("sayHello:" + message);
    return "You said '" + message + "'";
    }
    }
    JaxWsService.java

    • @WebService annotation is used to denote a Web Service End point.
    • Alternatively, you can have a Service End Point Interface (SEI). An SEI declares methods that can be invoked by clients.
  3. Generate artifacts required for deploying, using wsgen: The wsgen.bat file is located in the GLASSFISH_HOME/bin directory. The following command can be used to create the artifacts
    C:\workspaces\WebServices\JaxWsTest\src>wsgen -classpath ../build/classes/ -wsdl -s . ws.JaxWsService
    You can see that I ran wsgen from my src directory (the project was created in eclipse).
  4. Export the WAR file and deploy on Glassfish. To verify, go to the glassfish administrative console -> Web Services, you should see a Web service installed by the name JaxWsService. You might get an exception as shown below
    Error loading deployment descriptors for module [WebServicesEAR] -- (class: com/sun/xml/ws/modeler/RuntimeModeler, method: processRpcMethod signature: (Lcom/sun/xml/ws/model/JavaMethod;Ljava/lang/String;Ljavax/jws/WebMethod;Ljava/lang/String;Ljava/lang/reflect/Method;Ljavax/jws/WebService;)V) Incompatible argument to funct
    This is due to JAXWS/JWSDP binaries in the classpath. Remove any WS jar files (appserv-ws.jar, webservices-tools.jar etc.) from your class path.
  • The Web deployment desciptor:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>JaxWsTest</display-name>
    <welcome-file-list>
    <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    </web-app>
    web.xml
  • The Client
    For this example I used a web application as a client. A servlet that invokes the actual Web Service client, and the Web Service client class which uses invokes the web method.
    1. Create a dynamic web application in Eclipse.
    2. Generate the required artifacts using wsimport command. The command I used is shown below.
      C:\workspaces\WebServices\JaxWsClientWeb\src>wsimport  -s . http://localhost:8080/JaxWsTest/JaxWsServiceService?wsdl
    3. Write the Servlet: The servlet uses the @WebServiceRef annotation, so that the server can inject the Web service reference into the servlet. The following is the code for the servlet.
      import java.io.IOException;

      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.xml.ws.WebServiceRef;

      import ws.JaxWsServiceService;

      import client.JaxWsClient;

      public class JaxWsClientServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

      @WebServiceRef(wsdlLocation = "http://localhost:8080/JaxWsTest/JaxWsServiceService?wsdl")
      JaxWsServiceService service;

      public JaxWsClientServlet() {
      super();
      }

      protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      JaxWsClient client = new JaxWsClient(service);
      response.getWriter().println(client.callService());
      response.getWriter().close();
      }
      }
      JaxWsClientServlet.java
    4. Write the client class: The client class is a simple Java class, which uses the Service references generated by the wsimport command to invoke the Web Service. Following is the code for the client class.
      import ws.JaxWsService;
      import ws.JaxWsServiceService;

      public class JaxWsClient {
      JaxWsServiceService service;

      public JaxWsClient(JaxWsServiceService service) {
      this.service = service;
      }

      public String callService() {
      JaxWsService port = service.getJaxWsServicePort();
      String result = port.sayHello("Hello");
      return result;
      }
      }
      JaxWsClient
    5. The Web Deployment Descriptor
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <display-name>JaxWsTest</display-name>
      <display-name>JaxWsClientWeb</display-name>
      <servlet>
      <description></description>
      <display-name>clientServlet</display-name>
      <servlet-name>clientServlet</servlet-name>
      <servlet-class>servlets.JaxWsClientServlet</servlet-class>
      </servlet>
      <servlet-mapping>
      <servlet-name>clientServlet</servlet-name>
      <url-pattern>/clientServlet</url-pattern>
      </servlet-mapping>
      <welcome-file-list>
      <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
      </web-app>
      web.xml
    6. Export WAR file and deploy. To test go to
      http://localhost:8080/JaxWsClientWeb/clientServlet

    11 comments:

    Nick said...

    I have been looking for a proper means not to hard code the WSDL path in the client object.

    Any adise?

    Nick McCalip

    Abhi said...

    Are you looking for a deployment descriptor type of solution? Then there is an option to include a deployment descriptor (sun-jaxws.xml) with you application. I haven't tried it yet, but the JSR-109 (Web services implementation) does mention it. That could be your starting point.

    Anonymous said...

    Wich GlassFish version did you use with this sample? Is it possible to make available all the war source code? Do you know how to use it with Eclipse instead of Netbeans?

    Thanks a lot!
    José Renato

    Abhi said...

    I used glassfish v1, build 14 for this example.

    This was built using eclipse (not netbeans) and a couple of commands from the dos command line.

    Leave you email id if you would like the war file.

    Anonymous said...

    Hi,

    can you also email me the war file ? I've been trying to get your example up and running without any luck.

    thanks.
    erdal_akgol@hotmail.com

    Anonymous said...

    Abhi,

    I run into the same problem from within NetBeans with Web Services pack installed.

    The Jax-Ws lib is included in the default server setup. Any idea how to remove fronm that deafult setup ?

    Anonymous said...

    Hi Abhi,
    I was trying to create a web service client to consume some of the news service from 'newsisfree'. I wanted to access it from my servlet. Have you tried it before? Any code samples that shows how to access a webservice(from internet) from a servlet?
    Thanks a lot for the help.
    Regards,
    John.
    audiophilesg@yahoo.com.sg

    Kartik said...

    Hi Abhi

    Can't thank you more for this artical. I am able to run this example.

    But here is the problem i am facing. If i am running the following command on the server, it works.

    wsimport -extension -s . http://localhost:8080/TestWebService/TestWebServiceService?wsdl


    But if i want to run the same from remote PC it fails. and gives following result.

    wsimport -extension -s . http://w2vzvfds01:8080/TestWebService/TestWebServiceService?wsdl

    where w2vzvfds01 is my server PC.

    ----------------------------------------
    parsing WSDL...


    [ERROR] Failed to read the WSDL document: http://w2vzvfds01:8080/TestWebService/TestWebServiceService?wsdl, because 1) could not find the document; /2) the document could not be read; 3) the root element of the document is not < wsdl:definitions>.
    unknown location

    Failed to parse the WSDL.
    ----------------------------------------

    All the WSDL and schema are accessible in the browser. I tried manually running them. So they are definitely visible and accessible and available.

    Can u help me?

    Thanks
    Kartik

    Anonymous said...

    Hi,
    @WebServiceRef always returns a null. What is the fix for this?

    Thanks.

    -T

    Anonymous said...

    Hi Abhi,
    Thanks for the Article..I am trying to run webservice on Sun Application server using the steps which u described, but its getting deployed as a web application instead of a Web Service..am I missing something..Thanks in advance.

    Anonymous said...

    Hi Abhi

    Greatly appreciated your article.

    I got a question - how can you deploy the war file derived from this exercise to SJAS 8.1. Any tweaking of config files or removal of RPC stuff on the server or mods on the build process?

    Thanks a lot in advance,
    Jane