Building Services that Retry

When creating a service, you can construct and configure the service to retry automatically if a transient error occurs during service execution. A transient error is an error that arises from a temporary condition that might be resolved or restored, such as the unavailability of a resource due to network issues or failure to connect to a database. The service might execute successfully if Integration Server waits a short interval of time and then retries the service.

To build a service that retries, you create it so that it catches errors and determines whether an error is transient. When the service determines that an error is transient, have it re-throw the error as an ISRuntimeException. The ISRuntimeException is the signal to Integration Server to retry the service. For more information about how to construct the service, see Requirements for Retrying a Service and Example Service that Throws an Exception for Retry.

In addition to constructing the service for retry, you also must set retry properties for the service (or the trigger calling the service) so that Integration Server knows that it is to retry a service when an ISRuntimeException is thrown. When Integration Server retries the service it re-executes it using the original input. For more information about how to configure a service for retry, see About Automatic Service Retry and Configuring Service Retry.

Requirements for Retrying a Service

If you want a service to catch a transient error, re-throw it as an ISRuntimeException, and then re-execute, the following criteria must be met:

  • You must configure the Transient error handling properties for the top-level service. For more information about configuring service retry and how Integration Server retries services, see Configuring Service Retry.
  • If the service functions as a trigger service (the service is invoked by a trigger), you must configure the Transient error handling properties for the trigger. In this situation, Integration Server uses the trigger retry properties instead of the service retry properties. For more information about configuring retry for webMethods Messaging Triggers, see the Configuring Transient Error Handling for a webMethods Messaging Trigger. For information about configuring retry for JMS triggers, see the Configuring Transient Error Handling for a Non-Transacted JMS Trigger.
  • If the service is a flow service, the service must invoke pub.flow:throwExceptionForRetry to throw the ISRuntimeException. For more information about the pub.flow:throwExceptionForRetry service, see the webMethods Integration Server Built-In Services Reference.
  • If the service is written in Java, the service can use com.wm.app.b2b.server.ISRuntimeException() to throw the ISRuntimeException. For more information about constructing ISRuntimeExceptions in Java services, see webMethods Integration Server Java API Reference for the com.wm.app.b2b.server.ISRuntimeException class.
  • If the service invokes an adapter service, ensure that the service catches transient errors that the adapter service detects.

    When an adapter service built on Integration Server 6.0 or later, and based on the ART framework, detects a transient error, for example, if their back-end server is down or the network connection is broken, the adapter service propagates an exception that is based on ISRuntimeException. When creating a service that invokes an adapter service, ensure that the logic that catches errors and determines whether they are transient errors can interpret the adapter service exception that signals a retry.

    For more information about adapter services, see the relevant adapter guides.

Example Service that Throws an Exception for Retry

This example shows one possible way to build a service that catches errors, checks errors to determine whether they are transient, and re-throws an error as an ISRuntimeException if it is transient. It includes the following basic sections of logic:

  • An outer sequence that contains a try sequence and a catch sequence:
    • The try sequence executes the work that you want the service to perform.
    • The catch sequence examines any exception that occurs in the try sequence, determines whether the exception is a transient error, and indicates whether Integration Server should retry the service.

    The outer sequence is used so that the catch sequence is skipped when the try sequence is successful.

  • A throw exception step that executes only when the catch sequence indicates that a transient error occurred. It throws the ISRuntimeException to signal Integration Server that the service should be re-executed.
Figure 1. Example logic for a service that throws an exception for retry
  • STEP 1 - Outer SEQUENCE exits on SUCCESS

    The outer sequence wraps the try sequence and the catch sequence. This sequence is set to exit on success so that it exits when either of its child steps (the try sequence or the catch sequence) execute successfully. If the try sequence executes successfully, Integration Server skips the catch sequence.

  • STEP 1.1 - Try SEQUENCE exits on FAILURE

    The try sequence contains the logic you want the service to execute. This sequence is set to exit on failure. As a result, if a step in this try sequence fails, Integration Server executes the next step, which is the catch sequence that checks for transient errors.

  • STEP 1.1.1 - Insert service logic

    This step contains the logic that you want the service to perform. The service logic might consist of multiple services or flow steps.

    When the service logic executes successfully, that means the try sequence is successful. Because the outer sequence exits on success, Integration Server exits the outer sequence, skipping the catch sequence. Integration Server executes the next step, which is the BRANCH on ‘/isTransientError’ step.

    If an error occurs in the service logic, Integration Server exits the try sequence because it is set to exit on failure. As a result, Integration Server executes the catch sequence.

  • STEP 1.2 - Catch SEQUENCE exits on DONE

    Integration Server only executes the catch sequence if the try sequence failed. The catch sequence contains logic that evaluates the error to determine whether the error is transient.

    Because the catch sequence exits on DONE, the sequence is successful after Integration Server executes all the steps in the sequence. After the catch sequence is successful, the outer sequence, which is set to exit on success, also exits. Integration Server executes the next step, which is the BRANCH on ‘/isTransientError’ step.

  • STEP 1.2.1 - Catch the last error

    To determine whether a transient error occurred, the catch sequence first invokes the pub.flow:getLastError service to catch the error that caused the try sequence to fail.

    Important: The pub.flow:getLastError service must be the first service invoked within the catch sequence. If it is not first and a preceding service in the catch sequence fails, the error thrown in the try sequence is overwritten with the new error.
  • STEP 1.2.2 - Determine whether the error is a transient error

    This step evaluates the contents of the lastError document that the pub.flow:getLastError service returns to determine whether the try sequence failed because of a transient error. You might use multiple services or flow steps to determine whether a transient error occurred.

    Note: If the service logic in the try sequence includes an adapter service and a transient error occurs during adapter service execution, the adapter service throws an exception that extends the ISRuntimeException. Ensure that your catch sequence interprets the adapter service exception that signals retry. For more information, see Requirements for Retrying a Service.
  • STEP 1.2.3 - Set flag to indicate whether the service should retry

    This step sets the transient error flag based on whether the try sequence failed because of a transient error. In this example if a transient error occurred, the variable isTransientError) is set to “true”.

    After this step executes, Integration Server exits the catch sequence, exits the outer sequence, and then executes the BRANCH on ‘/isTransientError’ step.

  • STEP 2 - Check transient error flag

    This step uses the value of isTransientError to determine whether the service should throw an ISRuntimeException.

    If the try sequence executed successfully, isTransientError is null. As a result, Integration Server falls through to the end of the service because the value of the switch variable does not match any of the target steps. Integration Server will not attempt to retry the service.

    If the try sequence failed, but the catch sequence determined that the error was not transient, the catch sequence does not set isTransientError to “true”. It might be null or the catch sequence might set isTransientError to another value, for example, “false”. Either way, Integration Server falls through to the end of the service because the value of the switch variable does not match any of the target steps. Integration Server will not attempt to retry the service.

    If the try sequence failed and the catch sequence determined that the error was transient, isTransientError is “true”, and as a result, Integration Server executes the next step.

  • STEP 2.1 - Throws ISRuntimeException

    Integration Server executes this step to invoke pub.flow:throwExceptionForRetry service when the value of isTransientError is “true”. This service wraps the exception generated by the transient error in the try sequence and re-throws it as an ISRuntimeException.

    If the service is configured for retry, Integration Server retries the service if the maximum number of retries has not been reached. For more information, see Configuring Service Retry.