Programming Web Services for WebLogic Server

     Previous  Next    Open TOC in new window  Open Index in new window  View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

Invoking Web Services

The following sections describe how to invoke WebLogic Web Services:

Note: The following sections do not include information about invoking message-secured Web Services; for that topic, see the message security section, in particular Updating a Client Application to Invoke a Message-Secured Web Service.

 


Overview of Web Services Invocation

Invoking a Web Service refers to the actions that a client application performs to use the Web Service. Client applications that invoke Web Services can be written using any technology: Java, Microsoft .NET, and so on.

Note: In this context, a client application can be two types of clients: One is a stand-alone client that uses the WebLogic client classes to invoke a Web Service hosted on WebLogic Server or on other application servers. In this document, a stand-alone client is a client that has a runtime environment independent of WebLogic Server. The other type of client application that invokes a Web Service runs inside a J2EE component deployed to WebLogic Server, such as an EJB or another Web Service.

The sections that follow describe how to use BEA’s implementation of the JAX-RPC specification (Version 1.1) to invoke a Web Service from a Java client application. You can use this implementation to invoke Web Services running on any application server, both WebLogic and non-WebLogic. In addition, you can create a stand-alone client application or one that runs as part of a WebLogic Server.

WARNING: You cannot use a dynamic client to invoke a Web Service operation that implements user-defined data types as parameters or return values. A dynamic client uses the JAX-RPC Call interface. Standard (static) clients use the Service and Stub JAX-RPC interfaces, which correctly invoke Web Services that implement user-defined data types.

Types of Client Applications

This section describes two different types of client applications:

JAX-RPC

The Java API for XML based RPC (JAX-RPC) is a Sun Microsystems specification that defines the APIs used to invoke a Web Service. WebLogic Server implements the JAX-RPC 1.1 specification.

The following table briefly describes the core JAX-RPC interfaces and classes.

Table 9-1 JAX-RPC Interfaces and Classes
javax.xml.rpc Interface or Class
Description
Service
Main client interface.
ServiceFactory
Factory class for creating Service instances.
Stub
Base class of the client proxy used to invoke the operations of a Web Service.
Call
Used to dynamically invoke a Web Service.

Note: For Dynamic Invocation Interface (DII) Web Service clients to use WebLogic Server 9.x Web Service stack, you must specify the system propery -Djavax.xml.rpc.ServiceFactory = weblogic.wsee.jaxrpc.ServiceFactoryImpl.

JAXRPCException
Exception thrown if an error occurs while invoking a Web Service.

For detailed information on JAX-RPC, see http://java.sun.com/xml/jaxrpc/index.html.

The clientgen Ant Task

The clientgen WebLogic Web Services Ant task generates, from an existing WSDL file, the client artifacts that client applications use to invoke both WebLogic and non-WebLogic Web Services. These artifacts include:

For additional information about the clientgen Ant task, such as all the available attributes, see Ant Task Reference.

WARNING: The fully qualified name of the clientgen Ant task supported in this release of WebLogic Server is weblogic.wsee.tools.anttasks.ClientGenTask. This is different from the clientgen Ant task supported in version 8.1 of WebLogic Server, which is weblogic.webservice.clientgen.
WARNING: Although the 8.1 clientgen Ant task is still provided in this release of WebLogic Server, it is deprecated. If you want to generate the client artifacts to invoke a 9.X WebLogic Web Service, be sure you use the 9.X version of clientgen and not the 8.1 version. For example, if you have upgraded an 8.1 Web Service to 9.2, but your Ant scripts explicitly call the 8.1 clientgen Ant task by specifying its fully qualified name, then you must update your Ant scripts to call the 9.X clientgen instead.

Examples of Clients That Invoke Web Services

WebLogic Server includes examples of creating and invoking WebLogic Web Services in the WL_HOME/samples/server/examples/src/examples/webservices directory, where WL_HOME refers to the main WebLogic Server directory.

For detailed instructions on how to build and run the examples, open the WL_HOME/samples/server/docs/index.html Web page in your browser and expand the WebLogic Server Examples->Examples->API->Web Services node.

 


Invoking a Web Service from a Stand-alone Client: Main Steps

In the following procedure it is assumed that you use Ant in your development environment to build your client application, compile Java files, and so on, and that you have an existing build.xml file that you want to update with Web Services client tasks.

For general information about using Ant in your development environment, see Creating the Basic Ant build.xml File. For a full example of a build.xml file used in this section, see Sample Ant Build File for a Stand-Alone Java Client.

To create a Java stand-alone client application that invokes a Web Service:

  1. Open a command shell and set your environment.
  2. On Windows NT, execute the setDomainEnv.cmd command, located in your domain directory. The default location of WebLogic Server domains is BEA_HOME\user_projects\domains\domainName, where BEA_HOME is the top-level installation directory of the BEA products and domainName is the name of your domain.

    On UNIX, execute the setDomainEnv.sh command, located in your domain directory. The default location of WebLogic Server domains is BEA_HOME/user_projects/domains/domainName, where BEA_HOME is the top-level installation directory of the BEA products and domainName is the name of your domain.

  3. Update your build.xml file to execute the clientgen Ant task to generate the needed client-side artifacts to invoke a Web Service.
  4. See Using the clientgen Ant Task To Generate Client Artifacts.

  5. Get information about the Web Service, such as the signature of its operations and the name of the ports.
  6. See Getting Information About a Web Service.

  7. Write the client application Java code that includes code for invoking the Web Service operation.
  8. See Writing the Java Client Application Code to Invoke a Web Service.

  9. Compile and run your Java client application.
  10. See Compiling and Running the Client Application.

