Using Reliable SOAP Messaging
The following sections describe how to use reliable SOAP messaging, both as a sender and a receiver of a SOAP message, between WebLogic Server instances:
Warning: Reliable SOAP Messaging is not supported in a clustered environment.
Overview of Reliable SOAP Messaging
Reliable SOAP messaging is a framework whereby an application running in one WebLogic Server instance can asynchronously and reliably invoke a Web Service running on another WebLogic Server instance. Reliable is defined as the ability to guarantee message delivery between the two Web Services.
Note: Reliable SOAP messaging works between two Web Services deployed on a single WebLogic Server instance. Typically this setup is used for development. However, in real-life, reliable SOAP messaging is meant to be used between two WebLogic Server instances, both of which must be configured to use reliable SOAP messaging.
The sender WebLogic Server has an application that asynchronously invokes a reliable Web Service operation running on the receiver WebLogic Server. The sender sends the receiver a SOAP message that has reliable SOAP messaging information in its header. The Web Service operation being invoked has been configured for reliable SOAP messaging. Due to the asynchronous nature of the invoke, the sender does not immediately know whether the relevant operation has been invoked, but it has the guarantee that it will get one of two possible notifications:
- The message has been received by the receiver.
Note: This does not mean that the Web Service operation on the receiver WebLogic Server was invoked successfully; the operation might fail due to an application exception. The exception is included in the notification to the sender. For details about transactions, see Receiver Transactional Context.
- The sender was unable to deliver the message.
Using the Weblogic Web Services asynchronous API, the sender can either poll the receiver for notification, or register a callback to be notified. Eventually, either the sender receives a notification that the message was received, or it receives notification that the message was not delivered.
Reliable SOAP messaging is transport-independent. By default, it uses HTTP/S. However, you can also use JMS if you configure the receiving Web Service appropriately and use the JMS port when the sender invokes the Web Service. For details on using JMS transport, see Using JMS Transport to Invoke a WebLogic Web Service.
Reliable SOAP Messaging Architecture
The following terms are used in this section:
- sender: The WebLogic Server instance that sends the reliable SOAP message.
- sender application: The user application running in the sender that reliably invokes a Web Service operation running on the receiver.
- sender runtime: The WebLogic Server code running on the sender that handles reliable SOAP messaging.
- receiver: The WebLogic Server instance that receives a reliable SOAP message.
- receiver Web Service: The Web Service running on the receiver that contains the operation configured to be invoked reliably.
- receiver runtime: The WebLogic Server code running on the receiver that handles reliable SOAP messaging.
The following diagram and corresponding steps describe the architecture of the reliable SOAP messaging feature.
Figure 10-1 Reliable SOAP Messaging Architecture
- The sender application invokes a reliable operation running on the receiver WebLogic Server.
- The sender runtime saves the message in its persistent JMS store. The store can be either a JMS File or JDBC store.
The sender runtime sends the SOAP message to the receiver WebLogic Server.
- The receiver runtime receives the message, checks for duplicates in its persistent JMS store, and if none are found, saves the message ID in its store. If it finds a duplicate, the receiver runtime acknowledges the message, but does not deliver it to the receiver Web Service.
Note: Only the message ID, and not the entire message itself, is persisted in the receiver's store.
The actions performed by the receiver execute within the context of a transaction. See Receiver Transactional Context.
- The receiver runtime invokes the reliable operation and sends an acknowledgement back to the sender in the SOAP header.
Because only void operations can be invoked reliably, the receiver does not return any values to the sender. If the invoked operation throws an application exception, the exception is, however, sent back to the sender. System exceptions (from EJBs, but not from Java classes) roll back the transaction started by a receiver. For details, see Receiver Transactional Context.
- The sender runtime removes the message from its persistent store so that the message does not get sent again.
The sender is configured to retry sending the message if it does not receive notification of receipt. You configure the number of retries, and amount of time between retries, of the sender using the Administration Console. Once sender runtime has resent the message the maximum number of retries, it removes the message from its store.
- The sender runtime sends notification to the sender application (either via callbacks or polling) that either the message was received and the operation invoked or that it was never successfully delivered.
Receiver Transactional Context
When the receiver runtime receives a message from a sender, it starts a transaction, and the following subsequent receiver actions execute within the context of this transaction:
- Receives a message from the sender.
- Starts a transaction.
- Checks for duplicates in its persistent store.
- If duplicates are found, the receiver sends an acknowledgement back to the sender and rolls back the transaction.
- If no duplicates are found, saves the message ID in its store.
- Invokes the operation.
- Sends an acknowledgment back to the sender.
- Commits the transaction.
The main reason the receiver executes all its actions within the context of a transaction is to preserve the integrity of the message IDs in its persistent store. For example, suppose WebLogic Server crashes right after the receiver saves a message ID in its store, but before it invokes the operation; in this case, the transaction is rolled back and the saved message ID is removed from the store. Later, when the sender resends the message (because it has not yet received an acknowledgement that the operation was invoked), the receiver has no history of the message and will correctly go through the whole process again. If the receiver had not executed within the context of a transaction, it would never invoke the operation in this case because of the incorrect presence of the message ID in its store.
The transaction started by the receiver is rolled back if any of the following events occurs during the transaction:
- WebLogic Server crashes.
- The EJB container or EJB application method that implements the operation issues a rollback.
- The Java class method that implements the operation issues a rollback.
- The EJB container or EJB application method throws a system exception, such as a RemoteException.
The following events do not cause a rollback of the transaction:
- The EJB application method throws an application exception. An example of an application exception is WithdrawalErrorException, which is thrown by a method when a user tries to withdraw too much money from their account.
- The Java class method throws any exception.
Guidelines For Programming the EJB That Implements a Reliable Web Service Operation
When creating a stateless session EJB-implemented Web Service whose operations can be invoked reliably, follow these guidelines when programming the EJB:
- The EJB must use only container-managed transactions; bean-managed transactions are not supported.
- The transactional attribute of the EJB method that implements the reliable operation must be set to one of the following values:
- Required (recommended)
- Supports
- Mandatory
Set the transactional attribute of an EJB method with the <trans-attribute> element in the ejb-jar.xml deployment descriptor.
- If you want to explicitly roll back the transaction from the EJB application method, use the EJBContext.setRollbackOnly() method.
- Be aware that system exceptions (such as RemoteException) thrown by the EJB container or the EJB application method will roll back the transaction. Application exceptions (such as WithdrawalErrorException thrown by the EJB when a user tries to withdraw too much money from an account) do not roll back the transaction.
For more information, see Programming WebLogic Enterprise JavaBeans and Programming WebLogic JTA.
Guidelines for Programming the Java Class That Implements a Reliable Web Service Operation
When creating a Java class-implemented Web Service whose operations can be invoked reliably, follow these guidelines when programming the Java class:
- If you want to roll back the transaction from the Java method, use the Java Transaction API (JTA) to get the transaction object and then explicitly roll back the transaction.
- Be aware exceptions thrown by the Java class never roll back the transaction.
For more information, see Programming WebLogic JTA.
Configuring the Transaction
Use the Administration Console to configure the following transaction attributes:
- Transaction time-out and limits
- Transaction manager behavior
Configuration settings for JTA transactions are applicable at the domain level. This means that configuration attribute settings apply to all servers within a domain. For details, see Configuring Transactions.
Limitations of Reliable SOAP Messaging
- Only Web Service operations that return void can be configured to be invoked reliably.
- One-way Web Service operations cannot be configured to be invoked reliably.
Using Reliable SOAP Messaging: Main Steps
The following procedure describes the main steps for configuring reliable SOAP messaging to invoke a WebLogic Web Service operation. The procedure describes configuration and code-writing tasks that take place in both the sender and receiver WebLogic Server instances.
Note: It is assumed that you have already implemented and assembled a WebLogic Web Service and you want to enable one or more of its operations to be invoked reliably. Additionally, it is assumed that you have already coded a server-side application (such as a servlet in a Web application) that invokes the Web Service in a non-reliable way and you want to update the application to invoke the Web Service reliably.
For details about these tasks, see Implementing WebLogic Web Services, Assembling WebLogic Web Services Using Ant Tasks, and Invoking Web Services from Client Applications and WebLogic Server.
- Configure the reliable SOAP messaging attributes for the sender WebLogic Server instance.
- Configure the reliable SOAP messaging attributes for the receiver WebLogic Server instance.
- Update the build.xml file that contains the call to the servicegen Ant task, adding the <reliability> child element to the <service> element that builds your Web Service on the receiver WebLogic Server, as shown in the following example:
<servicegen destEar="ears/myWebService.ear" warName="myWAR.war" contextURI="web_services" > <service ejbJar="jars/myEJB.jar" targetNamespace="http://www.bea.com/examples/Trader" serviceName="TraderService" serviceURI="/TraderService" generateTypes="True" expandMethods="True" > <reliability duplicateElimination="True" persistDuration="60" />
</service> </servicegen>In the example, the Web Service ignores duplicate invokes from the same sender application and persists messages for at least 60 seconds. For more information on the attributes of the <reliability> element, see servicegen.
Note: When you regenerate your Web Service using this build.xml file, every operation that returns void will be enabled for reliable invocation. If you want only certain operations to be invoked reliably, or you prefer not to regenerate your Web Service using servicegen, you can update the web-services.xml file of your WebLogic Web Service manually. For details, see Updating the web-services.xml File Manually for Reliable SOAP Messaging.
- Re-run the servicegen Ant task to regenerate your receiver Web Service.
- Re-run the clientgen Ant task, specifying the generateAsyncMethods="True" attribute, to generate a new Web Service-specific client JAR file that contains the asynchronous operation invocations. This new client JAR file will be used with the server-side application running in the sender WebLogic Server.
- On the client application running on the sender WebLogic Server, update the Java code that invokes the Web Service to invoke it reliably.
For an example, see Writing the Java Code to Invoke an Operation Reliably.
Configuring the Sender WebLogic Server
This section describes how to configure reliable SOAP messaging attributes for a WebLogic Server instance in its role as a sender of a reliable SOAP message.
Note: Part of the reliable SOAP messaging configuration involves configuring, if it does not already exist, a JMS File or JDBC store.
The following table describes the reliable SOAP messaging attributes.
To configure these attributes:
- Invoke the Administration Console in your browser, as described in Overview of Administering WebLogic Web Services.
- Create, if one does not already exist, a JMS store. This can be either a JMS File store or a JMS JDBC store. See JMS File Store Tasks and JMS JDBC Store Tasks.
- Click the Servers node in the left pane.
- Select the WebLogic Server for which you want to configure reliable SOAP messaging in its role as a sender.
- In the right pane, select the Services
- > Web Services tab.- Select the JMS store from the Store drop-down list that will contain WebLogic Server's reliable SOAP messages when acting as a sender.
- Enter the default maximum number of times the sender WebLogic Server should attempt to resend a message in the Default Retry Count field.
- Enter the default minimum number of seconds that the sender WebLogic Server should wait between retries in the Default Retry Interval field.
- Enter the default minimum number of seconds that the receiver of the reliable SOAP message should persist the history of the message in its JMS store in the Default Time to Live field
Warning: This value should be larger than the corresponding value of any Web Service operation being invoked reliably. Later sections describe how to configure his value in the Web Service's web-services.xml file by updating the persist-duration attribute of the <reliable-delivery> subelement of the invoked <operation>.
- Click Apply.
Configuring the Receiver WebLogic Server
This section describes how to configure reliable SOAP messaging attributes for a WebLogic Server instance in its role as a receiver of a reliable SOAP message.
Note: Part of the reliable SOAP messaging configuration involves configuring, if it does not already exist, a JMS File or JDBC store.
The following table describes the reliable SOAP messaging attributes.
To configure these attributes:
- Invoke the Administration Console in your browser, as described in Overview of Administering WebLogic Web Services.
- Create, if one does not already exist, a JMS store. This can be either a JMS File store or a JMS JDBC store. See JMS File Store Tasks and JMS JDBC Store Tasks.
- Click the Servers node in the left pane.
- Select the WebLogic Server for which you want to configure reliable SOAP messaging in its role as a receiver.
- In the right pane, select the Services
- > Web Services tab.- Select the JMS store from the Store drop-down list that will be used for duplicate elimination by the receiver.
- Enter the number of seconds in the Default Time to Live field.
Later sections in this document describe how each Web Service operation can override this default value. See Updating the web-services.xml File Manually for Reliable SOAP Messaging.
- Click Apply.
Writing the Java Code to Invoke an Operation Reliably
You specify that a WebLogic Web Service operation is reliable by updating its definition in the web-services.xml file, adding the <reliable-deliver> child element to the corresponding <operation> element. You can do this using the servicegen Ant task (see Using Reliable SOAP Messaging: Main Steps), or by updating the web-services.xml file manually (see Updating the web-services.xml File Manually for Reliable SOAP Messaging). A client application, however, is not required to invoke a reliable operation in a reliable manner. There are three ways to invoke a reliable operation:
- Synchronously with no reliability. This is the standard JAX-RPC way of invoking operations.
- Asynchronously with no reliability, as described in Writing an Asynchronous Client Application.
- Asynchronously with reliability, as described in this chapter.
Writing the Java code to invoke a Web Service operation reliably from a sender application is very similar to invoking an operation asynchronously, as described in Writing an Asynchronous Client Application. The asynchronous invoke of an operation is split into two methods: startOperation() and endOperation().
In addition to the standard asynchronous client Java code, to invoke an operation reliably :
- Enable reliable delivery in your client application with the AsyncInfo.setReliableDelivery(true) method.
This method also checks for correct JMS configuration and throws an exception if it finds any errors in the configuration.
- Optionally create and set a listener to listen for the results of a reliable operation invocation with the AsyncInfo.setResultListener(listener) method. The listener class implements the ResultListener interface, which in turn defines the onCompletion() listener callback method in which you define what happens when the asynchronous reliable operation invocation completes.
The following example shows the simplest way to invoke the processOrder() operation asynchronously and reliably by specifying the setReliableDeliver(true) method and using the asynchronous API to split the operation into two invocations: startProcessOrder() and endProcessOrder(). You tell the clientgen Ant task to generate these two methods in the stubs by specifying the generateAsyncMethods attribute.
import weblogic.utils.Debug;import weblogic.webservice.async.AsyncInfo;
import weblogic.webservice.async.FutureResult;public final class ReliableSender {public void placeOrder(String order) { try { // set up Web Service port MarketService market = new MarketService_Impl(); MarketServicePort marketPort = marketService.getMarketServicePort();// enable reliable delivery AsyncInfo asyncCtx = new AsyncInfo(); asyncCtx.setReliableDelivery(true);// call the Web Service asynchronously FutureResult futureResult = marketPort.startProcessOrder(order, asyncCtx); marketPort.endProcessOrder(futureResult);} catch (Exception e) { Debug.say("Exception in ReliableSender: " + e); } }
}The following more complex example builds on the previous by setting a result listener to listen for the completion of the asynchronous and reliable operation invoke. The implementation of the onCompletion() method specifies what happens when the invoke completes; in the example, a message is printed if the invoke failed.
import java.io.Serializable;import weblogic.webservice.async.AsyncInfo;
import weblogic.webservice.async.FutureResult;
import weblogic.webservice.async.InvokeCompletedEvent;
import weblogic.webservice.async.ResultListener;
import weblogic.webservice.async.ReliableDeliveryFailureEvent;import weblogic.utils.Debug;public final class ReliableSender {public void placeOrder(String order) { try { // set up Web Service port MarketService market = new MarketService_Impl(); MarketServicePort marketPort = marketService.getMarketServicePort();// enable reliable delivery AsyncInfo asyncCtx = new AsyncInfo(); asyncCtx.setReliableDelivery(true);// set up the result listener RMListener listener = new RMListener(); asyncCtx.setResultListener(listener);// call the Web Service asynchronously FutureResult futureResult = marketPort.startProcessOrder(order, asyncCtx);while ( !futureResult.isCompleted()) { Debug.say("async polling ..."); // do something else Thread.sleep(3000); }marketPort.endProcessOrder(futureResult);} catch (Exception e) { Debug.say("Exception in ReliableSender: " + e); } }
}class RMListener implements ResultListener, Serializable {public void onCompletion(InvokeCompletedEvent event) { if (event instanceof ReliableDeliveryFailureEvent) { ReliableDeliveryFailureEvent rdEvent = (ReliableDeliveryFailureEvent) event; Debug.say("Reliable delivery failed with the following message: " + rdEvent.getErrorMessage()); } }
}
Handling Sender Server Failures
The application that invokes an operation reliably must handle the case where the sender server crashes in the middle of retrying SOAP message delivery. Once the sender server restarts, it will check its persistent store for any messages that have not yet been successfully delivered, and if it finds any, it will continue trying to send the message to the receiver server. The problem, however, is that due to the sender server crash, the application that initially invoked the operation reliably may not be deployed anymore, and when the receiver server sends back an acknowledgement after the sender server restarts, there will be no application to accept the acknowledgment.
To handle this situation correctly, code your application to follow these guidelines:
- Create a class that implements the ResultListener interface. This class listens for the completion of the reliable operation invoke. See the second example Writing the Java Code to Invoke an Operation Reliably for a sample of writing this class.
- Code the class that implements the ResultListener interface to also implement the Serializable interface to ensure that, in case of a sender server crash, the class will be serialized and stored on disk. Then, once the sender server restarts, the result listener class will also be invoked and will handle subsequent acknowledgment messages from the receiver.
- Be sure to also serialize any information needed by the result listener class so that once the class is instantiated after a sender server crash it can return to its previous state and correctly handle acknowledgments from the receiver.
Updating the web-services.xml File Manually for Reliable SOAP Messaging
If you regenerated your Web Service using the servicegen Ant task, every operation that returns void is enabled for reliable invocation. If you want only certain operations to be invoked reliably, or you prefer not to regenerate your Web Service using servicegen, you can update the web-services.xml file of your WebLogic Web Service manually, as described in this section.
The web-services.xml file is located in the WEB-INF directory of the Web application of the Web Services EAR file. See The Web Service EAR File Package for more information on locating the file.
To update the web-services.xml file to enable reliable SOAP messaging for one or more operations:
- Open the file in your favorite editor.
- For each operation for which you want to enable reliable SOAP messaging, add a <reliable-delivery> subelement and specify the following optional attributes:
- duplicate-elimination - Boolean that specifies whether the WebLogic Web Service should ignore duplicate invokes with the same message ID from the same sender application. Default value is True.
- persist-duration - Integer value that specifies the minimum number of seconds that the Web Service should persist the history of the reliable SOAP message (received from the sender that invoked the Web Service) in its storage. When persist-duration seconds have elapsed, the receiver WebLogic Server deletes the history of the message from its store. The value of this attribute, if you set it, should be greater than the product of the retry interval and the retry count of the sender.
This attribute overrides the default server value you set in Configuring the Receiver WebLogic Server. The default if neither is set is 360 seconds.
The following example shows an operation that can be invoked reliably:
<operation name="getQuote" component="simpleStockQuoteBean" method="getQuote">
<reliable-delivery persist-duration="80" />
</operation>