7 Roadmap for Developing JAX-WS Web Service Clients

This chapter presents best practices for developing WebLogic web service clients for Java API for XML Web Services (JAX-WS) for WebLogic Server 12.1.3.

Table 7-1 lists each best practice and is followed by an example that illustrates the best practices presented. The best practices are described in more detail later in this document.

For additional best practices, refer to the following sections:

Note:

In the following table, client instance can be a port or a Dispatch instance.

Table 7-1 Roadmap for Developing Web Service Clients

Best Practice Description

Synchronize use of client instances.

Create client instances as you need them; do not store them long term.

Use a stored list of features, including client ID, to create client instances.

Define all features for the web service client instance, including client ID, so that they are consistent each time the client instance is created. For example:

_service.getBackendServicePort(_features);

Explicitly define the client ID.

Use the ClientIdentityFeature to define the client ID explicitly. This client ID is used to group statistics and other monitoring information, and for reporting runtime validations, and so on. For more information, see Managing Client Identity.

Note: Oracle strongly recommends that you define the client ID explicitly. If not explicitly defined, the server generates the client ID automatically, which may not be user-friendly.

Explicitly close client instances when processing is complete.

For example:

((java.io.Closeable)port).close();

If not closed explicitly, the client instance will be closed automatically when it goes out of scope.

Note: The client ID remains registered and visible until the container (Web application or EJB) is deactivated. For more information, see Client Identity Lifecycle.


The following example illustrates best practices for developing web service clients.

Example 7-1 Web Service Client Best Practices Example

import java.io.IOException;
import java.util.*;
 
import javax.servlet.*;
import javax.xml.ws.*;
 
import weblogic.jws.jaxws.client.ClientIdentityFeature;
 
/**
 * Example client for invoking a web service.
 */
public class BestPracticeClient
  extends GenericServlet {
 
  private BackendServiceService _service;
  private WebServiceFeature[] _features;
  private ClientIdentityFeature _clientIdFeature;
 
  @Override
  public void init()
    throws ServletException {
 
    // Create a single instance of a web service as it is expensive to create repeatedly.
    if (_service == null) {
      _service = new BackendServiceService();
    }
 
    // Best Practice: Use a stored list of features, per client ID, to create client instances.
    // Define all features for the web service client instance, per client ID, so that they are 
    // consistent each time the client instance is created. For example: 
    // _service.getBackendServicePort(_features);
 
    List<WebServiceFeature> features = new ArrayList<WebServiceFeature>();
 
    // Best Practice: Explicitly define the client ID.
    // TODO: Maybe allow ClientIdentityFeature to store other features, and
    //       then create new client instances simply by passing the
    //       ClientIdentityFeature (and the registered features are used).
    _clientIdFeature = new ClientIdentityFeature("MyBackendServiceClient");
    features.add(_clientIdFeature);
 
    // Set the features used when creating clients with
    // the client ID "MyBackendServiceClient". The features are stored in an array to 
    // reinforce that the list should be treated as immutable.
    _features = features.toArray(new WebServiceFeature[features.size()]);
  }
 
  @Override
  public void service(ServletRequest req, ServletResponse res)
    throws ServletException, IOException {
 
    // ... Read the servlet request ...
 
    // Best Practice: Synchronize use of client instances.
    // Create a web service client instance to talk to the backend service.
    // Note, at this point the client ID is 'registered' and becomes
    // visible to monitoring tools such as the Administration Console and WLST.
    // The client ID *remains* registered and visible until the container
    // (the Web application hosting our servlet) is deactivated (undeployed).
    //
    // A client ID can be used when creating multiple client instances (port or Dispatch client).
    // The client instance should be created with the same set of features each time, and should
    // use the same service class and refer to the same port type. 
    // A given a client ID should be used for a given port type, but not across port types.
    // It can be used for both port and Dispatch clients.
    BackendService port =
      _service.getBackendServicePort(_features);
 
    // Set the endpoint address for BackendService.
    ((BindingProvider)port).getRequestContext().
      put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
          "http://localhost:7001/BestPracticeService/BackendService");
 
    // Print out the explicit client ID, and compare it to the client ID 
    // that would have been generated automatically for the client instance.
    showClientIdentity();
 
    // Make the invocation on our real port
    String request = "Make a cake";
    System.out.println("Invoking DoSomething with request: " + request);
    String response = port.doSomething(request);
    System.out.println("Got response: " + response);
    res.getWriter().write(response);
 
    // Best Practice: Explicitly close client instances when processing is complete.
    // If not closed, the client instance will be closed automatically when it goes out of 
    // scope. Note, this client ID will remain registered and visible until our
    // container (Web application) is undeployed.
    ((java.io.Closeable)port).close();
  }
 
  /**
    // Print out the client's full ID, which is a combination of
    // the client ID provided above and qualifiers from the application and
    // Web application that contain the client. Then compare this with the client ID that
    // would have been generated for the client instance if not explicitly set.
    //
  private void showClientIdentity()
    throws IOException {
 
    System.out.println("Client Identity is: " + _clientIdFeature.getClientId());
 
    // Create a client instance without explicitly defining the client ID to view the 
    // client ID that is generated automatically.
    ClientIdentityFeature dummyClientIdFeature =
      new ClientIdentityFeature(null);
    BackendService dummyPort =
      _service.getBackendServicePort(dummyClientIdFeature);
    System.out.println("Generated Client Identity is: " +
                       dummyClientIdFeature.getClientId());
    // Best Practice: Explicitly close client instances when processing is complete.
    // If not closed, the client instance will be closed automatically when it goes out of 
    // scope. Note, this client ID will remain registered and visible until our
    // container (Web application) is undeployed.
    ((java.io.Closeable)dummyPort).close();
  }
 
  @Override
  public void destroy() {
  }
}