Using the clientgen Ant Task To Generate Client Artifacts

Update your build.xml file, adding a call to the clientgen Ant task, as shown in the following example:

  <taskdef name="clientgen"
classname="weblogic.wsee.tools.anttasks.ClientGenTask" />
  <target name="build-client">
    <clientgen
wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL"
destDir="clientclasses"
packageName="examples.webservices.simple_client"/>
</target>

Before you can execute the clientgen WebLogic Web Service Ant task, you must specify its full Java classname using the standard taskdef Ant task.

You must include the wsdl and destDir attributes of the clientgen Ant task to specify the WSDL file from which you want to create client-side artifacts and the directory into which these artifacts should be generated. The packageName attribute is optional; if you do not specify it, the clientgen task uses a package name based on the targetNamespace of the WSDL.

Note: The clientgen Ant task also provides the destFile attribute if you want the Ant task to automatically compile the generated Java code and package all artifacts into a JAR file. For details and an example, see clientgen.

If the WSDL file specifies that user-defined data types are used as input parameters or return values of Web Service operations, clientgen automatically generates a JavaBean class that is the Java representation of the XML Schema data type defined in the WSDL. The JavaBean classes are generated into the destDir directory.

Note: The package of the Java user-defined data type is based on the XML Schema of the data type in the WSDL, which is different from the package name of the JAX-RPC stubs.

See Sample Ant Build File for a Stand-Alone Java Client for a full sample build.xml file that contains additional targets from those described in this procedure, such as clean.

To execute the clientgen Ant task, along with the other supporting Ant tasks, specify the build-client target at the command line:

prompt> ant build-client

See the clientclasses directory to view the files and artifacts generated by the clientgen Ant task.

Getting Information About a Web Service

You need to know the name of the Web Service and the signature of its operations before you write your Java client application code to invoke an operation. There are a variety of ways to find this information.

The best way to get this information is to use the clientgen Ant task to generate the Web Service-specific JAX-RPC stubs and look at the generated *.java files. These files are generated into the directory specified by the destDir attribute, with subdirectories corresponding to either the value of the packageName attribute, or, if this attribute is not specified, to a package based on the targetNamespace of the WSDL.

You can also examine the actual WSDL of the Web Service; see Browsing to the WSDL of the Web Service for details about the WSDL of a deployed WebLogic Web Service. The name of the Web Service is contained in the <service> element, as shown in the following excerpt of the TraderService WSDL:

  <service name="TraderService">
<port name="TraderServicePort"
binding="tns:TraderServiceSoapBinding">
...
</port>
</service>

The operations defined for this Web Service are listed under the corresponding <binding> element. For example, the following WSDL excerpt shows that the TraderService Web Service has two operations, buy and sell (for clarity, only relevant parts of the WSDL are shown):

  <binding name="TraderServiceSoapBinding" ...>
...
<operation name="sell">
...
</operation>
<operation name="buy">
</operation>
</binding>

Writing the Java Client Application Code to Invoke a Web Service

In the following code example, a stand-alone application invokes a Web Service operation.

The client application takes a single argument: the WSDL of the Web Service. The application then uses standard JAX-RPC API code and the Web Service-specific implementation of the Service interface, generated by clientgen, to invoke an operation of the Web Service.

The example also shows how to invoke an operation that has a user-defined data type (examples.webservices.complex.BasicStruct) as an input parameter and return value. The clientgen Ant task automatically generates the Java code for this user-defined data type.

package examples.webservices.simple_client;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
// import the BasicStruct class, used as a param and return value of the
// echoComplexType operation. The class is generated automatically by
// the clientgen Ant task.
import examples.webservices.complex.BasicStruct;
/**
* This is a simple stand-alone client application that invokes the
* the echoComplexType operation of the ComplexService Web service.
*
* @author Copyright (c) 2005 by BEA Systems. All Rights Reserved.
*/
public class Main {
  public static void main(String[] args)
throws ServiceException, RemoteException{
    ComplexService service = new ComplexService_Impl (args[0] + "?WSDL");
ComplexPortType port = service.getComplexServicePort();
    BasicStruct in = new BasicStruct();
    in.setIntValue(999);
in.setStringValue("Hello Struct");
    BasicStruct result = port.echoComplexType(in);
System.out.println("echoComplexType called. Result: " + result.getIntValue() + ", " + result.getStringValue());
}
}

In the preceding example:

The method of your application that invokes the Web Service operation must throw or catch java.rmi.RemoteException and javax.xml.rpc.ServiceException, both of which are thrown from the generated JAX-RPC stubs.

Compiling and Running the Client Application

Add javac tasks to the build-client target in the build.xml file to compile all the Java files (both of your client application and those generated by clientgen) into class files, as shown by the bold text in the following example

  <target name="build-client">
    <clientgen
wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL"
destDir="clientclasses"
packageName="examples.webservices.simple_client"/>
    <javac
srcdir="clientclasses"
destdir="clientclasses"
includes="**/*.java"/>
    <javac
srcdir="src"
destdir="clientclasses"
includes="examples/webservices/simple_client/*.java"/>
</target>

In the example, the first javac task compiles the Java files in the clientclasses directory that were generated by clientgen, and the second javac task compiles the Java files in the examples/webservices/simple_client subdirectory of the current directory; where it is assumed your Java client application source is located.

In the preceding example, the clientgen-generated Java source files and the resulting compiled classes end up in the same directory (clientclasses). Although this might be adequate for proto-typing, it is often a best practice to keep source code (even generated code) in a different directory from the compiled classes. To do this, set the destdir for both javac tasks to a directory different from the srcdir directory. You must also copy the following clientgen-generated files from clientgen’s destination directory to javac’s destination directory, keeping the same sub-directory hierarchy in the destination:

packageName/ServiceName_internaldd.xml
packageName/ServiceName_java_wsdl_mapping.xml
packageName/ServiceName_saved_wsdl.wsdl

where packageName refers to the subdirectory hierarchy that corresponds to the package of the generated JAX-RPC stubs and ServiceName refers to the name of the Web Service.

To run the client application, add a run target to the build.xml that includes a call to the java task, as shown below:

<path id="client.class.path">
<pathelement path="clientclasses"/>
<pathelement path="${java.class.path}"/>
</path>
<target name="run" >
<java
fork="true"
classname="examples.webServices.simple_client.Main"
failonerror="true" >
<classpath refid="client.class.path"/>
<arg line="http://${wls.hostname}:${wls.port}/complex/ComplexService" />
</java>
</target>

The path task adds the clientclasses directory to the CLASSPATH. The run target invokes the Main application, passing it the URL of the deployed Web Service as its single argument.

See Sample Ant Build File for a Stand-Alone Java Client for a full sample build.xml file that contains additional targets from those described in this procedure, such as clean.

Rerun the build-client target to regenerate the artifacts and recompile into classes, then execute the run target to invoke the echoStruct operation:

    prompt> ant build-client run

You can use the build-client and run targets in the build.xml file to iteratively update, rebuild, and run the Java client application as part of your development process.

Sample Ant Build File for a Stand-Alone Java Client

The following example shows a complete build.xml file for generating and compiling a stand-alone Java client. See Using the clientgen Ant Task To Generate Client Artifacts and Compiling and Running the Client Application for explanations of the sections in bold.

<project name="webservices-simple_client" default="all">
  <!-- set global properties for this build -->
  <property name="wls.hostname" value="localhost" />
<property name="wls.port" value="7001" />
  <property name="example-output" value="output" />
<property name="clientclass-dir" value="${example-output}/clientclass" />
  <path id="client.class.path">
<pathelement path="${clientclass-dir}"/>
<pathelement path="${java.class.path}"/>
</path>
  <taskdef name="clientgen"
classname="weblogic.wsee.tools.anttasks.ClientGenTask" />
  <target name="clean" >
<delete dir="${clientclass-dir}"/>
</target>
  <target name="all" depends="clean,build-client,run" />
  <target name="build-client">
    <clientgen
wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL"
destDir="${clientclass-dir}"
packageName="examples.webservices.simple_client"/>
    <javac
srcdir="${clientclass-dir}" destdir="${clientclass-dir}"
includes="**/*.java"/>
    <javac
srcdir="src" destdir="${clientclass-dir}"
includes="examples/webservices/simple_client/*.java"/>
</target>
  <target name="run" >
<java fork="true"
classname="examples.webservices.simple_client.Main"
failonerror="true" >
<classpath refid="client.class.path"/>
<arg line="http://${wls.hostname}:${wls.port}/complex/ComplexService"
/>
</java>
</target>
</project>

 


Invoking a Web Service from Another Web Service

Invoking a Web Service from within a WebLogic Web Service is similar to invoking one from a stand-alone Java application, as described in Invoking a Web Service from a Stand-alone Client: Main Steps. However, instead of using the clientgen Ant task to generate the JAX-RPC stubs of the Web Service to be invoked, you use the <clientgen> child element of the <jws> element, inside the jwsc Ant task that compiles the invoking Web Service. In the JWS file that invokes the other Web Service, however, you still use the same standard JAX-RPC APIs to get Service and PortType instances to invoke the Web Service operations. This section describes the differences between invoking a Web Service from a client in a J2EE component and invoking from a stand-alone client.

It is assumed that you have read and understood Invoking a Web Service from a Stand-alone Client: Main Steps. It is also assumed that you use Ant in your development environment to build your client application, compile Java files, and so on, and that you have an existing build.xml that builds a Web Service that you want to update to invoke another Web Service.

The following list describes the changes you must make to the build.xml file that builds your client Web Service, which will invoke another Web Service. See Sample build.xml File for a Web Service Client for the full sample build.xml file:

The following bullets describe the changes you must make to the JWS file that implements the client Web Service; see Sample JWS File That Invokes a Web Service for the full JWS file example.

Sample build.xml File for a Web Service Client

The following sample build.xml file shows how to create a Web Service that itself invokes another Web Service; the relevant sections that differ from the build.xml for building a simple Web Service that does not invoke another Web Service are shown in bold.

