Chapter 5. Invoking Web Services

Table of Contents

5.1. Overview
5.2. Web Service Invocation Using Dynamic Proxy
5.2.1. Creating Client Artifacts
5.2.2. Java SE Client Invocation
5.2.3. Java EE Client Invocation
5.3. Web Service Invocation Using Dispatch Method

This chapter describes how to invoke web services with implementation examples.

5.1. Overview

A JAX-WS web service client application can access a remote web service endpoint through the following methods.

  • Dynamic proxy method

  • Dispatch method

5.2. Web Service Invocation Using Dynamic Proxy

There are two kinds of web service invocation through a dynamic proxy, Java SE and Java EE. Client artifacts need to be created beforehand for both types.

This section describes about the Java SE and Java EE web service invocation methods, and how to create the client artifacts.

5.2.1. Creating Client Artifacts

Whether a web service is generated from a Java class or WSDL file, the web service client is invoked by creating a Java class after creating the client artifacts with the published WSDL file. This section briefly shows how to create the client artifacts for a client invoking the web service created by the Java class from the previous chapter.

Web service client artifacts (proxies) consist of service endpoint interface and service interface classes, which were obtained from the WSDL provided by the service by using the JEUS 8 wsimport tool.

The following example shows how to obtain the client artifacts by using wsimport in the console.

$ wsimport -help
Usage: wsimport [options] <WSDL_URI>

where [options] include:
  -b <path>                 specify jaxws/jaxb binding files or additional schemas
                            (Each <path> must have its own -b)
  -B<jaxbOption>            Pass this option to JAXB schema compiler                            
  -catalog <file>           specify catalog file to resolve external
                            entity references supports TR9401,
                            XCatalog, and OASIS XML Catalog format.
  -d <directory>            specify where to place generated output files
  -extension                allow vendor extensions - functionality
                            not specified by the specification. Use
                            of extensions may result in applications
                            that are not portable or may not
                            interoperate with other implementations
  -help                     display help
  -httpproxy:<host>:<port>  specify a HTTP proxy server (port defaults to 8080)
  -keep                     keep generated files
  -p <pkg>                  specifies the target package
  -quiet                    suppress wsimport output
  -s <directory>            specify where to place generated source files
  -target <version>         generate code as per the given JAXWS spec version
                            e.g. 2.0 will generate compliant code for JAXWS 2.0 spec
  -verbose                  output messages about what the compiler is doing
  -version                  print version information
  -wsdllocation <location>  @WebServiceClient.wsdlLocation value

Examples:
  wsimport stock.wsdl -b stock.xml -b stock.xjb
  wsimport -d generated http://example.org/stock?wsdl

Note

JEUS 8 web service supports wsimport ANT TASK. For more information about console commands and ANT TASK, refer to JEUS Reference Book. "5.5.4. wsimport" and JEUS Reference Book. "5.6.2. wsimport".

Portable artifacts are created by using wsimport ANT TASK with a WSDL file of the following remote web service.

[Example 5.1] << http://host:port/AddNumbers/AddNumbersImplService?wsdl >>

<?xml version="1.0" encoding="UTF-8"?>
<definitions targetNamespace="http://server.fromjava/"
    name="AddNumbersImplService" xmlns:tns="http://server.fromjava/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns="http://schemas.xmlsoap.org/wsdl/">
    <types>
        <xsd:schema>
            <xsd:import namespace="http://server.fromjava/"
                schemaLocation="AddNumbersImplService_schema1.xsd" />
        </xsd:schema>
    </types>
    <message name="addNumbers">
        <part name="parameters" element="tns:addNumbers" />
    </message>
    <message name="addNumbersResponse">
        <part name="parameters" element="tns:addNumbersResponse" />
    </message>
    <portType name="AddNumbersImpl">
        <operation name="addNumbers">
            <input message="tns:addNumbers" />
            <output message="tns:addNumbersResponse" />
        </operation>
    </portType>
    <binding name="AddNumbersImplPortBinding" type="tns:AddNumbersImpl">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
            style="document" />
        <operation name="addNumbers">
            <soap:operation soapAction="" />
            <input>
                <soap:body use="literal" />
            </input>
            <output>
                <soap:body use="literal" />
            </output>
        </operation>
    </binding>
    <service name="AddNumbersImplService">
        <port name="AddNumbersImplPort"
            binding="tns:AddNumbersImplPortBinding">
            <soap:address location="REPLACE_WITH_ACTUAL_URL" />
        </port>
    </service>
