Implementing simple technical XML acknowledgements using a sync-async bridge in SAP PO
An occasional requirement when setting up a new one-way (asynchronous) interface with a new client is that this client wants, after sending a message to SAP PO, to get a simple technical XML acknowledgement back in the HTTP 200 response. This acknowledgement indicates that this particular sent message has been succesfully received by SAP PO.
In this situation, the standard technical HTTP responses with status code of ‘200 OK’ or ‘202 Accepted’ with an empty payload is for the sender client not sufficient to serve as a technical acknowledgment; the sender client also additionally wants a small payload in the response that contains one or few identifiers from the original request message.
The purpose of this blog post is to provide a simple method on how to accomplish this in SAP PO using a simple sync-async bridge setup using a simple example requirement. The idea here is to set up a working example from scratch, which you can then use to build upon for your own requirement.
For more information sync-async bridges, I’d like to refer you to the excellent blog posts that have already been written on this topic, which can be found at the bottom of this post.
Suppose the client sends this XML message to SAP PO:
<MessageFromClient> <ID>ID_FROM_CLIENT_fcb06e30-5b81-11e9-8647-d663bd873d93</ID> <Content>some interesting stuff</Content> </MessageFromClient>
and wants that its HTTP 200 response contains a simple technical acknowledgement XML that also includes the original ID:
<ResponseFromServer> <OriginalID>ID_FROM_CLIENT_fcb06e30-5b81-11e9-8647-d663bd873d93</OriginalID> </ResponseFromServer>
Additionally, we want to send the original message from the client asynchronously to a receiver system.
As mentioned, this can be accomplished by setting up a sync-async bridge.
A possible implementation of the solution would be as follows:
Create required ESR objects
First, we need to create some required ESR objects, which we will need in our iflow later. We need:
- Two External Definitions
- Three Service interfaces
- One message mapping
- One operation mapping
The two external definitions contain the xsd’s of the two xml messages above (you can use an online xsd generator to generate xsd’s based on a sample xml message)
The three Service Interfaces are as follows and use the above xsd’s as its source definitions:
- SIOA_MessageFromClient (set as outbound/asynchronous)
- SIIA_ResponseFromServer (set as inbound/asynchronous)
- SIOA_ResponseFromServer (set as outbound/asynchronous)
Message mapping is:
- MM_MessageFromClient_to_ResponseFromServer (implementation follows below)
Operation mapping is:
- OM_SIOA_MessageFromClient_to_SIIA_ResponseFromServer (assign the message mapping to this operation mapping)
The implementation of the objects above are straightforward. The message mapping maps the value from <ID> in the source message to <OriginalID> to the target message, as shown in the message mapping below.
Create required Integration Directory components
For this purpose, we create the following business components
- BC__TEST__SenderClient. The SenderClient component is our client that sends the message and wants to see the technical acknowledgement. Associate Outbound interface SIOA_MessageFromClient with this component.
- BC__TEST__SyncAckResponder. The SyncAckResponder component handles the acknowledgment response that is synchronously sent back to the sender. Associate interfaces SIIA_ResponseFromServer for receiver and SIOA_ResponseFromServer for sender to this business component.
- BC__TEST__AnyOtherAsyncReceiver .The AnyOtherAsyncReceiver is any other system that wants to receive the message that was sent from the client. We’ll assign an dummy inbound interface to this component later.
We create new communication channels and associate them to the business components as follows:
- BC__TEST__SenderClient | CC_MessageFromClient_BestEffort_SOAP_Sender
- BC__TEST__SyncAckResponder | CC_ResponseFromServer_SOAP_Receiver
- BC__TEST__SyncAckResponder | CC_ResponseFromServer_BestEffort_SOAP_Sender
- BC__TEST__AnyOtherAsyncReceiver | CC_MessageFromClient_SOAP_Receiver
For the BC__TEST__SenderClient | CC_MessageFromClient_BestEffort_SOAP_Sender , use the SOAP Sender channel defaults with Quality of Service parameter “Best Effort”, but set the module chain as follows:
For the BC__TEST__SyncAckResponder | CC_ResponseFromServer_SOAP_Receiver communication channel set the target URL as:
https://<your SAP PO host>:<your SAP PO port>/XISOAPAdapter/MessageServlet?channel=:BC__TEST__SyncAckResponder:CC_ResponseFromServer_BestEffort_SOAP_Sender
Use a valid user so that the call will be succesful. The SOAP Receiver channel makes an internal call to a the SOAP Sender channel.
In the ‘Advanced’ tab, set Variable Transport Binding for XHeaderName1 with name msgid:
Then, in the module chain make sure that XHeaderName1 will be filled in with the correlationId value from the DynamicConfigurationHeader record that was filled in earlier via the DynamicConfigurationBean in the module chain of BC__TEST__SenderClient | CC_MessageFromClient_BestEffort_SOAP_Sender communication channel. We can use DynamicConfigurationBeans for this purpose. More on this principle is found in: https://blogs.sap.com/2009/06/18/unknown-use-case-of-dynamicconfigurationbean-store-file-name-to-jms-header-without-mapping/
For the remainder of the settings, use the defaults.
In the | BC__TEST__SyncAckResponder | CC_ResponseFromServer_BestEffort_SOAP_Sender communication channel, set Quality Of Service as “Best Effort” and set in the advanced tab XHeaderName1:
Finally, add in the module chain the DynamicConfigurationBean and NotifyResponseBean and REMOVE the default sap.com/com.sap.aii.af.soapadapter/XISOAPAdapterBean from the module chain
There is one more object we have to create, and that is a Sender Agreement for this channel. This is needed to pass the standard binding check in SAP PO so that the communication channel can be successfully called. It does not serve any other purpose besides that.
Finally, we have a SOAP receiver channel for any other Async Receiver. The details don’t really matter here; the idea is that the MessageFromClient message can be succesfully sent to an intended async receiver destination.
So now we have the following components in our change list:
Activate the changelist. Now we can start creating our iflow in Netweaver Developer Studio.
Create the iflow
Start with a Recipient List iflow:
Click Next for the Sender System and fill in the Sender System:
Add the two receivers in the other tab:
After clicking finish, we see our flow:
Assign the reference channels we created earlier. There should always be a single choice for a communication channel.
Assign a dummy interface to BC__TEST__AnyOtherAsyncReceiver
Assign the operation mapping OM_SIOA_MessageFromClient_to_SIIA_ResponseFromServer to the branch for BC__TEST_SyncAckResponder:
You now have this iflow. Save, activate and deploy it.
The endpoint from the client sender of this iflow is the SOAP Send channel BC__TEST__SenderClient | CC_MessageFromClient_BestEffort_SOAP_Sender. The URL of this endpoint is:
https://<your SAP PO host>:<your SAP PO port>/XISOAPAdapter/MessageServlet?channel=:BC__TEST__SenderClient:CC_MessageFromClient_BestEffort_SOAP_Sender
Test the iFlow
Let’s call this endpoint with a test client like Postman (used in the screenshot below) or SoapUI to test our iflow. The request is in the top half, the response at the bottom.
In the SAP PO message monitoring overview, we find two entries for the message that the client sent:
The message to BC__TEST__AnyOtherAsyncReceiver is asynchronous, while the message to the SyncAckResponder is behaves synchronously. However, because we have used a sync-async bridge consturction, the response flow from SyncAckResponder to SenderClient will not show up in the message monitoring, because the combined functionality of the RequestOnewayBean,WaitResponseBean and NotifyResponseBean handles the response back to the client, and these beans bypass the standard SAP PO messaging system.