Friday, January 05, 2007

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

    13 comments:

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

      Any adise?

      Nick McCalip

      ReplyDelete
    2. 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.

      ReplyDelete
    3. 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

      ReplyDelete
    4. 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.

      ReplyDelete
    5. 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

      ReplyDelete
    6. 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 ?

      ReplyDelete
    7. 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

      ReplyDelete
    8. 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

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

      Thanks.

      -T

      ReplyDelete
    10. 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.

      ReplyDelete
    11. 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

      ReplyDelete
    12. Hi Abhi,

      when i execute C:\workspaces\WebServices\JaxWsClientWeb\src>wsimport -s . http://localhost:8080/JaxWsTest/JaxWsServiceService?wsdl command on command prompt. i have found following error.

      parsing WSDL...


      [ERROR] file:/C:\workspaces\WebServices\JaxWsClientWeb\src/ûs is unreachable


      Failed to parse the WSDL.

      ReplyDelete
    13. Thanks for your valuable posting.I have collect more than information from your website. It is really wonderful blog. please added more than tips. i'm working in Erp in india.Here providing very low price and Quality ERP,Cloud ERP, CMS , responsive webdesign and ERP. you have any more than information kindly make me call this number 044-42127512 or send your mail info@excelanto.com.

      ReplyDelete

    Popular Posts