</definitions>


[Example 5.2] << build.xml >>

...

<target name="build_client" depends="do-deploy-success, init">
    <antcall target="wsimport">
        <param name="package.name" value="fromjava.client" />
        <param name="binding.file" value="" />
        <param name="wsdl.file"
            value="http://localhost:8088/AddNumbers/AddNumbersImplService?wsdl" />
    </antcall>
    <antcall target="do-compile">
        <param name="javac.excludes" value="fromjava/server/" />
    </antcall>
</target>

...

The following are the files that are generated as the result of creating the portable artifacts from the WSDL file of the web service which will be invoked using the aforementioned wsimport ANT TASK.

fromwsdl/client/AddNumbers.class
fromwsdl/client/AddNumbersImpl.class
fromwsdl/client/AddNumbersImplService.class
fromwsdl/client/AddNumbersResponse.class
fromwsdl/client/ObjectFactory.class
fromwsdl/client/package-info.class

JAXB uses the java bean files, AddNumbers and AddNumbersResponse, to convert a request and response, respectively, for the addNumbers method.

The AddNumbersImpl file implements the service endpoint interface, and the AddNumbersImplService file implements the service interface Java class used as a proxy by the client. The ObjectFactory and packageinfo classes are created by JAXB.

The following is the AddNumbersImplService class which is the service interface class obtained from the WSDL file of the previous remote web service by using wsimport.

[Example 5.3] << AddNumbersImplService.java >>

@WebServiceClient(name = "AddNumbersImplService",
    targetNamespace = "http://server.fromjava/",
    wsdlLocation = "http://localhost:8088/AddNumbers/AddNumbersImplService?wsdl")
public class AddNumbersImplService extends Service {

    private final static URL ADDNUMBERSIMPLSERVICE_WSDL_LOCATION;
    private final static WebServiceException ADDNUMBERSIMPLSERVICE_EXCEPTION;
    private final static QName ADDNUMBERSIMPLSERVICE_QNAME =
            new QName("http://server.fromjava/", "AddNumbersImplService");

    static {
        URL url = null;
        WebServiceException e = null;
        try {
            url = new URL(
                "http://localhost:8088/AddNumbers/AddNumbersImplService?wsdl");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        ADDNUMBERSIMPLSERVICE_WSDL_LOCATION = url;
        ADDNUMBERSIMPLSERVICE_EXCEPTION = e;
    }

    public AddNumbersImplService() {
        super(__getWsdlLocation(), ADDNUMBERSIMPLSERVICE_QNAME);
    }

    public AddNumbersImplService(WebServiceFeature... features) {
        super(__getWsdlLocation(), ADDNUMBERSIMPLSERVICE_QNAME, features);
    }

    public AddNumbersImplService(URL wsdlLocation) {
        super(wsdlLocation, ADDNUMBERSIMPLSERVICE_QNAME);
    }

    public AddNumbersImplService(URL wsdlLocation, WebServiceFeature... features) {
        super(wsdlLocation, ADDNUMBERSIMPLSERVICE_QNAME, features);
    }

    public AddNumbersImplService(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public AddNumbersImplService(URL wsdlLocation, QName serviceName,
                                 WebServiceFeature... features) {
        super(wsdlLocation, serviceName, features);
    }

    @WebEndpoint(name = "AddNumbersImplPort")
    public AddNumbersImpl getAddNumbersImplPort() {
        return super.getPort(new QName("http://server.fromjava/", 
                                       "AddNumbersImplPort"),
                             AddNumbersImpl.class);
    }

    @WebEndpoint(name = "AddNumbersImplPort")
    public AddNumbersImpl getAddNumbersImplPort(WebServiceFeature... features) {
      return super.getPort(new QName("http://server.fromjava/", 
                                     "AddNumbersImplPort"),
                            AddNumbersImpl.class, features);
    }

    private static URL __getWsdlLocation() {
        if (ADDNUMBERSIMPLSERVICE_EXCEPTION!= null) {
            throw ADDNUMBERSIMPLSERVICE_EXCEPTION;
        }
        return ADDNUMBERSIMPLSERVICE_WSDL_LOCATION;
    }
}


The previous service interface is used to obtain the actual proxy object from the client.

The client can obtain the service endpoint interface AddNumbersImpl by using the getAddNumbersImplPort() method of the AddNumbersImplService object, which was instantiated through the AddNumbersImplService constructor of the previous example class.

The following is the AddNumbersImpl class which is a service endpoint interface obtained from the WSDL file of the previous remote web service by using wsimport.

[Example 5.4] << AddNumbersImpl.java >>

@WebService(name = "AddNumbersImpl", targetNamespace = "http://server.fromjava/")
@XmlSeeAlso( { ObjectFactory.class })
public interface AddNumbersImpl {

    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "addNumbers",
        targetNamespace = "http://server.fromjava/",
        className = "fromjava.client.AddNumbers")
    @ResponseWrapper(localName = "addNumbersResponse",
        targetNamespace = "http://server.fromjava/",
        className = "fromjava.client.AddNumbersResponse")
    public int addNumbers(@WebParam(name = "arg0", targetNamespace = "")
    int arg0, @WebParam(name = "arg1", targetNamespace = "")
    int arg1);
}


The service endpoint interface has annotations for converting into Java object, which is used for dynamic binding or at runtime, or XML document. (The service endpoint interface may be used to recreate the WSDL and schema files, but they may not be identical to the WSDL or schema files used to obtain the service endpoint interface.)

The following are Java bean classes, AddNumbers and AddNumbersResponse, used by JAXB to convert a request and response of the addNumbers method into a Java object or XML document.

[Example 5.5] << AddNumbers.java >>

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "addNumbers", propOrder = { "arg0", "arg1" })
public class AddNumbers {

