Integration Design Pattern – Synchronous Facade for Asynchronous Interaction

Introduction

In this blog, we will explore a Hybrid Message Interaction pattern, which combines the characteristics of traditional Synchronous Request-Reply and Asynchronous patterns. We will also see, the need for such a design pattern and how it can be implemented using Oracle SOA Suite.

Need for this Design Pattern

A Hybrid Synchronous-Asynchronous message exchange pattern is a requirement that pops up often in architectural discussions at customer engagements. The below discussion summarizes the need for such a design pattern.

Consider the following scenario:

A Web Client end-user fills in a form and submits a request. This is a blocking request and the client waits for a reply. The process is expected to reply to the user within a short period and let us assume that the client times out after 30 seconds. In a happy path, the backend systems are responsive and user receives the response within 30 seconds. This is shown in the below ‘Synchronous – Happy Path’ diagram.

pic1

Now, consider if a backend delay or system outage prevents a response from the website within 30s. All that the client receives is a Timeout Error. No further information is available and the user can only refill and resubmit the form, another time! This is shown in the below ‘Synchronous – Not so Happy Path’ diagram.

pic2The above solution is designed for the happy path. It can even be optimized for a high throughput in the happy path scenario. But for the negative path, it is desirable to have a more responsive and user friendly behavior. We should note that any design for the negative scenario would inherently be Asynchronous in nature, as we do not want the user to wait for the delayed response. Rather the user should be notified by other means whenever such a response is available.

Even though the percentage of requests that end up in the delayed scenario may be quite less, it is still desirable that such requests are handled in a more user friendly manner. We also want to achieve the Asynchronous error handling without sacrificing the high performance of a purely synchronous interaction.

The next section proposes such a design

The Hybrid Design Pattern

Consider an alternative to the earlier discussed design, where the website is more resilient against such error conditions.

In this design, whenever any backend delay or system outage prevents a response from the website within 30s, then the website provides the user with an acknowledgement ID at the end of 30s. This acknowledgement ID is something that the user can use to track the status of his request offline when he or she calls up the customer care.

Meanwhile the website, after acknowledging the client in 30s, continues to wait for a response from the backend. When the actual response is eventually available, the user is notified promptly via email or sms or any notification channel. The ‘Hybrid Sync-Async Interaction’ diagram below depicts this design.  Note that the positive case of a happy path remains to be synchronous delivering the timely responses immediately to the UI user.

Pic3_Sync_Async_Hybrid

This above use case has a mixture of Synchronous and Asynchronous characteristics. The interaction from the client side for the 30s interval is purely synchronous. Whereas the delayed message processing is asynchronous and may involve the use of Queues, database table or other means of persisting messages.

Implementation using Oracle SOA Suite

Oracle SOA Suite provides the tools to implement such a hybrid message interaction. We will explore the SOA Suite implementation and example source code.

This implementation assumes that the backend legacy systems are represented as a pair of request and response queues.  In reality these could be any complex systems or integration with multiple systems over different protocols and interfaces.

SOA Suite Components

The implementation is divided up in 2 BPEL components.

The SyncWrapperProcess provides the synchronous interface to the UI client. It manages the Synchronous blocking call by the client and is responsible to pass on the backend responses as Synchronous Replies or propagate appropriate fault to the UI Client. This process is implemented using the “Synchronous BPEL Process” template.

Pic4_SyncWrapperCompositeThe AsyncInteractionProcess acts as the Asynchronous client to the Backend legacy systems. It is responsible to orchestrate multiple requests with the back end and also manage the timing of responses to the SyncWrapper. This process is implemented using the “Asynchronous BPEL Process” template.

Pic5_AsyncInteractionCompositeThe below Cross Functional Flow Chart shows the division of responsibilities between the components. It also depicts the interactions with the UI Client the Backend Legacy system. Note that the Backend systems are represented here as the black box behind the pair of queues.

 

pic6_SyncFacade_v0.1

 

Screenshots of the SyncWrapper and AsyncInteraction BPEL processes shed more light into the BPEL orchestration and activities required within these processes. The activities and orchestration logic is use-case specific and we will refrain from deep diving into these BPEL processes themselves.

