Implementing web services with JAX-WS

This recipe will explore the implementation of web services with JAX-WS. For web service construction, we will use the top-down approach.

Getting ready

In the recipe Implementing web services with Axis2, we started web service implementation with the POJO class. The approach is called the bottom-up design. We will start the development of web services in JAX-WS from the WSDL definition; that is, we will use the top-down approach.

Initially, we create a new Java project in Eclipse. In the wizard, we change the output directory from bin to classes. When the project is created, we amend it with the following actions:

  1. Create the wsdl directory. We put it in the WSDL file that is our starting point of creating a web service.
  2. Create the build directory. The directory presents the placeholder, where the deployment package will be created.
  3. Create an empty build.xml file at the top-level project directory.

The WSDL file for our example web service is as follows:

<?xml version = "1.0" encoding = "UTF-8" ?>
<wsdl:definitions targetNamespace = "http://org.packt.ws.jaxws.async/reservation" xmlns:msgel = "http://org.packt.ws.jaxws.async/elts" xmlns:res = "http://org.packt.ws.jaxws.async/reservation" xmlns:wsdl = "http://schemas.xmlsoap.org/wsdl/" xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsaw = "http://www.w3.org/2006/05/addressing/wsdl" xmlns:jaxws = "http://java.sun.com/xml/ns/jaxws">
  <wsdl:types>
    <xsd:schema targetNamespace = "http://org.packt.ws.jaxws.async/elts" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" elementFormDefault = "qualified">
    <xsd:element name = "ReservationEl" type = "msgel:ReservationType"/>
    <xsd:complexType name = "ReservationType">
    <xsd:sequence>
      <xsd:element name = "hotelName" type = "xsd:string"/>
      <xsd:element name = "name" type = "xsd:string"/>
      <xsd:element name = "lastname" type = "xsd:string"/>
      <xsd:element name = "price" type = "xsd:int"/>
      <xsd:element name = "noOfNights" type = "xsd:int"/>
    </xsd:sequence>
    </xsd:complexType>
    <xsd:element name = "ReservationConfirmationEl" type = "msgel:ReservationConfirmationType"/>
    <xsd:complexType name = "ReservationConfirmationType">
    <xsd:sequence>  
    <xsd:element name = "confirmationId" type = "xsd:string"/> 
    </xsd:sequence>
    </xsd:complexType>
    </xsd:schema>
  </wsdl:types>  
  <wsdl:message name = "Reservation">
    <wsdl:part name = "payload" element = "msgel:ReservationEl"/>
  </wsdl:message>
  <wsdl:message name = "Confirmation">
    <wsdl:part name = "payload" element = "msgel:ReservationConfirmationEl"/>
  </wsdl:message>
  <wsdl:portType name = "DoReservationAsync">
  <wsdl:operation name = "reserve">
  <jaxws:bindings>
    <jaxws:enableAsyncMapping>true</jaxws:enableAsyncMapping>
  </jaxws:bindings>
  <wsdl:input message = "res:Reservation" wsaw:Action = "http://org.packt.ws.jaxws.async/reservation/reserve"/>
  <wsdl:output message = "res:Confirmation" wsaw:Action = "http://org.packt.ws.jaxws.async/reservation/confirm"/>
  </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name = "DoReservationBind" type = "res:DoReservationAsync">
  <wsaw:UsingAddressing required = "true"/>
  <soap:binding style = "document" transport = "http://schemas.xmlsoap.org/soap/http"/>
  <wsdl:operation name = "reserve">
  <!-- soap:operation style = "document" soapAction = "http://org.packt.ws.jaxws.async/reservation/confirm"/-->
  <wsdl:input>
    <soap:body use = "literal" parts = "payload"/>
  </wsdl:input>
  <wsdl:output>
    <soap:body use = "literal" parts = "payload"/>
  </wsdl:output>
  </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name = "ReservationService">
  <wsdl:port name = "DoReservationAsyncPort" binding="res:DoReservationBind">
  <soap:address location = "http://localhost/reservation"/>
  </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Now, we are ready to start with web service creation.

How to do it…

