Tuesday, April 19, 2011

Simple JAX-WS Client example


    In my previous articles I have discussed server side code of a web service which deals essentially with publishing a web service. However in most of the business situation that one comes across the role is of a web service client rather than a web service provider. This articles deals with the creation of a web service client using JAX-WS.

    In JAX-WS clients are of 2 types. a) Static Clients b) Dynamic Clients.

Static Clients – The more commonly developed clients, these clients are generally developed by creating auto-generated code on the WSDL provided. These are specific to a WSDL hence the provider cannot be changed at runtime.

Dynamic Client – The lesser common of the two forms of clients, used when developing a client dynamically at runtime. This method is used when we may want to change our web service provider at runtime (or for REST services since they do not have a WSDL).

In this article we discuss the creation of a Static Client. The brief process of creation of a static client is highlighted below:

Step 1. Identify the WSDL location of the service provider

Step 2. Run the auto generate tool, to generate the artifacts/ stubs that are needed to create a web service client.

Step 3. Create the client code that will create the request object and then call the service using the stubs created in Step 2.

Let us try to create a sample code for a Web Service Client for the HelloWorld service that we created here. For my case, the service is deployed on Glassfish and the WSDL is located at the following location: http://localhost:8080/JAXWSHelloWorld/HelloWorld?wsdl

To create the stubs/artifacts use the wsimport command available with the web service provider (in my case Glassfish or Java 6). Though the name may vary with different providers the basic syntax normally remains the same. Run the command to create a list of artifacts as given below:

Command: wsimport -s src -keep -d build\classes -verbose -p com.jaxws.helloworld.client http://localhost:8080/JAXWSHelloWorld/HelloWorld?wsdl

The parameters / arguments which have been passed are:

ArgumentDescription
-s [folder]Location to place the generated .java source files
-d [folder]Location to place the generated class files
-keepInstructs wsimport to keep the generated source files and not delete them
-verboseTo output the trace logs in stdout (to debug / follow)
-p [package name]To use a custom package name for generated classes. The default value would be taken from the target namespace if this is not specified

 

On running the above command the following files are generated. Please note the files generated below will vary according to WSDL.

File NamePurpose
package-info.javaThis defines the mapping between the namespace and package name as an annotation
ObjectFactory.javaThis factory class which is used to create request and response objects.
HelloWorldEndpoint.javaThe SEI (Service Endpoint Interface) generated to map the WSDL port. It makes all the exposed operations available to the client.
HelloWorld.javaThe Service class which implements the code for the SEI, allowing us to call the remote server (web service provider) to get the response. This class takes the request in object form, marshals it into XML, sends the XML / SOAP to service, gets back the response as XML/SOAP, un-marshals it to an object and gives us back.
Greet.java

GreetResponse.java
The Request and Response objects that are created.

 

The above generated files are called stubs and are used to access the web service. A sample simple program to access the service is shown below:

public
class HelloWorldClient {

    @WebServiceRef(wsdlLocation="http://localhost:8080/JAXWSHelloWorld/HelloWorld?wsdl")

    private HelloWorldEndpoint helloWorld;


    public static void main(String[] args) {

        HelloWorldClient client = new HelloWorldClient();

        if(client.helloWorld==null){

            HelloWorld helloWrldService = new HelloWorld();

            client.helloWorld = helloWrldService.getHelloWorldEndpointPort();

        }

        String resp = client.helloWorld.greet("Aditya", "Keyal");

        System.out.println(resp);

    }

}

The above code is a standalone main program which is used to access the web service. There are few points to be noted here. The SEI member variable has an annotation @WebServiceRef added. If deployed in a web service container (i.e. if this piece of code was present in a Servlet instead of a standalone main program and the Servlet deployed in the same glassfish server as the service) then the SEI Implementation [HelloWorld.java] is used to automoatically look up the "Port" which is then injected through dependency injection. In this program since I have used a main program I had to create an instance of HelloWorld.java and assign the port to the SEI variable.

In the next article I will create a Dynamic client for the sample service.

No comments:

Post a Comment