During the course of my day-to-day PI developments, I frequently encounter scenarios in which I need to create an async-to-sync bridge in order to connect to some 3rd-party Web service. Here, for example, I might receive an asynchronous IDoc on one hand, and need to turn around and call a synchronous Web service on the other hand. Generally speaking, there are two ways of building this bridge using PI:
- You can interject an integration process to broker the synchronous call and deal with the results.
- You can use the JMS adapter module-based bridge described here.
While both of these scenarios are viable options, they are not without their drawbacks. For a simple point-to-point call, the interjection of an integration process adds a lot of unneeded overhead. The JMS adapter module solution performs much more favorably, but can be difficult to work with if messages need to be delivered reliably (and perhaps in order). To get around these limitations, I bent the rules a little bit and devised a custom adapter module that allows you to configure the synchronous Web service call using asynchronous message processing semantics. Sufficiently confused? Don’t worry, this blog entry describes the architecture of this solution.
If you’ve worked with the SAP standard async-to-sync bridge, then you know that it interjects a couple of adapter modules into a JMS sender channel definition in order to implement a synchronous call behind-the-scenes and then forward the result on asynchronously to some final destination (e.g. a JMS queue, IDoc, etc.).
The archtiecture of my solution is similar, but it deviates in the way it executes the synchronous call. With SAP’s solution, the synchronous call is brokered through the Integration Server. The advantage of this approach is that it allows you to leverage any adapter type when performing the synchronous call. The downside is that you must process the message using a QOS of “Best Effort”. In my solution, I have tailored the adapter module to facilitate the Web service call internally and then replace the request message payload with the results message payload. Thus, from a configuration perspective, you’re essentially configuring an asynchronous scenario that forwards the results of the Web service call to some receiver interface.
To demonstrate how this works, imagine that you are receiving an ORDERS05 IDoc message out of some source SAP ECC system and forwarding it on to some downstream 3rd-party system using SOAP Web services. You then want to take the results of this Web service call and forward the message back to the source SAP ECC system. The configuration steps are as follows:
- You configure an asynchronous scenario which takes receipt of the IDoc message, converts it into a SOAP request message (minus the SOAP envelope), and then places the result on a JMS queue.
- Then, you configure a JMS sender channel using the custom adapter module to pick up the request message, forward it on to the 3rd-party system, and then swap the payload such that the results of the Web service call are forwarded on to the Integration Server.
- From there, you have a normal asynchronous scenario in which you are sending the response message asynchronously back to the source SAP ECC system.
As you can see, PI really doesn’t know much about the synchronous call. To the Integration Server, it’s business as usual. Of course, the adapter module is smart enough to react to communication failures and SOAP faults. If this occurs, an exception is raised and the message gets rolled back. That way, messages can be delivered with a QOS of “Exactly Once” or “Exactly Once In Order”.
Implementing the Adapter Module
You can find the complete source code for the custom adapter module here. For step-by-step instructions for building the EAR file and deploying it, I highly recommend William Li’s article on the SDN entitled Developing Adapter User-Module to Encrypt XML Elements in Process Integration 7.1. As you can see, the code itself utilizes the Java standard SAAJ API as well as the JDOM and Commons Codec libraries. Beyond that, the code should seem fairly straightforward. In essence, it’s job is to:
- Extract the values of relevant configuration parameters which determine the target URL to call, the SOAP action of the target operation, and basic authentication tokens (if needed).
- Extract the request message payload, build a SOAP envelope, and call the target Web service operation.
- Validate the results and raise an exception to rollback the message as necessary.
- And finally, if the request was succesful, overlay the request message with the response message.
Naturally, you can tweak this behavior for any custom message processing requirements that you might have.
Configuration in the Integration Directory
Once the adapter module is deployed, you can configure it by selecting the Module tab in your JMS sender channel. The figure below demonstrates how this works. The Module Name field must contain the JNDI name assigned to the adapter module when it is deployed. Other than that, the configuration is very straightforward.
I hope that you’ll find this utility module useful for those scenarios that just don’t quite fit in with the default SAP behavior. Also, if you like what you see above, allow me to offer a shameless plug for my new book SAP NetWeaver Process Integration: A Developer’s Guide.