The build-service target in this case is very similar to a target that builds a simple Web Service; the only difference is that the jwsc Ant task that builds the invoking Web Service also includes a <clientgen> child element of the <jws> element so that jwsc also generates the required JAX-RPC client stubs.

<project name="webservices-service_to_service" default="all">
  <!-- set global properties for this build -->
  <property name="wls.username" value="weblogic" />
<property name="wls.password" value="weblogic" />
<property name="wls.hostname" value="localhost" />
<property name="wls.port" value="7001" />
<property name="wls.server.name" value="myserver" />
  <property name="ear.deployed.name" value="ClientServiceEar" />
<property name="example-output" value="output" />
<property name="ear-dir" value="${example-output}/ClientServiceEar" />
<property name="clientclass-dir" value="${example-output}/clientclasses" />
  <path id="client.class.path">
<pathelement path="${clientclass-dir}"/>
<pathelement path="${java.class.path}"/>
</path>
  <taskdef name="jwsc"
classname="weblogic.wsee.tools.anttasks.JwscTask" />
  <taskdef name="clientgen"
classname="weblogic.wsee.tools.anttasks.ClientGenTask" />
  <taskdef name="wldeploy"
classname="weblogic.ant.taskdefs.management.WLDeploy"/>
  <target name="all" depends="clean,build-service,deploy,client" />
  <target name="clean" depends="undeploy">
<delete dir="${example-output}"/>
</target>
  <target name="build-service">
    <jwsc
srcdir="src"
destdir="${ear-dir}" >
        <jws
file="examples/webservices/service_to_service/ClientServiceImpl.java">
<clientgen
wsdl="http://${wls.hostname}:${wls.port}/complex/ComplexService?WSDL"
packageName="examples.webservices.service_to_service" />
</jws>
    </jwsc>
  </target>
  <target name="deploy">
<wldeploy action="deploy" name="${ear.deployed.name}"
source="${ear-dir}" user="${wls.username}"
password="${wls.password}" verbose="true"
adminurl="t3://${wls.hostname}:${wls.port}"
targets="${wls.server.name}" />
</target>
  <target name="undeploy">
<wldeploy action="undeploy" name="${ear.deployed.name}"
failonerror="false"
user="${wls.username}"
password="${wls.password}" verbose="true"
adminurl="t3://${wls.hostname}:${wls.port}"
targets="${wls.server.name}" />
</target>
  <target name="client">
    <clientgen
wsdl="http://${wls.hostname}:${wls.port}/ClientService/ClientService?WSDL"
destDir="${clientclass-dir}"
packageName="examples.webservices.service_to_service.client"/>
    <javac
srcdir="${clientclass-dir}" destdir="${clientclass-dir}"
includes="**/*.java"/>
    <javac
srcdir="src" destdir="${clientclass-dir}"
includes="examples/webservices/service_to_service/client/**/*.java"/>
  </target>
  <target name="run">
<java classname="examples.webservices.service_to_service.client.Main"
fork="true"
failonerror="true" >
<classpath refid="client.class.path"/>
<arg
line="http://${wls.hostname}:${wls.port}/ClientService/ClientService"/>
    </java>
  </target>
</project>

Sample JWS File That Invokes a Web Service

The following sample JWS file, called ClientServiceImpl.java, implements a Web Service called ClientService that has an operation that in turn invokes the echoComplexType operation of a Web Service called ComplexService. This operation has a user-defined data type (BasicStruct) as both a parameter and a return value. The relevant code is shown in bold and described after the example.

package examples.webservices.service_to_service;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import javax.jws.WebService;
import javax.jws.WebMethod;
import weblogic.jws.WLHttpTransport;
// Import the BasicStruct data type, generated by clientgen and used
// by the ComplexService Web Service
import examples.webservices.complex.BasicStruct;
// Import the JAX-RPC Stubs for invoking the ComplexService Web Service.
// Stubs generated by clientgen
import examples.webservices.service_to_service.ComplexPortType;
import examples.webservices.service_to_service.ComplexService_Impl;
import examples.webservices.service_to_service.ComplexService;
@WebService(name="ClientPortType", serviceName="ClientService",
targetNamespace="http://examples.org")
@WLHttpTransport(contextPath="ClientService", serviceUri="ClientService",
portName="ClientServicePort")
public class ClientServiceImpl {
  @WebMethod()
public String callComplexService(BasicStruct input, String serviceUrl)
throws ServiceException, RemoteException
{
    // Create service and port stubs to invoke ComplexService
ComplexService service = new ComplexService_Impl(serviceUrl + "?WSDL");
ComplexPortType port = service.getComplexServicePort();
    // Invoke the echoComplexType operation of ComplexService
BasicStruct result = port.echoComplexType(input);
System.out.println("Invoked ComplexPortType.echoComplexType." );
    return "Invoke went okay!  Here's the result: '" + result.getIntValue() + ",  " + result.getStringValue() + "'";
  }
}

Follow these guidelines when programming the JWS file that invokes another Web Service; code snippets of the guidelines are shown in bold in the preceding example:

 


Using a Proxy Server When Invoking a Web Service

