The following sections describe how to create a conversational Web Service:
A Web Service and the client application that invokes it may communicate multiple times to complete a single task. Also, multiple client applications might communicate with the same Web Service at the same time. Conversations provide a straightforward way to keep track of data between calls and to ensure that the Web Service always responds to the correct client.
Conversations meet two challenges inherent in persisting data across multiple communications:
WebLogic Server manages this unique ID and state by creating a conversation context each time a client application initiates a new conversation. The Web Service then uses the context to correlate calls to and from the service and to persist its state-related data.
Conversations between a client application and a Web Service have three distinct phases:
Conversations typically occur between two WebLogic Web Services: one is marked conversational and defines the start, continue, and finish operations and the other Web Service uses the @ServiceClient
annotation to specify that it is a client of the conversational Web Service. You can also invoke a conversational Web Service from a stand-alone Java client, although there are restrictions.
As with other WebLogic Web Service features, you use JWS annotations to specify that a Web Service is conversational.
Note: | The client Web Service that invokes a conversational Web Service is not required to also be conversational. However, if the client is not conversational, there is a danger of multiple instances of this client accessing the same conversational Web Service stub and possibly corrupting the saved conversational state. If you believe this might true in your case, then specify that the client Web Service also be conversational. In this case you cannot use a stand-alone Java client, because there is no way to mark it as conversational using the WebLogic APIs. |
Note: | A conversational Web Service on its own does not guarantee message delivery or that the messages are delivered in order, exactly once. If you require this kind of message delivery guarantee, you must also specify that the Web Service be reliable. See Using Web Services Reliable Messaging and Using the Asynchronous Features Together. |
The following procedure describes how to create a conversational Web Service, as well as a client Web Service and stand-alone Java client application, both of which initiate and conduct a conversation. The procedure shows how to create the JWS files that implement the two Web Services from scratch. If you want to update existing JWS files, you can also use this procedure as a guide.
It is 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 conversational Web Service. It is further assumed that you have a similar setup for the WebLogic Server instance that hosts the client Web Service that initiates the conversation. For more information, see the following sections in Getting Started With WebLogic Web Services Using JAX-RPC:
Use your favorite IDE or text editor. See Programming Guidelines for the Conversational JWS File.
|
||
See
“Running the jwsc WebLogic Web Services Ant Task” in Getting Started With WebLogic Web Services Using JAX-RPC.
|
||
prompt> ant build-mainService |
||
See
“Deploying and Undeploying WebLogic Web Services” in Getting Started With WebLogic Web Services Using JAX-RPC.
|
||
If the client application is a stand-alone Java client, see Updating a Stand-Alone Java Client to Invoke a Conversational Web Service. Skip Steps 6-9.
|
||
Use your favorite IDE or text editor. It is assumed that the client Web Service is deployed to a different WebLogic Server instance form the one that hosts the conversational Web Service. See Programming Guidelines for the JWS File That Invokes a Conversational Web Service.
|
||
prompt> ant build-clientService |
||
See
“Deploying and Undeploying WebLogic Web Services” in Getting Started With WebLogic Web Services Using JAX-RPC.
|
The following example shows a simple JWS file that implements a conversational Web Service; see the explanation after the example for coding guidelines that correspond to the Java code in bold.
package examples.webservices.conversation;
import java.io.Serializable;
import weblogic.jws.WLHttpTransport;import weblogic.jws.Conversation;
import weblogic.jws.Conversational;
import weblogic.jws.Context;
import weblogic.wsee.jws.JwsContext;
import weblogic.wsee.jws.ServiceHandle;
import javax.jws.WebService;
import javax.jws.WebMethod;
@Conversational(maxIdleTime="10 minutes",
maxAge="1 day",
runAsStartUser=false,
singlePrincipal=false )
@WebService(name="ConversationalPortType",
serviceName="ConversationalService",
targetNamespace="http://examples.org/")
@WLHttpTransport(contextPath="conv",
serviceUri="ConversationalService",
portName="ConversationalServicePort")
/**
* Conversational Web Service.
*/
public class ConversationalServiceImpl implements Serializable {
@Context
private JwsContext ctx;
public String status = "undefined";
@WebMethod@Conversation (Conversation.Phase.START)
public String start() {
ServiceHandle handle = ctx.getService();
String convID = handle.getConversationID();
status = "start";
return "Starting conversation, with ID " + convID + " and status equal to " + status;
}
@WebMethod@Conversation (Conversation.Phase.CONTINUE)
public String middle(String message) {
status = "middle";
return "Middle of conversation; the message is: " + message + " and status is " + status;
}
@WebMethod@Conversation (Conversation.Phase.FINISH)
public String finish(String message ) {
status = "finish";
return "End of conversation; the message is: " + message + " and status is " + status;
}
}
Follow these guidelines when programming the JWS file that implements a conversational Web Service. Code snippets of the guidelines are shown in bold in the preceding example.
java.io.Serializable
, so you must first import the class into your JWS file:import java.io.Serializable;
import weblogic.jws.Conversation;
import weblogic.jws.Conversational;
@Context
annotation and context APIs:import weblogic.jws.Context;
import weblogic.wsee.jws.JwsContext;
import weblogic.wsee.jws.ServiceHandle;
See “Accessing Runtime Information about a Web Service” in Getting Started With WebLogic Web Services Using JAX-RPC for more information about the runtime Web Service context.
@Conversational
annotation to specify that the Web Service is conversational. Although this annotation is optional (assuming you are specifying the @Conversation
method-level annotation), it is a best practice to always use it in your JWS file to clearly specify that your Web Service is conversational.
Specify any of the following optional attributes: maxIdleTime
is the maximum amount of time that the Web Service can be idle before WebLogic Server finishes the conversation; maxAge
is the maximum age of the conversation; runAsStartUser
indicates whether the continue and finish phases of an existing conversation are run as the user who started the conversation; and singlePrincipal
indicates whether users other than the one who started a conversation are allowed to execute the continue and finish phases of the conversation.
@Conversational(maxIdleTime="10 minutes",
maxAge="1 day",
runAsStartUser=false,
singlePrincipal=false )
If a JWS file includes the @Conversational
annotation, all operations of the Web Service are conversational. The default phase of an operation, if it does not have an explicit @Conversation
annotation, is continue. However, because a conversational Web Service is required to include at least one start and one finish operation, you must use the method-level @Conversation
annotation to specify which methods implement these operations.
See “weblogic.jws.Conversational” in WebLogic Web Services Reference for additional information and default values for the attributes.
java.io.Serializable
:public class ConversationalServiceImpl implements Serializable {
weblogic.wsee.jws.JwsContext
, with the field-level @Context
JWS annotation:@Context
private JwsContext ctx;
@Conversation
annotation to specify the methods that implement the start, continue, and finish phases of your conversation. A conversation is required to have at least one start and one finish operation; the continue operation is optional. Use the following parameters to the annotation to specify the phase: Conversation.Phase.START
, Conversation.Phase.CONTINUE
, or Conversation.Phase.FINISH
. The following example shows how to specify the start operation:@WebMethod
@Conversation (Conversation.Phase.START)
public String start() {...
If you mark just one method of the JWS file with the @Conversation
annotation, then the entire Web Service becomes conversational and each operation is considered part of the conversation; this is true even if you have not used the optional class-level @Conversational
annotation in your JWS file. Any methods not explicitly annotated with @Conversation
are, by default, continue operations. This means that, for example, if a client application invokes one of these continue methods without having previously invoked a start operation, the Web Service returns a runtime error.
Finally, if you plan to invoke the conversational Web Service from a stand-alone Java client, the start operation is required to be request-response, or in other words, it cannot be annotated with the @Oneway
JWS annotation. The operation can return void
. If you are going to invoke the Web Service only from client applications that run in WebLogic Server, then this requirement does not apply.
See “weblogic.jws.Conversation” in WebLogic Web Services Reference for additional information.
JwsContext
instance to get runtime information about the Web Service.For example, the following code in the start operation gets the ID that WebLogic Server assigns to the new conversation:
ServiceHandle handle = ctx.getService();
String convID = handle.getConversationID();
See “Accessing Runtime Information about a Web Service Using the JwsContext” in Getting Started With WebLogic Web Services Using JAX-RPC for detailed information on using the context-related APIs.
The following example shows a simple JWS file for a Web Service that invokes the conversational Web Service described in Programming Guidelines for the Conversational JWS File; see the explanation after the example for coding guidelines that correspond to the Java code in bold.
package examples.webservices.conversation;
import weblogic.jws.WLHttpTransport;import weblogic.jws.ServiceClient;
import weblogic.wsee.conversation.ConversationUtils;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.xml.rpc.Stub;
import examples.webservices.conversation.ConversationalPortType;
import java.rmi.RemoteException;
@WebService(name="ConversationalClientPortType",
serviceName="ConversationalClientService",
targetNamespace="http://examples.org/")
@WLHttpTransport(contextPath="convClient",
serviceUri="ConversationalClient",
portName="ConversationalClientPort")
/**
* client that has a conversation with the ConversationalService.
*/
public class ConversationalClientImpl {
@ServiceClient(
wsdlLocation="http://localhost:7001/conv/ConversationalService?WSDL",
serviceName="ConversationalService",
portName="ConversationalServicePort")
private ConversationalPortType port;
@WebMethod
public void runConversation(String message) {
try {
// Invoke start operationString result = port.start();
System.out.println("start method executed.");
System.out.println("The message is: " + result);
// Invoke continue operationresult = port.middle(message );
System.out.println("middle method executed.");
System.out.println("The message is: " + result);
// Invoke finish operationresult = port.finish(message );
System.out.println("finish method executed.");
System.out.println("The message is: " + result);ConversationUtils.renewStub((Stub)port);
}
catch (RemoteException e) {
e.printStackTrace();
}
}
}
Follow these guidelines when programming the JWS file that invokes a conversational Web Service; code snippets of the guidelines are shown in bold in the preceding example:
@ServiceClient
JWS annotation:import weblogic.jws.ServiceClient;
import weblogic.wsee.conversation.ConversationUtils;
jwsc
Ant task. The stub package is specified by the packageName
attribute of the <clientgen>
child element of <jws>
, and the name of the stub is determined by the WSDL of the invoked Web Service.import examples.webservices.conversation.ConversationalPortType;
@ServiceClient
JWS annotation to specify the WSDL, name, and port of the conversational Web Service you want to invoke. You specify this annotation at the field-level on a private variable, whose data type is the JAX-RPC port type of the Web Service you are invoking. @ServiceClient(
wsdlLocation="http://localhost:7001/conv/ConversationalService?WSDL",
serviceName="ConversationalService",
portName="ConversationalServicePort")
private ConversationalPortType port;
@ServiceClient
annotation, invoke the start operation of the conversational Web Service to start the conversation. You can invoke the start method from any location in the JWS file (constructor, method, and so on):
String result = port.start();
result = port.middle(message );
result = port.finish(message );
renewStub()
method of the weblogic.wsee.conversation.ConversationUtils
utility class:ConversationUtils.renewStub((Stub)port);
Note: | The client Web Service that invokes a conversational Web Service is not required to also be conversational. However, if the client is not conversational, there is a danger of multiple instances of this client accessing the same conversational Web Service stub and possibly corrupting the saved conversational state. If you believe this might true in your case, then specify that the client Web Service also be conversational. |
WebLogic Server provides a utility class for use with the conversation feature. Use this class to perform common tasks such as getting and setting the conversation ID and setting configuration options. Some of these tasks are performed in the conversational Web Service, some are performed in the client that invokes the conversational Web Service. See Programming Guidelines for the JWS File That Invokes a Conversational Web Service for an example of using this class.
See weblogic.wsee.conversation.ConversationUtils Javadocs for details.
You update a build.xml
file to generate the JWS file that invokes a conversational Web Service by adding taskdefs
and a build-clientService
target that looks something like the following example. 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/conversation/ConversationalClientImpl.java" ><clientgen
wsdl="http://${wls.hostname}:${wls.port}/conv/ConversationalService?WSDL"
packageName="examples.webservices.conversation"/>
</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 ConversationalService
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. You do this because the ConversationalClientImpl
JWS file imports and uses one of the generated classes.
The following example shows a simple stand-alone Java client that invokes the conversational Web Service described in Programming Guidelines for the Conversational JWS File. See the explanation after the example for coding guidelines that correspond to the Java code in bold.
package examples.webservices.conv_standalone.client;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;
import weblogic.wsee.jaxrpc.WLStub;
/**
* stand-alone client that invokes and converses with ConversationlService.
*/
public class Main {
public static void main(String[] args)
throws ServiceException, RemoteException{
ConversationalService service = new ConversationalService_Impl(args[0] + "?WSDL");
ConversationalPortType port = service.getConversationalServicePort();
// Set property on stub to specify that client is invoking a Web Service
// that uses advanced features; this property is automatically set if
// the client runs in a WebLogic Server instance.
Stub stub = (Stub)port;
stub._setProperty(WLStub.COMPLEX, "true");
// Invoke start operation to begin the conversationString result = port.start();
System.out.println("start method executed.");
System.out.println("The message is: " + result);
// Invoke continue operationresult = port.middle("middle" );
System.out.println("middle method executed.");
System.out.println("The message is: " + result);
// Invoke finish operationresult = port.finish("finish" );
System.out.println("finish method executed.");
System.out.println("The message is: " + result);
}
}
Follow these guidelines when programming the stand-alone Java client that invokes a conversational Web Service. Code snippets of the guidelines are shown in bold in the preceding example.
weblogic.wsee.jaxrpc.WLStub
class:import weblogic.wsee.jaxrpc.WLStub;
WLStub.Complex
property on the JAX-RPC stub of the ConversationalService
using the _setProperty
method:Stub stub = (Stub)port;
stub._setProperty(WLStub.COMPLEX, "true");
This property specifies to the Web Services runtime that the client is going to invoke an advanced Web Service, in this case a conversational one. This property is automatically set when invoking a conversational Web Service from another WebLogic Web Service.
String result = port.start();
result = port.middle(message );
result = port.finish(message );
WebLogic Server supports production redeployment, which means that you can deploy a new version of an updated conversational 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 Web Service, its work is considered complete when the existing conversation is explicitly ended by the client or because of a timeout.
For additional information about production redployment and Web Service clients, see “Client Considerations When Redeploying a Web Service” in Getting Started With WebLogic Web Services Using JAX-RPC.