I have a POC that I have recently built. The initial driver was building SaaS Connectivity for ServiceNow. Currently there is not an Azure ‘out-of-cloud’ connector for ServiceNow. This gave me the opportunity to get my hands dirty and build my own custom API App where I can expose ServiceNow operations.
Solution Purpose
The purpose of the solution is that you may have an Plant Operations employee that needs to perform an ‘Operator Round’. An Operator Round has a few difference purposes:
- To get equipment meter reads that are not hooked up to the SCADA system
- To perform an inspection on equipment in the plant
Some assets may be managed by a Plant Operations team where as some assets (cyber assets) may be managed by an IT team. When a Cyber Asset requires maintenance, a ticket needs to be created in ServiceNow. But, when we create this incident we want to ensure that we are using the SAP Master data for this asset as SAP is the system of the record for Plant assets. We need to track this information from a regulatory standpoint, but we also want to make sure that the technician performing this work is working on the correct piece of equipment.
Below is a high-level architecture diagram of the solution.
I started to build out a mobile solution that encompassed the Logic Apps and API Apps components as that was the focus of my POC. I quickly realized there was some real benefits in leveraging Azure API Management. In this case, provisioning Azure API Management was ridiculously simple. With my MSDN account in hand I provisioned my own instance. About 15 minutes later I was ready.
Azure API Management Benefits
The drivers for using Azure API Management include:
- Security – Even though this is a POC, I am using real data from an SAP DEV system and wanted an additional layer of security as I am exposing the solution through a Mobile App.
- Performance – Based on the nature of some of my data (Master Data), I knew I could improve the user experience by caching frequent requests. For example if I want to provide a list of Assignment Groups from ServiceNow that a user can select, this list is not going to change very frequently. Why would I hit ServiceNow each time I needed to select an Assignment Group. Let’s cache this data and provide a user with a 20 millisecond experience instead of 2 seconds.
- Analytics – It is always great to see where your app is performing well and not so well. This leads me to my next opportunity.
ServiceNow has a very modern and rich API. I give them a lot of credit, it is one of the best I have seen. Exposing my ServiceNow API operations through API management was straight forward and the caching worked great.
However, when it came to SAP it was a very different experience. SAP uses more of an RPC approach instead of a RESTful approach. The difference being in ServiceNow I will have a Resource (i.e. Assignment Groups). I can then perform actions against that Resource such as GET, POST, PATCH and DELETE. To retrieve Assignment Groups I would perform a GET against this resource. For SAP it is very different, I need to actually send a message payload to the service in order to retrieve data. For example getting a list of Equipment from SAP will look more like a POST than a GET.
You can’t cache POST Requests
By definition a POST request implies you are creating data which is very counter-intuitive to caching a GET Request. The idea behind caching a GET request is that you have static data and you do not want to hit the back end system if there is a very high probability that it has not changed. Since a POST implies you are creating new data, then you shouldn’t be caching it right? Here is where the problem is. I didn’t want to be using a POST to get master data from SAP but that is the way SAP has exposed the interface.
Since my SAP instance is buried deep within a data center the performance was not great. There was a noticeable wait on the mobile app when it came to SAP. I could have replicated this master data in the cloud but that seemed like a lot of synchronization and overhead especially for a POC. What I really wanted to do was to just cache my SAP data on the API Management tier. However, since I was sending POST requests (against my will) this wasn’t possible, or was it?
Update (Edit)
@darrel_miller reached out to me over twitter after posting this article and we chatted about caching rules. It is worth adding to this post that “POST responses may be cacheable, but will only be served to a subsequent GET request. A POST request will never receive a cached response.” He has a great blog post that further describes caching rules here.
Solution
Recently, I watched an #IntegrationMonday presentation from the Azure API Management team. In this presentation, Miao Jiang was talking about an upcoming feature called a Send Request Policy. (Watch the video for more details). It was after watching this video that gave me the idea to expose a GET request to the mobile application and then within the API in Azure Management, convert it to a POST. This way SAP will be continue to be happy, I will be exposing a GET so that I can cache it in API Management and my User Experience improves. A Win-Win-Win on all accounts.
So how did I do this? By simply configuring a few policies in the Azure API Management.
Click on the image for more details but in summary here is what I was able to do:
Inbound Policies
- Enabling Caching
- Set my new Method to POST
- Set a Message Body since this will now be a POST request
- Insert a Query Parameter from Mobile App into payload so it is dynamic
- Set my Auth Header (optional but recommended)
- Use a Rewrite URL since I don’t want to pass a Query Parameter on a POST
Outbound Policies
- Convert my XML response to JSON so that my mobile app can easily digest this response.
Conclusion
I love that I can modify the behavior of my solution through simple configuration. You could have performed some of these capabilities in an ESB or other Middleware but it would have been much more cumbersome. The end result is that I get a much better User Experience with very little tradeoff. The data that I am returning from SAP does not change that frequently, so why would I fetch it all the time if I don’t have to? In this case Azure API Management has really been an agility layer for me.
Also want to take this opportunity to thank Maxim, from Azure API Mgmt team, for the assistance. I started going down the path of the Send Request policy when there was a simpler way of achieving this.