    protected int arg0;

    protected int arg1;

    public int getArg0() {
        return arg0;
    }

    public void setArg0(int value) {
        this.arg0 = value;
    }

    public int getArg1() {
        return arg1;
    }

    public void setArg1(int value) {
        this.arg1 = value;
    }
}


[Example 5.6] << AddNumbersResponse.java >>

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "addNumbersResponse", propOrder = { "_return" })
public class AddNumbersResponse {

    @XmlElement(name = "return")
    protected int _return;

    public int getReturn() {
        return _return;
    }

    public void setReturn(int value) {
        this._return = value;
    }
}


The two Java bean classes, AddNumbers and AddNumbersResponse, are message elements in the WSDL file of the remote web service.

5.2.2. Java SE Client Invocation

This section describes how to create and invoke a client class, that contains the logic for invoking a remote web service, by using client portable artifacts obtained in the "5.2.1. Creating Client Artifacts" section.

5.2.2.1. Creating a Java SE Client Program

Create an AddNumbersImplService object, which is a service interface obtained in the previous example, and then obtain an object which implements the service endpoint interface AddNumbersImpl. The object contains logic for invoking a remote web service through a dynamic proxy. Now call a method to invoke the actual web service by using the object.

The following is a sample code that invokes a remote web service with portable artifacts which were obtained in the previous wsimport ANT TASK execution.

[Example 5.7] << AddNumbersClient.java >>

public class AddNumbersClient {

    public static void main(String[] args) {
       AddNumbersImpl port = new AddNumbersImplService().getAddNumbersImplPort();

       int number1 = 10;
       int number2 = 20;

       System.out.println("##############################################");
       System.out.println("### JAX-WS Webservices examples - fromjava ###");
       System.out.println("##############################################");
       System.out.println("Invoking addNumbers(" + number1 + ", " + number2 + ")");
       int result = port.addNumbers(number1, number2);
       System.out.println("Result: " + result);
    }
}

5.2.2.2. Invoking a Java SE Client Program

This section discusses how to deploy a web service, which is implemented by using the classes and other configuration files from the previous examples, and execute the client program.

The client program that accesses a remote web service is invoked by using the same method regardless of whether it is implemented from Java or WSDL.

If implemented from Java, create the service in the fromjava directory, and if implemented from WSDL file, create it in the fromwsdl directory. Use the following command to deploy the service to JEUS 8.

