![]() ![]() ![]() ![]() ![]() ![]() |
The following sections describe how to invoke a Web Service using asynchronous request-response:
WARNING: | This feature can be implemented only for a JAX-RPC 1.1-based Web Service; you cannot implement it for a JAX-WS 2.0 Web Service. |
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. |
Note: | 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. See:
StockQuoteClientService
Web Service.See Writing the Asynchronous JWS File.
build.xml
file to compile the JWS file that implements the StockQuoteClientService
. You will add a <clientgen>
child element to the jwsc
Ant task so as to automatically generate the asynchronous flavor of the Web Service operations you are invoking.See Updating the build.xml File When Using Asynchronous Request-Response.
StockQuoteClientService
:prompt> ant build-clientService
StockQuoteClientService
Web Service as usual.
When you invoke the StockQuoteClientService
Web Service, which in turn invokes the StockQuoteService
Web Service, the second invoke will be asynchronous rather than synchronous.
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) throws RemoteException {
AsyncPreCallContext apc = AsyncCallContextFactory.getAsyncPreCallContext();
apc.setProperty("symbol", symbol);
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) {
System.out.println("-------------------");
System.out.println("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;
The AsyncPreCallContext
and AsyncPostCallContext
APIs describe asynchronous contexts that you can use for a variety of reasons in your Web Service: to set a property in the pre-context so that the method that handles the asynchronous response can distinguish between different asynchronous calls; to set and get contextual variables, such as the name of the user invoking the operation, their password, and so on; to get the name of the JAX-RPC stub that invoked a method asynchronously; and to set a time-out interval on the context.
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();
setProperty
method of the pre-call context to create a property whose name and value is the same as the parameter to the getQuote
method:apc.setProperty("symbol", symbol);
@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.@AsyncResponse(target="port", operation="getQuote")
public void onGetQuoteAsyncResponse(AsyncPostCallContext apc,
int quote) {
System.out.println("-------------------");
System.out.println("Got quote " + quote );
System.out.println("-------------------");
}
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 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 handes 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.
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.
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 for general information about creating a network channel.
![]() ![]() ![]() |