Hello and welcome back to your ABAP Cloud with Microsoft integration journey. Part 0 of this series got you covered with the prerequisites to get your SAP dev environment with
ABAP Development Tools (ADT) on Eclipse up and running.
#Kudos to
karl.kessler,
harish.bokkasam1,
andre.fischer and team for the nudges in the right directions when it comes to ABAP Cloud 🤟
Today we approve
a travel booking request issued to SAP
from Microsoft Teams. The orchestration happens through the ABAP cloud compliant RAP enabled business object. Wow, that was a mouthful 🤯but no worries, there will be screenshots and more mumbo-jumbo to help you along. See below the architecture for the flow.
🛈 To ensure the usage of the ABAP environment in “on-premises” or private edition scenarios, simply verify the ABAP language version setting on ADT is set to “ABAP for Cloud Development”. Find the option on the Properties pane under General. Public edition or BTP ABAP environment in any flavor default to ABAP Cloud automatically. |
Generate the complete ABAP object tree on ADT
For this sample I ran through the SAP developer tutorial “
How to Create RAP Business Events in an On-Premise system” till step 7 (skipping 5 and 6), which creates a Travel Booking app. It was the simplest one regarding the integration without any additional “shi-shi”.
Pay special attention to:
- Step 2 subsection 4: The program supplied by the tutorial relies on an existing table with demo data. In case that doesn't exist in your system you can skip step 2 and easily create your own values from the Fiori preview screen once you have generated them in step 3.
- Step 1 subsection 4: My S/4 HANA 2022 didn’t contain the SAP demo namespace “/dmo/” referenced by the tutorial. Replace them with internal types (e.g. abap.numc(6) instead of /DMO/travel_id) to continue (have a look at my modified version of it here). Alternatively, you may consider loading the “/dmo/” objects via abapGit as SAP described here and here. See this community post for reference.
- Skip step 5-6
- Step 7 subsection 3: Use my implementation of the “lcl_event_handler” class instead
The last step of the tutorial introduces the custom behavior for the “Save” action. We are using it to send the approval request to Microsoft Teams to change the Travel Request state.
UPDATE:
Double check the "strict" setting of your Core Data Service behavior definition. See below sample for reference (line 2). The RAP generators default now to strict (2) instead of 1 as before:
managed with additional save implementation in class ZEVENT_BP_BOOKINGTP_100 unique;
strict ( 1 );
with draft;
define behavior for ZEVENT_R_BOOKINGTP_100 alias BOOKING
...
Strict (1) allows plain http calls on the ABAP Cloud classes as described in this post. Strict (2) demands additional background processing to meet the "guarded" RAP BO lifecylce handling requirments on save operations. See
this SAP docs entry for details. SAP recommends strict (2).
🛈 In case you are curious to go down the RAP built-in eventing route, described by the remaining parts of the tutorial, have a look at this blog post. In there, I describe the various options available. Among them is also native SAP Event Mesh integration with Azure Event Grid. |
A deep dive into the integration options with Microsoft services for this scenario
There are multiple options to interact with Microsoft services like Microsoft Teams. Any compute that can perform the authentication flow and http request achieves the technical goal (check the security section at the end for more insights)
See below a list of integration options that I typically discuss with our joint SAP + Microsoft customers:
Since
Azure Logic Apps (serverless low code workflow engine in AIS) has a drag & drop experience with a couple of clicks to send an
adaptive card to Teams I chose that path. See projects like SAP’s
bridge framework to generate mentioned cards with SAP means in case you go down that route instead.
So, on to Azure…
For starters,
deploy the provided Azure Logic App to your Azure Subscription using the “Deploy to” button on GitHub or this
link from here. Once finished, navigate to the app, and authorize your Teams connection.
Open the Logic App and retrieve the generated endpoint URL from the http trigger. It contains an access signature. That is the simplest way to get started.
🛈 For production readiness, see the next section for more details on how to secure and isolate the integration workload using private virtual network integration, Azure AD backed OAuth2 flows, and OIDC etc. |
Secret hint: Fix Logic Apps Designer UI glitches ad-hoc by navigating to Code View saving from there.
Copy the URL and add to your ABAP code in line 8.
CLASS lcl_event_handler IMPLEMENTATION.
***** Make your changes below
METHOD save_modified.
***** Act on booking create action. Use update, delete, etc. for alternate behavior.
IF create IS NOT INITIAL.
***** get destination for http client by com arrangement in steampunk
"DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement(
" comm_scenario = 'Your Comm Scenario'
" service_id = 'Your Generated Service ID'
***** Setup http request to Azure Logic Apps directly when not using comm arrangement above.
DATA(dest) = cl_http_destination_provider=>create_by_url(
'https://prod-78.eastus.logic.azure.com:443/workflows/your-id/triggers/manual/paths/invoke?api-version=2016-10-01&sp=your-access-signature' ).
DATA(client) = cl_web_http_client_manager=>create_by_http_destination( dest ).
DATA(req) = client->get_http_request( ).
***** Create JSON payload from booking item properties
DATA(lv_json) = /ui2/cl_json=>serialize( create-booking ).
req->set_text( lv_json ).
req->set_header_field( i_name = 'Content-Type' i_value = 'application/json; charset=UTF-8' ).
***** POST message to Azure Logic Apps
DATA(create_response) = client->execute( if_web_http_client=>post )->get_text( ).
client->close( ).
ENDIF.
ENDMETHOD.
ENDCLASS.
🚨Warning:
the class cl_http_destination_provider doesn't exist in S/4HANA Cloud ABAP environment private edition. To implement with embedded steampunk use the wrapper-concept with system-internal release (C1) for use in Cloud Development as described by SAP here.
Updating above abap snippet with next post. |
I like
lars.hvam's approach to describe the implementation differences using
Venn diagrams.
Moving on...
In my sample using the
/ui2/cl_json class to generate the JSON payload for the POST request from the booking business object structure. Kudos to
s7oev and his
blog post describing an ABAP Cloud option for REST calls.
With that we are ready for an integration test
😎
Debugging with Fiori Preview and ADT
Put a break point on the
save_modified method and open the Fiori preview of your Booking app.
Everything working as expected? Great, I had no doubts
🤞. Release your breakpoint and head over to your Azure Logic App to inspect the run.
Note the successful workflow steps generating the adaptive card with the details from your Fiori booking app including the buttons to approve/reject the request. Hit approve for the fun of it because the description field reads “much needed vacation”.
Using the OData service generated for the RAP enabled business object, we can send an efficient PATCH request and adjust its status from Open (“O”) to Approved (“A).
See tutorial step 3 “Generating the transactional UI services” for reference on the OData v4 service generation.
And that’s it. Only thing left to do, is marveling at the beauty of the approved booking request 🤩
Fully isolated Azure environments
Done marveling? Ok, then let’s get serious again and see what is needed to uplevel this integration scenario into production readiness. Fixed access signatures are nice and simple but not going to cut it
😉also I know many of you love their private networks. Here you go
👇
All involved components can be isolated in a private virtual network. In addition to that they can be restricted to accept requests only from your own internal Azure services or IP ranges. Furthermore, OAuth2 or OIDC flows may be employed for secure authentication. For the callback to the SAP RAP enabled OData service X509 certificates or the OAuth2SAMLBearer flow are desirable for production. See this
blog post and this
Azure APIM policy to learn more about the setup process.
Stay tuned for part 2 of the steampunk series for insights into the X509 setup for BTP ABAP environment.
🛈 Comment on the side: you may implement above architecture in a similar fashion using SAP API Management, SAP Cloud Integration or SAP Build Process Automation. However, be aware that they have no private network injection capabilities. They are Internet-facing by design like Microsoft Teams or M365. And rightfully so, if you ask me - focus on app layer security rather than network.
Still many corporations like their private networks, hence my architecture reference above with private virtual networks on Azure.
Use the SAP Cloud Connector or SAP Private Link for Azure to reach your S/4HANA Cloud private edition from SAP BTP. See my blog series for a deep dive and more scenarios with Private Link. |
What if I want pure ABAP without any integration services as negotiators?
Instead of using the Azure Integration Services you can make the call to Teams from ABAP without any intermediary if you wish. Get inspired from the code
here to infuse your existing code. The ABAP classes speed up the integration with Microsoft Graph and Azure managed identities for instance.
However, compared to the “pure ABAP” way, using a workflow engine brings separation of concerns and the added value of managed connectors for the integration. In addition to that, the different developer personas (ABAP and Azure), that need to collaborate, also profit from this split as they can focus on their domain.
See the Microsoft Teams resources of the Microsoft Graph API. See the docs
here and the online Graph explorer
here.
The
ABAP SDK for Azure requires
abapGit to import the objects into your landscape.
For event-driven approaches using ABAP, see this
blog post.
Final Words
That’s a wrap
🌯you saw today how you can enhance the SAP RAP logic from the S/4HANA Cloud ABAP environment (public or private doesn’t matter) to surface an SAP approval process directly in Microsoft Teams. We used adaptive cards exposing buttons to kick off the approval process. To conclude we shed some light on how to secure the scenario properly.
Find all the resources to replicate this setup on
this GitHub repos. Stay tuned for the remaining parts of the steampunk series with Microsoft Integration Scenarios from my
overview post.
Cheers
Martin