You can use a proxy server to proxy requests from a client application to an application server (either WebLogic or non-WebLogic) that hosts the invoked Web Service. You typically use a proxy server when the application server is behind a firewall. There are two ways to specify the proxy server in your client application: programmatically using the WebLogic HttpTransportInfo API or using system properties.

For a complete example of using a proxy server when invoking a Web Service, see the example on the dev2dev Code Example site.

Using the HttpTransportInfo API to Specify the Proxy Server

You can programmatically specify within the Java client application itself the details of the proxy server that will proxy the Web Service invoke by using the standard java.net.* classes and the WebLogic-specific HttpTransportInfo API. You use the java.net classes to create a Proxy object that represents the proxy server, and then use the WebLogic API and properties to set the proxy server on the JAX-RPC stub, as shown in the following sample client that invokes the echo operation of the HttpProxySampleService Web Service. The code in bold is described after the example:

package dev2dev.proxy.client;
import javax.xml.rpc.Stub;
import java.net.Proxy;
import java.net.InetSocketAddress;
import weblogic.wsee.connection.transport.http.HttpTransportInfo;
/**
* Sample client to invoke a service through a proxy server via
* programmatic API
*/
public class HttpProxySampleClient {
public static void main(String[] args) throws Throwable{
assert args.length == 5;
String endpoint = args[0];
String proxyHost = args[1];
String proxyPort = args[2];
String user = args[3];
String pass = args[4];
    //create service and port
HttpProxySampleService service = new HttpProxySampleService_Impl();
HttpProxySamplePortType port = service.getHttpProxySamplePortTypeSoapPort();
    //set endpoint address
((Stub)port)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, endpoint);
    //set proxy server info
Proxy p = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, Integer.parseInt(proxyPort)));
HttpTransportInfo info = new HttpTransportInfo();
info.setProxy(p);
((Stub)port)._setProperty("weblogic.wsee.connection.transportinfo",info);
    //set proxy-authentication info
((Stub)port)._setProperty("weblogic.webservice.client.proxyusername",user);
((Stub)port)._setProperty("weblogic.webservice.client.proxypassword",pass);
    //invoke
String s = port.echo("Hello World!");
System.out.println("echo: " + s);
}
}

The sections of the preceding example to note are as follows:

Using System Properties to Specify the Proxy Server

When you use system properties to specify the proxy server, you write your client application in the standard way, and then specify the following system properties when you execute the client application:

where proxyHost is the name of the host computer on which the proxy server is running, proxyPort is the port to which the proxy server is listening, proxyUsername is the authenticated proxy server user and proxyPassword is the user’s password.

The following excerpt from an Ant build script shows an example of setting these system properties when invoking a client application called clients.InvokeMyService:

  <target name="run-client">
<java fork="true"
classname="clients.InvokeMyService"
failonerror="true">
<classpath refid="client.class.path"/>
<arg line="${http-endpoint}"/>
<jvmarg line=
"-DproxySet=true
-DproxyHost=${proxy-host}
-DproxyPort=${proxy-port}
-Dweblogic.webservice.client.proxyusername=${proxy-username}
-Dweblogic.webservice.client.proxypassword=${proxy-passwd}"
/>
</java>
</target>

 


Client Considerations When Redeploying a Web Service

WebLogic Server supports production redeployment, which means that you can deploy a new version of an updated WebLogic Web Service alongside an older version of the same Web Service.

WebLogic Server automatically manages client connections so that only new client requests are directed to the new version. Clients already connected to the Web Service during the redeployment continue to use the older version of the service until they complete their work, at which point WebLogic Server automatically retires the older Web Service. If the client is connected to a conversational or reliable Web Service, its work is considered complete when the existing conversation or reliable messaging sequence is explicitly ended by the client or because of a timeout.

You can continue using the old client application with the new version of the Web Service, as long as the following Web Service artifacts have not changed in the new version:

If any of these artifacts have changed, you must regenerate the JAX-RPC stubs used by the client application by re-running the clientgen Ant task.

For example, if you change the signature of an operation in the new version of the Web Service, then the WSDL file that describes the new version of the Web Service will also change. In this case, you must regenerate the JAX-RPC stubs. If, however, you simply change the implementation of an operation, but do not change its public contract, then you can continue using the existing client application.

 


Creating and Using Client-Side SOAP Message Handlers

The section Creating and Using SOAP Message Handlers describes how to create server-side SOAP message handlers that execute as part of the Web Service running on WebLogic Server. You can also create client-side handlers that execute as part of the client application that invokes a Web Service operation. In the case of a client-side handler, the handler executes twice:

You can configure client-side SOAP message handlers for both stand-alone clients and clients that run inside of WebLogic Server.

You create the actual Java client-side handler in the same way you create a server-side handler: write a Java class that extends the javax.xml.rpc.handler.GenericHandler abstract class. In many cases you can use the exact same handler class on both the Web Service running on WebLogic Server and the client applications that invoke the Web Service. For example, you can write a generic logging handler class that logs all sent and received SOAP messages, both for the server and for the client.

Similar to the server-side SOAP handler programming, you use an XML file to specify to the clientgen Ant task that you want to invoke client-side SOAP message handlers. However, the XML Schema of this XML file is slightly different, as described in the following procedure.