The following steps will describe the actions needed to be performed during the implementation of the JAX-WS web service:

  1. For the purpose of creating a web service from the WSDL document, we use the wsimport command that comes with Java SE 6. We prepare the wsimport command, and place it in our ant build.xml file as follows:
    <target name = "buildws">
      <echo message = "building the web service java classes from wsdl"/>
        <exec executable = "${java.home}/../bin/wsimport">
        <arg line = "-keep -verbose -Xdebug -d classes -p org.packt.ws.jaxws.async -s src wsdl/ReservationService.wsdl"/>
      </exec>
    </target>
  2. Since the wsimport utility prepared the interfaces for the web service, we need to provide its implementation. We create a new implementation class DoReservationAsyncImpl.java as follows:
    @WebService(name = "DoReservationAsync", targetNamespace = "http://org.packt.ws.jaxws.async/reservation")
    @SOAPBinding(style = javax.jws.soap.SOAPBinding.Style.RPC)
    public class DoReservationAsyncImpl {

    Note

    The implementation class does not extend the service interface class. Also, the asynchronous methods are not implemented.

  3. Now we have to pack our web service, so we put the following ant task into the build.xml file as follows:
    <target name = "pack">
      <echo message = "creating jar"/>
      <jar destfile = "build/ReservationService.jar" basedir = "/classes"/>
    </target>
  4. The last step of the recipe presents the deployment of the packed jar to the Axis2 server. To automate the deployment, we put the following line into the build.xml file:
    <target name = "main" depends = "pack">
      <echo message = "deploying sample web service to Axis2 servicejars"/>
      <copy file = "build/ReservationService.jar" todir = "<Axis_home>/repository/servicejars"/>
    </target>

We can check the deployment status in the Axis2 Management Console.

How it works…

There are two complementary approaches to building web services. The first one is bottom-up, where we start by coding web services in Java classes. Furthermore, we annotate the code with the web service annotations and at the end we deploy the web service. At the same time, the WSDL document is generated based on the annotated Java classes and their methods.

The second approach presents the top-down approach. In this case, we receive the WSDL document of the web service. With the utility, we create Java classes for the data model and service interface classes. The real implementation of the web service has to be provided by us. After packing the web service artifacts along with the implementation, we are ready to deploy and use our web service. It is worth mentioning that the top-down approach is the recommended one, and whenever possible we should use this approach. The benefits of starting with the top-down approach are numerous. We can start the design with the WSDL document, which is also WS-I compliant.. Furthermore, the development team that will use the web service can start coding the clients right away. This approach is sometimes also called the WS contract-first approach.

The Java API for XML Web Service 2.0 (JSR 224) or JAX-WS provides the ability for developers to expose Java code as a web service. The tools provided to support the JAX-WS web service development fully supports the top-down and bottom-up approach.

In this recipe, we started from the WSDL document, then generated the portable artifacts, and prepared the implementation. If we look at the web service artifact, we see that three methods were created. For the synchronous web service call we have the following code:

@WebMethod
@WebResult(name = "ReservationConfirmationEl", targetNamespace = "http://org.packt.ws.jaxws.async/elts", partName = "payload")
public ReservationConfirmationType reserve(@WebParam(name = "ReservationEl", targetNamespace = "http://org.packt.ws.jaxws.async/elts", partName = "payload")ReservationType payload);

There are two additional methods created for the asynchronous web service call. Remember, we use the asynchronous web service call when designing the BPEL process, supporting the long-running business process as follows:

  1. The first generated method utilize the callback invocation model. With this type of invocation, we first issue the request, and then we check in intervals, to see if the server responds.
    @WebMethod(operationName = "reserve")
      public Future<?> reserveAsync(@WebParam(name = "ReservationEl", targetNamespace = "http://org.packt.ws.jaxws.async/elts", partName = "payload") ReservationType payload, @WebParam(name = "reserveResponse", targetNamespace = "", partName = "asyncHandler") AsyncHandler<ReservationConfirmationType> asyncHandler);
  2. The second method is generated when we decide to use the polling invocation model. In this invocation model, we issue the request, and then poll the response from the server to identify if the web service has finished its processing yet. When the execution of the web service operation is done, we receive the actual Response object as the result.
    @WebMethod(operationName = "reserve")
      public Response<ReservationConfirmationType> reserveAsync(@WebParam(name = "ReservationEl", targetNamespace = "http://org.packt.ws.jaxws.async/elts", partName = "payload") ReservationType payload);

    After packing up the web service into a jar, we were able to deploy it, and consume it. The final outlook of the Eclipse project is as shown in the following screenshot:

    How it works…

The project contains the portable artifacts and implementation of the web services we provide. Also, in the wsdl directory resides the WSDL document from which we generated the portable artifacts. In the build directory, we have a package ready to be deployed.

There's more…

We decided to use the callback invocation model with this recipe. To test the web service, we also prepared the client that calls the asynchronous web service.

  1. First, we define the variables. We need to define the asynchronous callback handler and an input variable.
    ReservationServiceCallbackHandler aHandler = new ReservationServiceCallbackHandler();
    ReservationType input = new ObjectFactory().createReservationType();
  2. We invoke the web service method.
    Future<?> resp = svc.getDoReservationAsyncPort().reserveAsync(input, aHandler);
  3. The next step depends on how we want to handle the response. Either we wait for the response in our client, or we give the waiting task to some external application that then collects the responses and acts accordingly. We created the loop in our test client.
    while (!resp.isDone()) {
      Thread.sleep(5000);
      System.out.println("sleeping");
      }
  4. We handle the response when it becomes available.
    ReservationConfirmationType response = aHandler.getOutput();
    if (response ! = null) {
      String responseStr = response.getConfirmationId();
      System.out.println(">> Confirmation id is: " + responseStr);
      }
  5. We receive the following output, when we run the client code:
    >> Sending the following input
      Name: Jurij
      Lastname: Laznik
      Hotel name: Plaza
      Number of nights: 2
      Price: 100
    sleeping
    sleeping
    >> Confirmation id is: dbf93989-c8fd-47f7-9e7c-25b155aedf27

See also

  • For a bottom-up approach of web service development, see the Implementing a web service with Axis2 recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset