Consuming the Simple Greeting Service

To use your Web Service you need a client. For the purposes of this exercise, this client will be a standard Java class with a main method. However, it could also be a J2EE component such as a JSP or EJB. The differences with such clients are discussed later.

To call the Web Service from a client, you could use low-level APIs to create and send SOAP messages. However, one of the main intentions of JAX-RPC is to provide the developer with a familiar development model. Hence, you will again use the tools to create a stub (or proxy) that represents the service for the client. The stub exposes Java methods that match the SOAP operations supported by the server. The client application can simply call these Java methods to invoke the functionality of the service. The J2EE RI tool used is again wscompile. You can use wscompile to take the WSDL description of the deployed service and create client-side stubs through which to invoke the service.

In this case the configuration file needs client-focused information provided in a wscompile configuration file similar to the one used earlier to generate the WSDL in the section “Web Service Compiler Configuration File.” The file still has a root element of configuration, but in place of the service element you use a wsdl element. The packageName attribute of the wsdl element indicates that the generated Java classes and interfaces should reside in the package client. The location attribute specifies that the WSDL file to use should be retrieved from the deployed service. This means that it contains the correct endpoint location information for the service you deployed. The client configuration file is shown in Listing 20.6.

Listing 20.6. wscompile Client Configuration File (config-client.xml)
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
    <wsdl location="http://localhost:8000/wsgreeting
/GreetingService?WSDL"packageName="client"/>
</configuration>

NOTE

Do not use the original WSDL file without the location information when creating your client. Stubs generated from WSDL that do not contain a valid endpoint will fail at runtime unless one is set programmatically. This is a more flexible mechanism, but it makes them more complicated to use. Dynamic endpoint allocation is fine later, but for the time being we will be working with the endpoint URL encoded in the WSDL.


When you call wscompile, you should ask it to generate the client scaffolding you need (-gen:client). If you are working in a development environment that does not provide code completion based on introspection, you should also specify the –keep option so that the .java files are still around for inspection:

wscompile –gen:client -d classes –keep –s build/generatedproxy ws/config-client.xml

The client-side scaffolding shares many files with the server-side scaffolding, including any complex types, serializers, and a serializer registry to map types to serializers. However, the following client-specific artifacts are also generated:

  • Greeting interface— This is generated from the WSDL port description. It is almost identical to the remote Java Greeting interface from which the WSDL was generated.

  • GreetingService interface— This defines a single method getGreetingPort() that returns a client-side proxy for the service implementing the Greeting interface.

  • GreetingService_Impl class— This is a factory class that represents the Web Service as a whole. You can obtain client-side proxies from instances of this class. For your simple service, this will just serve client-side proxies that implement the Greeting interface.

  • Greeting_Stub class— This is the client-side proxy itself that implements the client-side Java Greeting interface generated from the WSDL.

You can build a Web Service client using these generated classes. To use these classes, you should either import the namespace in which they were generated (client derived from the client configuration file as shown in Listing 20.6) or place your client class in the same namespace:

package client;

You can create your client code in a simple main() method. Don't forget that all these method calls can generate RemoteExceptions, so be sure to place them all inside a try/catch block. The first thing to do is instantiate the factory that represents the Web Service:

GreetingService serviceProxy = new GreetingService_Impl();

From this service proxy, you can then obtain an interface proxy:

Greeting interfaceProxy = serviceProxy.getGreetingPort();

As the interface proxy implements the client-side Greeting interface, you can call the sayHelloTo() method on this, passing the name of the person to greet:

String response = interfaceProxy.sayHelloTo("Fred");

This call will trigger a SOAP request to the simple Greeting Web Service. The service will prepend the message you defined in your implementation and return the result. The full code for a sample simple Web Service client is shown in Listing 20.7.

Listing 20.7. Client for Simple Web Service (GreetingClient.java)
package client;

public class GreetingClient
{
    public static void main(String[] args)
    {
        try
        {
            GreetingService serviceProxy = new GreetingService_Impl();

            Greeting interfaceProxy = serviceProxy.getGreetingPort();

            String response = interfaceProxy.sayHelloTo("Fred");
            System.out.println("Response from greeting service was: " + response);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
}

You compile and run your client as you would any other Java application, but ensure that the generated client-side classes are on your classpath. To generate the client-side scaffolding, compile the pre-provided client class and run it, use the following Ant directive:

asant run

This will communicate with the web service you deployed earlier. You should see the following message:

Response from greeting service was: Hi there Fred

So, now you have created, deployed, and invoked a simple Web Service under J2EE using JAX-RPC.

One final question before moving on from here is how to re-target this Web Service client at a different endpoint. By default, the stub uses the endpoint URL encoded into the WSDL document. As you move from development into test, staging, and live environments, the URL of the endpoint will probably change. However, you do not necessarily want to regenerate your proxies at every stage. Instead, you can set the endpoint for the stub to use as follows (in this example “ELEPHANT” is the name of the host on which the service is deployed):

javax.xml.rpc.Stub stub = (javax.xml.rpc.Stub)interfaceProxy;
stub._setProperty(ENDPOINT_ADDRESS_PROPERTY,
                  "http://ELEPHANT:8000/wsgreeting/DIFFERENT_NAME");

You can then define the endpoint address as a property that can be picked up by the running program.

CAUTION

When re-targeting a proxy at a different endpoint, you should ensure that the endpoint supports the same port type—even down to the name of each part of each message. Some services may be forgiving on this (that is, the names could differ and it will still accept the operation invocation), but others are not.


..................Content has been hidden....................

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