Using Client-Side SOAP Message Handlers: Main Steps

The following procedure describes the high-level steps to add client-side SOAP message handlers to the client application that invokes a Web Service operation.

It is assumed that you have already created the client application that invokes a deployed Web Service, and that you want to update the client application by adding client-side SOAP message handlers and handler chains. It is also assumed that you have set up an Ant-based development environment and that you have a working build.xml file that includes a target for running the clientgen Ant task. For more information, see Invoking a Web Service from a Stand-alone Client: Main Steps.

  1. Design the client-side SOAP handlers and the handler chain which specifies the order in which they execute. This step is almost exactly the same as that of designing the server-side SOAP message handlers, except the perspective is from the client application, rather than a Web Service.
  2. See Designing the SOAP Message Handlers and Handler Chains.

  3. For each handler in the handler chain, create a Java class that extends the javax.xml.rpc.handler.GenericHandler abstract class. This step is very similar to the corresponding server-side step, except that the handler executes in a chain in the client rather than the server.
  4. See Creating the GenericHandler Class for details about programming a handler class. See Example of a Client-Side Handler Class for an example.

  5. Create the client-side SOAP handler configuration file. This XML file describes the handlers in the handler chain, the order in which they execute, and any initialization parameters that should be sent.
  6. See Creating the Client-Side SOAP Handler Configuration File.

  7. Update the build.xml file that builds your client application, specifying to the clientgen Ant task the name of the SOAP handler configuration file. Also ensure that the build.xml file compiles the handler files into Java classes and makes them available to your client application.
  8. See Specifying the Client-Side SOAP Handler Configuration File to clientgen.

  9. Rebuild your client application by running the relevant task:
  10. prompt> ant build-client

When you next run the client application, the SOAP messaging handlers listed in the configuration file automatically execute before the SOAP request message is sent and after the response is received.

Note: You do not have to update your actual client application to invoke the client-side SOAP message handlers; as long as you specify to the clientgen Ant task the handler configuration file, the generated JAX-RPC stubs automatically take care of executing the handlers in the correct sequence.

Example of a Client-Side Handler Class

The following example shows a simple SOAP message handler class that you can configure for a client application that invokes a Web Service.

package examples.webservices.client_handler.client;
import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.MessageContext;
public class ClientHandler1 extends GenericHandler {
  private QName[] headers;
  public void init(HandlerInfo hi) {
System.out.println("in " + this.getClass() + " init()");
}
  public boolean handleRequest(MessageContext context) {
System.out.println("in " + this.getClass() + " handleRequest()");
return true;
}
  public boolean handleResponse(MessageContext context) {
System.out.println("in " + this.getClass() + " handleResponse()");
return true;
}
  public boolean handleFault(MessageContext context) {
System.out.println("in " + this.getClass() + " handleFault()");
return true;
}
  public QName[] getHeaders() {
return headers;
}
}

Creating the Client-Side SOAP Handler Configuration File

The client-side SOAP handler configuration file specifies the list of handlers in the handler chain, the order in which they execute, the initialization parameters, and so on. See XML Schema for the Client-Side Handler Configuration File for a full description of this file.

The configuration file uses XML to describe a single handler chain that contains one or more handlers, as shown in the following simple example:

<weblogic-wsee-clientHandlerChain
xmlns="http://www.bea.com/ns/weblogic/90"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee">
        <handler>
<j2ee:handler-name>clienthandler1</j2ee:handler-name>
<j2ee:handler-class>examples.webservices.client_handler.client.ClientHandler1</j2ee:handler-class>
<j2ee:init-param>
<j2ee:param-name>ClientParam1</j2ee:param-name>
<j2ee:param-value>value1</j2ee:param-value>
</j2ee:init-param>
</handler>
        <handler>
<j2ee:handler-name>clienthandler2</j2ee:handler-name>
<j2ee:handler-class>examples.webservices.client_handler.client.ClientHandler2</j2ee:handler-class>
</handler>
</weblogic-wsee-clientHandlerChain>

In the example, the handler chain contains two handlers: clienthandler1 and clienthandler2, implemented with the class names specified with the <j2ee:handler-class> element. The two handlers execute in forward order directly before the client application sends the SOAP request to the Web Service, and then in reverse order directly after the client application receives the SOAP response from the Web Service.

The example also shows how to use the <j2ee:init-param> element to specify one or more initialization parameters to a handler.

Use the <soap-role>, <soap-header>, and <port-name> child elements of the <handler> element to specify the SOAP roles implemented by the handler, the SOAP headers processed by the handler, and the port-name element in the WSDL with which the handler is associated with, respectively.

XML Schema for the Client-Side Handler Configuration File

The following XML Schema file defines the structure of the client-side SOAP handler configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<schema
targetNamespace="http://www.bea.com/ns/weblogic/90"
xmlns:wls="http://www.bea.com/ns/weblogic/90"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
>
<include schemaLocation="weblogic-j2ee.xsd"/>
  <element name="weblogic-wsee-clientHandlerChain"
type="wls:weblogic-wsee-clientHandlerChainType">
<xsd:key name="wsee-clienthandler-name-key">
<xsd:annotation>
<xsd:documentation>
            Defines the name of the handler. The name must be unique within the