$ ant build deploy

The client must be built after the service has been successfully deployed. Since the Java SE client goes through the wsimport process, the client can only be built once deployment has been completed.

Create the client and invoke the service as in the following.

$ ant run
...

run:
     [java] ##################################################
     [java] ##### JAX-WS Webservices examples - fromjava #####
     [java] ##################################################
     [java] Invoking addNumbers(10, 20)
     [java] Result: 30

...

BUILD SUCCESSFUL

The console will show that the client has invoked the service and received the result successfully.

5.2.3. Java EE Client Invocation

This section explains how to use the Java EE method to create and invoke a client that calls a web service generated through the WSDL file from the previous section. It is assumed that the client portable artifacts have already been obtained as stated in the "5.2.1. Creating Client Artifacts" section.

5.2.3.1. Creating a Java EE Client Program

In generating Java EE clients for a JAX-RPC web service, the <service-ref> element is added to the web.xml file of a servlet or the ejb-jar.xml file of an EJB. This way, the information required to create a client proxy for a web service gets registered with the JNDI. However, the @WebServiceRef annotation needs to be configured to generate Java EE clients for a JAX-WS web service.

The following example shows how to configure the @WebServiceRef Annotation.

...
@WebServiceRef(wsdlLocation="http://host:port/TmaxService/TmaxService?wsdl)
static TmaxServiceImplService tsvc;
...

Declare a client Java class member variable with the @WebServiceRef annotation by using the AddNumbersService interface. The member variable will automatically inject its value into a servlet container for a servlet or into an EJB container for an EJB, even if there is no set method when the client class is initialized at runtime.

By doing this, AddNumbersPortType, an object which implements the service endpoint interface, can be obtained. The object contains logic for invoking a remote web service through a dynamic proxy. This object can be used to call the method that invokes the actual web service.

The following shows a client program that invokes a remote web service by using portable artifacts obtained through the wsimport ANT TASK execution in the previous example.

[Example 5.8] << AddNumbersClient.java >>

public class AddNumbersClient extends HttpServlet {

    @WebServiceRef
    static AddNumbersImplService svc;

    protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1)
            throws ServletException, IOException {
       AddNumbersImpl port = svc.getAddNumbersImplPort();

       int number1 = 10;
       int number2 = 20;

       System.out.println("##############################################");
       System.out.println("### JAX-WS Webservices examples - fromjava ###");
       System.out.println("##############################################");
       System.out.println("Invoking addNumbers(" + number1 + ", " + number2 + ")");
       int result = port.addNumbers(number1, number2);
       System.out.println("##############################################");
       System.out.println("### JAX-WS Webservices examples - fromjava ###");
       System.out.println("##############################################");
       System.out.println("Result: " + result);
    }
}

5.2.3.2. Invoking a JavaEE Client Program

This section discusses how to deploy a web service, which is implemented using the classes and other configuration files from previous examples, and execute the Java EE client program. The client program that accesses a remote web service is invoked by using the same method regardless of whether it is implemented from Java or WSDL.

If implemented from Java, create the service in the fromjava directory, and if implemented from WSDL file, create it in the fromwsdl directory. Use the following command to deploy the service to JEUS 8.

$ ant build deploy

The client must be built after the service has been successfully deployed. Since the Java SE client goes through the wsimport process, the client can only be built once deployment has been completed.

Create the client and invoke the service as in the following.

$ ant run
...

##############################################
### JAX-WS Webservices examples - fromjava ###
##############################################
Invoking addNumbers(10, 20)

...

##############################################
### JAX-WS Webservices examples - fromjava ###
##############################################
Result: 30

...

After entering the previous commands in the console, the web browser can be used to view the server logs to check that the client servlet has invoked the service and received the result successfully.

5.3. Web Service Invocation Using Dispatch Method

Invoking web services by using the dispatch method is intended for developers who prefer handling the XML configuration at the XML level by using the java.lang.transform.Source or javax.xml.soap.SOAPMessage interfaces. Web service invocation using the dispatch method can be done in the message or payload mode, and can be used to create REST web services through XML/HTTP binding (javax.activation.DataSource).

For more information, refer to "Chapter 8. Provider and Dispatch Interfaces".