Pic7_SyncWrapperBPEL

Pic8_AsyncInteractionBPEL

However, what is of more importance is to delve into some finer aspects of the implementation which make the hybrid interaction solution possible.

Transaction Boundaries

  1. The SyncWrapper process is configured with transaction attribute – requiresNew. This is required to start the transaction for the overall interaction. Also the assumption here is that there isn’t a need for transaction propagation from the UI client.
  • config.transaction = ‘requiresNew’ in composite.xml of SyncWrapperProject

 

  1. The AsyncInteractionProcess is configured to participate in the transaction initiated by SyncWrapper. Also the deliveryPolicy is set to sync. This ensures that the same thread from the SyncWrapper is used for the invocation of AsyncInteractionProcess and that any fault can be propagated back to the client during the sync interaction period.
  • config.transaction = ‘required’ in composite.xml of AsyncInteractionProject
  • config.oneWayDeliveryPolicy = ‘sync’ in composite.xml of AsyncInteractionProject

 

Cluster-awareness:

One of the main pitfalls of using Asynchronous activities like ‘receive’ and ‘onMessage’ within Synchronous BPEL process is the issue of cluster awareness.  In multi node clustered environments, there is no guarantee that the callback messages arrive on the same server where the sync UI client is waiting for response.

The below diagram depicts the case when the callback message arrives at the origin node and hence the client receives the response message.

pic9_ClusterAwareness_2On the contrary, the diagram below shows the case when the callback message reaches the Synchronous process where the client is not listening to. This causes the client, which is listening on node 1, to timeout!

pic10_ClusterAwareness_2

In this implementation, the backend response message could arrive on any of the distributed queue members and this can rehydrate the AsyncProcess on any server in a cluster. But we want the callback to Sync process, to arrive on the specific server where the request originated from. This can achieved by setting the wsa.replyToAddress during the ‘invoke’ from Sync to Async BPEL process. Below are the required settings.

  • replyToAddress = Sync process’s service endpoint url of originating server.
  • faultToAddress = Sync process’s service endpoint url of originating server.

pic11_BpelProperties

 

Care should be taken to ensure that the value of the CallbackURL is computed at runtime and it resolves to the Service endpoint url of the SyncWrapperProcess on the originating server.  Please refer to the Java_Embedding block in the SyncWrapperProcess [source code provided here] for one way of obtaining the correct endpoint url. This can potentially be resolved using other methods as well.

OnAlarms

The AsyncInteractionProcess uses 2 ‘onAlarm’ handlers for executing the timebound activities.

The first ‘onAlarm’ is configured for the communications scope which encloses the ‘invoke’ and ‘receive’ activities with the Legacy backend systems. It triggers after elapse of 30s and is designed to send a synchronous acknowledgement message back to the UI client. Let us call this the ‘Comms_onAlarm’.

The second ‘onAlarm’ is set for the main overall scope of the Asynchronous process. This triggers after a sufficiently long wait like 3 minutes. This onAlarm block is responsible to abort the process instance so as not to have lingering long running process instances as a result of missing responses from the backend system.  This is the ‘InstanceCleanup_onAlarm’.

Note that any response messages received after the ’InstanceCleanup_onAlarm’ are effectively orphaned callback messages. These cannot be recovered from the BPEL console and will remain in the DLV_MESSAGE table of SOAINFRA until they are purged.  This should be borne in mind when setting the value for ‘InstanceCleanup_onAlarm’.

 

Sync Timeout settings

The ‘Comms_onAlarm’ should be small enough to complete within the BPEL SyncMaxWaitTime  and JTA Transaction Timeout periods. If this is not set correctly, the end user may receive a Webservice Fault or a Transaction Timeout fault instead of the acknowledgement message response.

  • SyncMaxWaitTime < BPEL EJB Timeout
  • onAlarm(1) duration < SyncMaxWaitTime

References

  •  JDeveloper Project /  Source code of the project is provided here

Add Your Comment