chain.
            </xsd:documentation>
</xsd:annotation>
<xsd:selector xpath="j2ee:handler"/>
<xsd:field xpath="j2ee:handler-name"/>
</xsd:key>
</element>
  <complexType name="weblogic-wsee-clientHandlerChainType">
<sequence>
<xsd:element name="handler"
type="j2ee:service-ref_handlerType"
minOccurs="0" maxOccurs="unbounded">
</xsd:element>
</sequence>
</complexType>
</schema>

A single configuration file specifies a single client-side handler chain. The root of the configuration file is <weblogic-wsee-clientHandlerChain>, and the file contains zero or more <handler> child elements, each of which describes a handler in the chain.

The structure of the <handler> element is described by the J2EE service-ref_handlerType complex type, specified in the J2EE 1.4 Web Service client XML Schema.

Specifying the Client-Side SOAP Handler Configuration File to clientgen

Use the handlerChainFile attribute of the clientgen Ant task to specify the client-side SOAP handler configuration file, as shown in the following excerpt from a build.xml file:

    <clientgen
wsdl="http://ariel:7001/handlers/ClientHandlerService?WSDL"
destDir="${clientclass-dir}"
handlerChainFile="ClientHandlerChain.xml"
packageName="examples.webservices.client_handler.client"/>

The JAX-RPC stubs generated by clientgen automatically ensure that the handlers described by the configuration file execute in the correct order before and after the client application invokes the Web Service operation

 


Using a Client-Side Security WS-Policy File

The section Using WS-Policy Files for Message-Level Security Configuration describes how a WebLogic Web Service can be associated with one or more WS-Policy files that describe the message-level security of the Web Service. These WS-Policy files are XML files that describe how a SOAP message should be digitally signed or encrypted and what sort of user authentication is required from a client that invokes the Web Service. Typically, the WS-Policy file associated with a Web Service is attached to its WSDL, which the Web Services client runtime reads to determine whether and how to digitally sign and encrypt the SOAP message request from an operation invoke from the client application.

Sometimes, however, a Web Service might not attach the WS-Policy file to its deployed WSDL or the Web Service might be configured to not expose its WSDL at all. In these cases, the Web Services client runtime cannot determine from the service itself the security that must be enabled for the SOAP message request. Rather, it must load a client-side copy of the WS-Policy file. This section describes how to update a client application to load a local copy of a WS-Policy file.

The client-side WS-Policy file is typically exactly the same as the one associated with a deployed Web Service. If the two files are different, and there is a conflict in the security assertions contained in the files, then the invoke of the Web Service operation returns an error.

You can specify that the client-side WS-Policy file be associated with the SOAP message request, response, or both. Additionally, you can specify that the WS-Policy file be associated with the entire Web Service, or just one of its operations.

Associating a WS-Policy File with a Client Application: Main Steps

The following procedure describes the high-level steps to associate a WS-Policy file with the client application that invokes a Web Service operation.

It is assumed that you have created the client application that invokes a deployed Web Service, and that you want to update it by associating a client-side WS-Policy file. It is also assumed that you have set up an Ant-based development environment and that you have a working build.xml file that includes a target for running the clientgen Ant task. See Invoking a Web Service from a Stand-alone Client: Main Steps.

  1. Create the client-side WS-Policy files and save them in a location accessible by the client application. Typically, the WS-Policy files are the same as those configured for the Web Service you are invoking, but because the server-side files are not exposed to the client runtime, the client application must load its own local copies.
  2. See Creating and Using a Custom WS-Policy File for information about creating WS-Policy files.

    WARNING: You can specify only concrete client-side WS-Policy files to a client application; you cannot use abstract WS-Policy files or the three pre-packaged security WS-Policy files.
  3. Update the build.xml file that builds your client application by specifying to the clientgen Ant task that it should generate additional getXXXPort() methods in the JAX-RPC stub, where XXX refers to the name of the Web Service. These methods are later used by the client application to load the client-side WS-Policy files.
  4. See Updating clientgen to Generate Methods That Load WS-Policy Files.

  5. Update your Java client application to load the client-side WS-Policy files using the additional getXXXPort() methods that the clientgen Ant task generates.
  6. See Updating a Client Application To Load WS-Policy Files.

  7. Rebuild your client application by running the relevant task. For example:
  8. prompt> ant build-client

When you next run the client application, it will load local copies of the WS-Policy files that the Web Service client runtime uses to enable security for the SOAP request message.

Updating clientgen to Generate Methods That Load WS-Policy Files

Set the generatePolicyMethods attribute of the clientgen Ant task to true to specify that the Ant task should generate additional getXXX() methods in the implementation of the JAX-RPC Service interface for loading client-side copies of WS-Policy files when you get a port, as shown in the following example:

    <clientgen
wsdl="http://ariel:7001/policy/ClientPolicyService?WSDL"
destDir="${clientclass-dir}"
generatePolicyMethods="true"
packageName="examples.webservices.client_policy.client"/>

See Updating a Client Application To Load WS-Policy Files for a description of the additional methods that are generated and how to use them in a client application.

Updating a Client Application To Load WS-Policy Files

