The following sections describe how to invoke a Web Service using asynchronous request-response:
When you invoke a Web Service synchronously, the invoking client application waits for the response to return before it can continue with its work. In cases where the response returns immediately, this method of invoking the Web Service might be adequate. However, because request processing can be delayed, it is often useful for the client application to continue its work and handle the response later on, or in other words, use the asynchronous request-response feature of WebLogic Web Services.
You invoke a Web Service asynchronously only from a client running in a WebLogic Web Service, never from a stand-alone client application. The invoked Web Service does not change in any way, thus you can invoke any deployed Web Service (both WebLogic and non-WebLogic) asynchronously as long as the application server that hosts the Web Service supports the WS-Addressing specification.
When implementing asynchronous request-response in your client, rather than invoking the operation directly, you invoke an asynchronous flavor of the same operation. (This asynchronous flavor of the operation is automatically generated by the jwsc
Ant task.) For example, rather than invoking an operation called getQuote
directly, you would invoke getQuoteAsync
instead. The asynchronous flavor of the operation always returns void
, even if the original operation returns a value. You then include methods in your client that handle the asynchronous response or failures when it returns later on. You put any business logic that processes the return value of the Web Service operation invoke or a potential failure in these methods. You use both naming conventions and JWS annotations to specify these methods to the JWS compiler. For example, if the asynchronous operation is called getQuoteAsync
, then these methods might be called onGetQuoteAsyncResponse
and onGetQuoteAsyncFailure
.
Note: | For information about using asynchronous request-response with other asynchronous features, such as Web Service reliable messaging or buffering, see Using the Asynchronous Features Together. This section describes how to use the asynchronous request-response feature on its own. The asynchronous request-response feature works only with HTTP; you cannot use it with the HTTPS or JMS transport. |
The following procedure describes how to create a client Web Service that asynchronously invokes an operation in a different Web Service. The procedure shows how to create the JWS file that implements the client Web Service from scratch; if you want to update an existing JWS file, use this procedure as a guide.
For clarity, it is assumed in the procedure that:
It is further assumed that you have set up an Ant-based development environment and that you have a working build.xml
file to which you can add targets for running the jwsc
Ant task and deploying the generated service. For more information, see the following sections in Getting Started With WebLogic Web Services Using JAX-RPC:
Configure the asynchronous response service, as described in Configuring the Host WebLogic Server Instance for the Asynchronous Web Service.
|
||
Use your favorite IDE or text editor. See Writing the Asynchronous JWS File.
|
||
prompt> ant build-clientService |
||
See
“Deploying and Undeploying WebLogic Web Services” in Getting Started With WebLogic Web Services Using JAX-RPC.
|
When you invoke the StockQuoteClientService
Web Service, which in turn invokes the StockQuoteService
Web Service, the second invoke will be asynchronous rather than synchronous.
Configuring the WebLogic Server instance on which the asynchronous Web Service is deployed involves configuring JMS resources, such as JMS servers and modules, that are used internally by the Web Services runtime.
You can configure these resources manually or you can use the Configuration Wizard to extend the WebLogic Server domain using a Web Services-specific extension template. Using the Configuration Wizard greatly simplifies the required configuration steps; for details, see “Configuring Your Domain For Web Services Features” in Getting Started With WebLogic Web Services Using JAX-RPC.
Note: | Alternatively, you can use WLST to configure the resources. For information about using WLST to extend the domain, see “Configuring Existing Domains” in WebLogic Scripting Tool. |
If you prefer to configure the resources manually, perform the following steps.
See
“Invoking the Administration Console” in Getting Started With WebLogic Web Services Using JAX-RPC.
|
||
Create a JMS Server. If a JMS server already exists, you can use it if you do not want to create a new one.
See
“Create JMS servers” in the Administration Console Online Help.
|
||
Create a JMS module, and then define a JMS queue in the module. If a JMS module already exists, you can use it if you do not want to create a new one. Target the JMS queue to the JMS server you created in the preceding step. Be sure you specify that this JMS queue is local, typically by setting the local JNDI name. See
“Create JMS system modules” and
“Create queues in a system module” in the Administration Console Online Help.
|
||
Define a Work Manager named
weblogic.wsee.mdb.DispatchPolicy , which is used by the asynchronous request-response feature, by default.
See
“Create global Work Managers” in the Administration Console Online Help.
|
||
Review
“Tuning Heavily Loaded Systems to Improve Web Service Performance” in WebLogic Server Performance and Tuning.
|
The following example shows a simple JWS file that implements a Web Service called StockQuoteClient
that has a single method, asyncOperation
, that in turn asynchronously invokes the getQuote
method of the StockQuote
service. The Java code in bold is described Coding Guidelines for Invoking a Web Service Asynchronously. See Example of a Synchronous Invoke to see how the asynchronous invoke differs from a synchronous invoke of the same operation.
package examples.webservices.async_req_res;
import weblogic.jws.WLHttpTransport;import weblogic.jws.ServiceClient;
import weblogic.jws.AsyncResponse;
import weblogic.jws.AsyncFailure;
import weblogic.wsee.async.AsyncPreCallContext;
import weblogic.wsee.async.AsyncCallContextFactory;
import weblogic.wsee.async.AsyncPostCallContext;
import javax.jws.WebService;
import javax.jws.WebMethod;
import examples.webservices.async_req_res.StockQuotePortType;
import java.rmi.RemoteException;
@WebService(name="StockQuoteClientPortType",
serviceName="StockQuoteClientService",
targetNamespace="http://examples.org/")
@WLHttpTransport(contextPath="asyncClient",
serviceUri="StockQuoteClient",
portName="StockQuoteClientServicePort")
/**
* Client Web Service that invokes the StockQuote Service asynchronously.
*/
public class StockQuoteClientImpl {
@ServiceClient(wsdlLocation="http://localhost:7001/async/StockQuote?WSDL",
serviceName="StockQuoteService", portName="StockQuote")
private StockQuotePortType port;
@WebMethod
public void asyncOperation (String symbol, String userName)
throws RemoteException {
AsyncPreCallContext apc = AsyncCallContextFactory.getAsyncPreCallContext();
apc.setProperty("userName", userName);
try {port.getQuoteAsync(apc, symbol );
System.out.println("in getQuote method of StockQuoteClient WS");
} catch (RemoteException re) {
System.out.println("RemoteException thrown");
throw new RuntimeException(re);
}
}
@AsyncResponse(target="port", operation="getQuote")
public void onGetQuoteAsyncResponse(AsyncPostCallContext apc, int quote) {
// Get the userName property we set on AsyncPreCallContext
String userName = (String)apc.getProperty("userName");
System.out.println("-------------------");
System.out.println(username + " Got quote " + quote );
System.out.println("-------------------");
}
@AsyncFailure(target="port", operation="getQuote")
public void onGetQuoteAsyncFailure(AsyncPostCallContext apc, Throwable e) {
System.out.println("-------------------");
e.printStackTrace();
System.out.println("-------------------");
}
}
The following guidelines for invoking an operation asynchronously correspond to the Java code shown in bold in the example described in Writing the Asynchronous JWS File. These guidelines are in addition to the standard ones for creating JWS files. See Example of a Synchronous Invoke to see how the asynchronous invoke differs from a synchronous invoke of the same operation.
To invoke an operation asynchronously in your JWS file:
import weblogic.jws.ServiceClient;
import weblogic.jws.AsyncResponse;
import weblogic.jws.AsyncFailure;
jwsc
Ant task, of the port type of the Web Service you want to invoke. The stub package is specified by the packageName
attribute of the <clientgen>
child element of jwsc
, and the name of the stub is determined by the WSDL of the invoked Web Service.import examples.webservices.async_req_res.StockQuotePortType;
import weblogic.wsee.async.AsyncCallContextFactory;
import weblogic.wsee.async.AsyncPreCallContext;
import weblogic.wsee.async.AsyncPostCallContext;
For more information about asynchronous pre- and post-call context, see Using Asynchronous Pre- and Post-call Contexts. See Javadocs for additional reference information about these APIs.
@ServiceClient
JWS annotation to specify the WSDL, name, and port of the Web Service you will be invoking asynchronously. You specify this annotation at the field-level on a variable, whose data type is the JAX-RPC port type of the Web Service you are invoking. @ServiceClient(
wsdlLocation="http://localhost:7001/async/StockQuote?WSDL",
serviceName="StockQuoteService",
portName="StockQuote")
private StockQuotePortType port;
When you annotate a variable (in this case, port
) with the @ServiceClient
annotation, the Web Services runtime automatically initializes and instantiates the variable, preparing it so that it can be used to invoke another Web Service asynchronously.
getQuote
operation asynchronously, get a pre-call asynchronous context using the context factory:AsyncPreCallContext apc =
AsyncCallContextFactory.getAsyncPreCallContext();
For more information about asynchronous pre- and post-call context, see Using Asynchronous Pre- and Post-call Contexts.
setProperty
method of the pre-call context to create a property to store the username:apc.setProperty("userName", userName);
@ServiceClient
annotation, invoke the operation (in this case, getQuote
). Instead of invoking it directly, however, invoke the asynchronous flavor of the operation, which has Async
added on to the end of its name. The asynchronous flavor always returns void
. Pass the asynchronous context as the first parameter:port.getQuoteAsync(apc, symbol);
on
Operationname
AsyncResponse
, where Operationname
refers to the name of the operation, with initial letter always capitalized. The method must return void
, and have two parameters: the post-call asynchronous context and the return value of the operation you are invoking. Annotate the method with the @AsyncResponse
JWS annotation; use the target
attribute to specify the variable whose datatype is the JAX-RPC stub and the operation
attribute to specify the name of the operation you are invoking asynchronously. Inside the body of the method, put the business logic that processes the value returned by the operation. Use the getProperty
method of the post-call context to get the property that was set by pre-call context before invoking the asynchronous method:@AsyncResponse(target="port", operation="getQuote")
public void onGetQuoteAsyncResponse(AsyncPostCallContext apc,
int quote) {
// Get the userName property we set on AsyncPreCallContext
String userName = (String)apc.getProperty("userName");
System.out.println("-------------------");
System.out.println("Got quote " + quote );
System.out.println("-------------------");
}
For more information about asynchronous pre- and post-call context, see Using Asynchronous Pre- and Post-call Contexts.
on
Operationname
AsyncFailure
, where Operationname
refers to the name of the operation, with initial letter capitalized. The method must return void
, and have two parameters: the post-call asynchronous context and a Throwable
object, the superclass of all exceptions to handle any type of exception thrown by the invoked operation. Annotate the method with the @AsyncFailure
JWS annotation; use the target
attribute to specify the variable whose datatype is the JAX-RPC stub and the operation
attribute to specify the name of the operation you are invoking asynchronously. Inside the method, you can determine the exact nature of the exception and write appropriate Java code.@AsyncFailure(target="port", operation="getQuote")
public void onGetQuoteAsyncFailure(AsyncPostCallContext apc,
Throwable e) {
System.out.println("-------------------");
e.printStackTrace();
System.out.println("-------------------");
}
Note: | You are not required to use the @AsyncResponse and @AsyncFailure annotations, although it is a good practice because it clears up any ambiguity and makes your JWS file clean and understandable. However, in the rare use case where you want one of the onXXX methods to handle the asynchronous response or failure from two (or more) stubs that are invoking operations from two different Web Services that have the same name, then you should explicitly NOT use these annotations. Be sure that the name of the onXXX methods follow the correct naming conventions exactly, as described above. |
The AsyncPreCallContext
and AsyncPostCallContext
APIs describe asynchronous contexts that you can use in your Web Service for a variety of reasons. For example:
To use asynchronous pre- and post-call contexts:
import weblogic.wsee.async.AsyncCallContextFactory;
import weblogic.wsee.async.AsyncPreCallContext;
import weblogic.wsee.async.AsyncPostCallContext;
AsyncPreCallContext apc =
AsyncCallContextFactory.getAsyncPreCallContext();
setProperty
method of the pre-call context to create a property that stores the username:apc.setProperty("userName", userName);
getProperty
method of the post-call context to get the property that was set by pre-call context before invoking the asynchronous method:String userName = (String)apc.getProperty("userName");
The following example shows a JWS file that invokes the getQuote
operation of the StockQuote
Web Service synchronously. The example is shown only so you can compare it with the corresponding asynchronous invoke shown in Writing the Asynchronous JWS File.
package examples.webservices.async_req_res;
import weblogic.jws.WLHttpTransport;
import weblogic.jws.ServiceClient;
import javax.jws.WebService;
import javax.jws.WebMethod;
import java.rmi.RemoteException;
@WebService(name="SyncClientPortType",
serviceName="SyncClientService",
targetNamespace="http://examples.org/")
@WLHttpTransport(contextPath="syncClient",
serviceUri="SyncClient",
portName="SyncClientPort")
/**
* Normal service-to-service client that invokes StockQuote service
* synchronously.
*/
public class SyncClientImpl {
@ServiceClient(wsdlLocation="http://localhost:7001/async/StockQuote?WSDL",
serviceName="StockQuoteService", portName="StockQuote")
private StockQuotePortType port;
@WebMethod
public void nonAsyncOperation(String symbol) throws RemoteException {
int quote = port.getQuote(symbol);
System.out.println("-------------------");
System.out.println("Got quote " + quote );
System.out.println("-------------------");
}
}
To update a build.xml
file to generate the JWS file that invokes a Web Service operation asynchronously, add taskdefs
and a build-clientService
target that looks something like the following; see the description after the example for details:
<taskdef name="jwsc"
classname="weblogic.wsee.tools.anttasks.JwscTask" />
<target name="build-clientService">
<jwsc
enableAsyncService="true"
srcdir="src"
destdir="${clientService-ear-dir}" >
<jws file="examples/webservices/async_req_res/StockQuoteClientImpl.java" >
<clientgen
wsdl="http://${wls.hostname}:${wls.port}/async/StockQuote?WSDL"
packageName="examples.webservices.async_req_res"/>
</jws>
</jwsc>
</target>
Use the taskdef
Ant task to define the full classname of the jwsc
Ant tasks.
Update the jwsc
Ant task that compiles the client Web Service to include a <clientgen>
child element of the <jws>
element so as to generate and compile the JAX-RPC stubs for the deployed StockQuote
Web Service. The jwsc
Ant task automatically packages them in the generated WAR file so that the client Web Service can immediately access the stubs. By default, the jwsc
Ant task in this case generates both synchronous and asynchronous flavors of the Web Service operations in the JAX-RPC stubs. You do this because the StockQuoteClientImpl
JWS file imports and uses one of the generated classes.
By default, every WebLogic Server instance deploys an internal asynchronous Web Service that handles the asynchronous request-response feature. To specify that you do not want to deploy this internal service, start the WebLogic Server instance using the -Dweblogic.wsee.skip.async.response=true
Java system property.
One reason for disabling the asynchronous service is if you use a WebLogic Server instance as a Web proxy to a WebLogic cluster. In this case, asynchronous messages will never get to the cluster, as required, because the asynchronous service on the proxy server consumes them instead. For this reason, you must disable the asynchronous service on the proxy server using the system property.
For details on specifying Java system properties to configure WebLogic Server, see “Specifying Java Options for a WebLogic Server Instance” in Managing Server Startup and Shutdown.
Client applications that use the asynchronous request-response feature might not invoke the operation directly, but rather, use a proxy server. Reasons for using a proxy include the presence of a firewall or the deployment of the invoked Web Service to a cluster.
In this case, the WebLogic Server instance that hosts the invoked Web Service must be configured with the address and port of the proxy server. If your Web Service is deployed to a cluster, you must configure every server in the cluster.
This procedure describes how to create a network channel, the primary configurable WebLogic Server resource for managing network connection. Network channels enable you to provide a consistent way to access the front-end address of a cluster. For more information about network channels, see “Understanding Network Channels” in Configuring Server Environments.
weblogic-wsee-proxy-channel-
XXX
, where XXX
refers to the protocol. For example, to create a network channel for HTTPS, call it weblogic-wsee-proxy-channel-https
. See “Configure custom network channels” in the Administration Console Online Help for general information about creating a network channel.