In both XI forum and weblogs, Sync/Async scenarios have always been a constant. To satisfy these scenarios, several solutions have already been proposed, most of them based on ccBPM. However, sometimes the overall integration performance is a real constraint and ccBPM cannot be used. To address such cases, some solutions have also already been proposed, mainly regarding JMS scenarios. That's because the Java Message Service natively deals with the correlation between the asynchronous messages, referring to the request message in the response message, by using the JMSCorrelationID header field. Documentation regarding async/sync and sync/async scenarios with JMS adapter may be found in the following link:
However, in most of the times, the communication protocol is not a development option, but rather a requirement. For instance, consider a legacy system which can only handle files (no API is available) and suppose you want to consume one of its services from a synchronous RFC in ERP system. This is going to be our sample scenario.
Finally, I'd like to comment on the differences between Sync/Async and Async/Sync scenarios.
Briefly, Async/Sync scenarios are simpler in the point of view of middleware development, since you don't need to address the correlation between the two asynchronous messages. For example, in a ccBPM approach, you don't need to create a correlation between those messages, since they are treated in the same logical transaction (the inbound async message is triggered, indirectly, by the outbound one). Since no correlation needs to be handled inside XI, the same logic (and the same standard modules) used for the JMS scenario may be used for non-JMS adapters, for example an File -> RFC -> File scenario, eliminating the necessity of custom developments. This scenario has already been addressed by Bhavesh Kantilal in this thread: File - RFC - File without a BPM - Possible from SP 19..
For Sync/Async scenarios, the correlation between the asynchronous calls needs to be handled in the middleware, and that makes it a little more difficult to be implemented. In ccBPMs, you need to define a correlation to link both async messages. In JMS scenario without BPM, you have the JMSCorrelationID which does the correlation. So, what we need to do is to handle this correlation between the async messages, in order for XI to understand that those messages are linked. For that, we could use the same modules of Sync/Async JMS scenario plus an extra logic to handle the correlation. As described in the thread above, this solution is available from XI 3.0 SP19 and PI 7.0 SP10.
As in the Sync/Async JMS scenario, the repository development simply includes the inbound and outbound interfaces (both defined as synchronous) and relevant message and interface mappings.
In our scenario, we've developed a simple sync RFC to request the service to XI and process the response. The RFC definition (request and response messages) may be found below:
The file message definitions are also very simple:
Finally, we've developed simple straightforward message mappings for the messages above and an interface mapping between the sync interfaces.
2.2.1. Implementation Considerations
This is where the main changes take place. However, most of the changes are as described in the JMS case. But before we go into the implementation details, I'd like to comment a little further on the differences between the JMS and the non-JMS cases.
As commented before, the critical point here is the correlation between the asynchronous messages. Since they are not natively correlated (as in the JMS case), we have to explicitly define this correlation.
To correlate two asynchronous messages, we have to set the Correlation Id message attribute in the response message with the Message ID of the request message, so that they will be correlated by XI. So, we need to send the Message ID of the request message for the receiver, in order for the application to be able to process the request, create a response and include that Message ID in the response message, as the Correlation ID.
There are several ways of achieving that. One could, for example, include the Message ID in some field of the request payload, for the application to be able to process it and send the Message Id in some field of the response payload. Also, a custom module would be needed to parse the response message and set the Correlation Id attribute with its value (using message.setCorrelationId() method). The module is necessary because the Correlation Id is evaluated in the Adapter Engine itself, before any mappings take place.
But to make it simpler and to show that the proposed scenario can be implemented without any custom code (only standard features), we went for a simpler logic. Instead of having the Message ID in the payload, we set the request file name with the Message ID. Then the receiver application processes the file and returns the response file with the same file name. When XI pools the response file, we retrieve the file name and set it as the Correlation ID of the response message. In this way, the response is correlated to the proper request message.
2.2.2. Implementation Details
Create 3 communication channels:
1. Sender RFC: maintain it as in any other sender RFC scenario;
2. Receiver File:
- in the Parameters tab, maintain the target directory and set the file name scheme as "%mid%" (without quotes), so we can set the filename with the message id through variable substitution. Set the construction mode as create (do not append any info after the message id) and enable variable substitution, with a single entry: name="mid", reference="message:message_id" (also, without quotes).
- in the Module tab, insert the "AF_Modules/RequestOnewayBean" module before the CallSapAdapter module, and set its parameter "passThrough" with value "true"; also, insert the "AF_Modules/WaitResponseBean" module after the CallSapAdapter module.
3. Sender File:
- in the Parameters tab, maintain the source directory and set the file name as "*" (without extension); set the polling interval for a short time, for example, 10 seconds (a long polling time may cause a timeout in the sync RFC); set Processing Mode to Delete and make sure you set the "Set Adapter-Specific Message Attributes" flag, with the File Name flag active;
- in the Module tab, replace the "CallSapAdapter" module with the "AF_Modules/NotifyResponseBean" (since the message doesn't need to be sent to the Integration Engine, but rather to the waiting WaitResponseBean); also, before the NotifyResponseBean, insert the "AF_Modules/DynamicConfigurationBean" module, with the following parameters and respective values: name="key.0" value="write http://sap.com/xi/XI/System/File FileName", name="value.0" value="message.correlationId".
With this configuration, the DynamicConfigurationBean module will get the filename ASMA (which was previously set by the adapter) and write its value in the message.correlationId attribute, before the message is sent to the waiting process (WaitResponseBean) by the NotifyResponseBean module.
After the adapters are done, create necessary sender and receiver agreements, receiver and interface determinations. If you use configuration wizard, remember to create the sender agreement for the Sender file CC manually.
In our scenario, in order to simulate the Legacy system, we used a simple File->File scenario, where the request message was mapped to the response message. In the mapping, we performed a reversion in the string characters, in order to emulate the consumed service. Also, we set File Name ASMA in both sender and receiver simulation communication channels, in order for the message ID which is the file name of the request message to be persisted in the response message.
After the Repository and Directory objects are created and activated, run the RFC (with the proper RFC Destination set in SM59) in order to trigger the scenario. You should then be able to see the response.
One last consideration I'd like to make is about the execution time. In the example below, the overall run time was 14.4 seconds, not that good for a productive interface. But this time is directly influenced by the pooling interval of the legacy system and the pooling interval of the sender file adapter in the sync/async bridge. In our case, both of these intervals were set to 10 seconds. In a productive system, shorter pooling times and a better synchronization could be realized to achieve a better run time for the interface.