When you set generatePolicyMethods="true" for clientgen, the Ant task generates additional methods in the implementation of the JAX-RPC Service interface that you can use to load WS-Policy files, where XXX refers to the name of the Web Service. You can use either an Array or Set of WS-Policy files to associate multiple files to a Web Service. If you want to associate just a single WS-Policy file, create a single-member Array or Set.

Use these methods, rather than the normal getXXXPort() method with no parameters, for getting a Web Service port and specifying at the same time that invokes of all, or the specified, operation using that port have an associated WS-Policy file or files.

Note: The following methods from a previous release of WebLogic Server have been deprecated; if you want to associate a single client-side WS-Policy file, specify a single-member Array or Set and use the corresponding method described above.

The following simple client application shows an example of using these policy methods; the code in bold is described after the example.

package examples.webservices.client_policy.client;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;
import java.io.FileInputStream;
import java.io.IOException;
/**
* This is a simple standalone client application that invokes the
* the <code>sayHello</code> operation of the ClientPolicyService Web service.
*
* @author Copyright (c) 2004 by BEA Systems. All Rights Reserved.
*/
public class Main {
  public static void main(String[] args)
throws ServiceException, RemoteException, IOException {
      FileInputStream [] inbound_policy_array = new FileInputStream[2];
inbound_policy_array[0] = new FileInputStream(args[1]);
inbound_policy_array[1] = new FileInputStream(args[2]);
      FileInputStream [] outbound_policy_array = new FileInputStream[2];
outbound_policy_array[0] = new FileInputStream(args[1]);
outbound_policy_array[1] = new FileInputStream(args[2]);
      ClientPolicyService service = new ClientPolicyService_Impl(args[0] + "?WSDL");
      // standard way to get the Web Service port
ClientPolicyPortType normal_port = service.getClientPolicyPort();
      // specify an array of WS-Policy file for the request and response
// of a particular operation
ClientPolicyPortType array_of_policy_port = service.getClientPolicyPort("sayHello", inbound_policy_array, outbound_policy_array);
    try {
String result = null;
result = normal_port.sayHello("Hi there!");
result = array_of_policy_port.sayHello("Hi there!");
System.out.println( "Got result: " + result );
} catch (RemoteException e) {
throw e;
}
}
}

The second and third argument to the client application are the two WS-Policy files from which the application makes an array of FileInputStreams (inbound_policy_array and outbound_policy_array). The normal_port uses the standard parameterless method for getting a port; the array_of_policy_port, however, uses one of the policy methods to specify that an invoke of the sayHello operation using the port has multiple WS-Policy files (specified with an Array of FileInputStream) associated with both the inbound and outbound SOAP request and response:

      ClientPolicyPortType array_of_policy_port =  service.getClientPolicyPort("sayHello", inbound_policy_array, outbound_policy_array);

 


WebLogic Web Services Stub Properties

WebLogic Server provides a set of stub properties that you can set in the JAX-RPC Stub used to invoke a WebLogic Web Service. Use the Stub._setProperty() method to set the properties, as shown in the following example:

((Stub)port)._setProperty(WLStub.MARSHAL_FORCE_INCLUDE_XSI_TYPE,"true");

Most of the stub properties are defined in the WLStub class. See weblogic.wsee.jaxrpc.WLStub for details.

The following table describes additional stub properties not defined in the WLStub class.

Table 9-2 Additional Stub Properties
Stub Property
Description
weblogic.wsee.transport.connection.timeout
Specifies, in milliseconds, how long a client application that is attempting to invoke a Web Service waits to make a connection. After the specified time elapses, if a connection hasn’t been made, the attempt times out.
weblogic.wsee.transport.read.timeout
Specifies, in milliseconds, how long a client application waits for a response from a Web Service it is invoking. After the specified time elapses, if a response hasn’t arrived, the client times out.
weblogic.wsee.security.bst.serverVerifyCert
Specifies the certificate that the client application uses to validate the signed response from WebLogic Server. By default, WebLogic Server includes the certification used to validate in the response SOAP message itself; if this is not possible, then use this stub property to specify a different one.
This stub property applies only to client applications that run inside of a WebLogic Server container, and not to stand-alone client applications.
The value of the property is an object of data type java.security.cert.X509Certificate.
weblogic.wsee.security.bst.serverEncryptCert
Specifies the certificate that the client application uses to encrypt the request SOAP message sent to WebLogic Server. By default, the client application uses the public certificate published in the Web Service’s WSDL; if this is not possible, then use this stub property to specify a different one.
This stub property applies only to client applications that run inside of a WebLogic Server container, and not to stand-alone client applications.
The value of the property is an object of data type java.security.cert.X509Certificate.
weblogic.wsee.marshal.forceIncludeXsiType
Specifies that the SOAP messages for a Web Service operation invoke should include the XML Schema data type of each parameter. By default, the SOAP messages do not include the data type of each parameter.
If you set this property to True, the elements in the SOAP messages that describe operation parameters will include an xsi:type attribute to specify the data type of the parameter, as shown in the following example:
<soapenv:Envelope>
...
<maxResults xsi:type="xs:int">10</maxResults>
...
By default (or if you set this property to False), the parameter element would look like the following example:
<soapenv:Envelope>
...
<maxResults>10</maxResults>
...
Valid values for this property are True and False; default value is False.


  Back to Top       Previous  Next