Reliable SOAP Messaging

WebLogic 8.1 supports a reliable SOAP messaging framework that enables an application hosted by one WebLogic instance to reliably invoke a web service hosted by another WebLogic instance. Reliability means that the sender will eventually know whether the SOAP message was received by the web service or if it was unable to deliver the message. In other words, WebLogic provides the sender with a transport guarantee only, and does not indicate whether the web service operation was invoked successfully. The sender must invoke the web service asynchronously and then either poll or register a listener to know whether the SOAP message was delivered.

WebLogic provides this reliability in the following ways:

Reliable SOAP messaging also imposes certain restrictions on its use:

Other than these restrictions, the reliable transport mechanism is transparent to both the application and the web service. WebLogic embeds all the reliable SOAP messaging logic in the runtime systems of the sender application and receiving web service.

19.6.1 Architecture

Reliability stems from the fact that both the sender and the receiver use JMS stores to keep a copy of the SOAP message until it has been delivered successfully. JMS stores can be kept in either the filesystem or the database, and you can read more about their setup in Chapter 8. A transaction context at the receiver's end further ensures that the receiver's runtime can correctly acknowledge the receipt of the SOAP message. In addition, the server's runtime can resend the SOAP message if its receipt hasn't been acknowledged. Let's take a closer look at the sequence of events that occur when a web service operation is reliably invoked:

  1. An application asynchronously invokes a reliable operation. Its runtime stores the SOAP message in a JMS store before sending it to the WebLogic instance hosting the web service.
  2. The receiver's runtime checks the incoming message against those already saved in its own JMS store. If the message is new (i.e., it is absent from its JMS store), the message ID is recorded in the store, the appropriate web service operation is invoked, and the message is acknowledged. If the message is not new (i.e., it already exists in the JMS store), the web service operation is skipped and the message simply is acknowledged. Note that all of the actions at the receiver's end occur within a transaction context.
  3. When the sender's runtime receives an acknowledgment, it removes the message from its JMS store to ensure that it is not delivered again. The sender's runtime also ensures that the application is notified if the SOAP message has been sent or was never delivered successfully, either through polling or via a registered listener.

Note that the receiver does not store the entire message, only its message ID. The sender runtime can be configured to retry a send automatically if the message was not acknowledged. The combination of the sender's retries, stored messages, and receiver's acknowledgment provides for a guaranteed delivery.

For example, even if the WebLogic instance hosting the web service is not available, the outgoing messages will be kept in the sender's JMS store, and the sender's runtime will try periodically to send them to the receiver. The transaction context at the receiver's end plays a key role in coordinating its activities. When the receiver's runtime receives a SOAP message, it performs a number of activities in a transaction context to preserve the integrity of the message IDs in its store. After a message has been received, the following actions occur:

  1. A transaction context is started.
  2. The receiver's runtime checks the message ID for duplicates in its JMS store. If a duplicate is found, it sends an acknowledgment back to the sender and rolls back the transaction. No further actions occur.
  3. If a duplicate isn't found, it saves the message ID in the JMS store.
  4. The web service operation is invoked.
  5. An acknowledgment is sent back to the sender's runtime.
  6. The transaction is committed.

The backend component that implements the web service operation can roll back the receiver's transaction. A rollback forces the sender's runtime to redeliver the SOAP message. It also ensures that the sender application is aware that the operation was not invoked. Note that ordinary application exceptions do not cause a rollback. For example, if a Java backend throws an exception, or if an EJB throws an application exception, the transaction isn't rolled back. Instead, the Java class or EJB must explicitly roll back the existing transaction context. An EJB can also throw a system exception (e.g., RemoteException) to cause a rollback. Finally, the transaction is rolled back if the WebLogic instance hosting the web service crashes.

19.6.2 Implementing Reliable Web Service Backends

If you implement the reliable web service with a Java backend, you must use the standard JTA to roll back the receiver's transaction context, as shown here:

try { //get the transaction context at the receiver's end tx = (UserTransaction) ctx.lookup("javax.transaction.UserTransaction"); //... } catch (Exception e) { //something went wrong tx.rollback( ); }

If you implement a web service using a stateless session EJB backend, you must remember the following:

The rest of the section looks at how to set up the WebLogic instances to use the reliable transport, configure the JMS stores, and finally write the sender application.

19.6.2.1 Building the sender and receiver

To enable reliable messaging at the web service's end, use the servicegen Ant task to build the web service, but also include the reliability subelement:

 

The reliability element has two optional attributes:

duplicateElimination

Use this attribute to determine whether the service should ignore duplicate invocations by keeping track of the message IDs. If you set this attribute to false, the message IDs are not recorded and you run the risk of an operation being invoked more than once.

persistDuration

Use this attribute to set the minimum number of seconds that the receiver should persist the history of a reliable SOAP message. It defaults to 60000.

If you specify the reliability subelement within the servicegen task, each operation that returns void will be configured for reliable invocations. If you want only specific operations to be reliably invoked, you must manually edit the web-services.xml descriptor. For example, here is an excerpt that highlights this:

The sender must invoke the reliable operation asynchronously, so remember to set the generateAsyncMethods attribute to true when employing clientgen to create the client JAR.

19.6.2.2 Configuring the servers

Both servers participating in reliable SOAP messaging must be configured with a JMS store. In other words, you must configure the web service system on both servers to use a JMS store. You can do this by selecting the server from the Administration Console and then navigating to the Services/Web Services tab. Use the drop-down list in the Store attribute to select the JMS store to be used.

For the sender, you also can set the Retry Count and Retry Interval attributes. The retry count determines the maximum number of times a sender should try to deliver an unacknowledged message, while the retry interval determines the minimum duration (in seconds) to wait between attempting to redeliver. For the receiver, you can set the Default Time To Live attribute, which determines the duration (in seconds) that a receiver should store the history of the message. The Default Time To Live setting determines how long the sender's runtime will attempt to resend a message with the same message ID. If the sender's runtime cannot send a message successfully before the Default Time To Live duration, it reports a delivery failure.

The persist-duration attribute that you specify for the reliable-delivery element when using servicegen can be set on a per-operation basis and corresponds to the time-to-live attribute that you can set for the server. The server setting defines the default value and always should be larger than the duration specified for any operation.

19.6.2.3 Writing the receiver

An application can invoke an operation in the standard way, without using the reliable delivery mechanism. If you want the benefit of a reliable invocation, however, the sender also must supply an AsyncInfo object to the operation. Here is an example:

AsyncInfo asyncInfo = new AsyncInfo( ); asyncInfo.setReliableDelivery(true); FutureResult fr = port.startReliableOperation("hello World", asyncInfo); port.endReliableOperation(fr);

Except for the call to setReliableDelivery( ), the rest of the code is identical to how you would create asynchronous clients. Because this is an asynchronous client, you could either poll for a return or register a ResultListener object.

Категории