Technical Articles
Calling External API In Custom Task UI of Workflow in Cloud Foundry
In this last blog of the series I would help you understand how you can access APIs (cloud or on-premise) from workflow task UI.
In the current scenario, all the companies have hybrid environment with SAP, non-SAP, cloud and on-premise systems and solutions. With the new wave of process orchestration, automation and digitization, companies require integration of SAP, non-SAP systems. There are different interfaces (SOAP, RFC, BAPI, IDOC, REST, OData etc.) that are available to establish communication between SAP and non-SAP systems to exchange data.
In SAP Cloud Platform Workflow, the integration channel with other cloud services or SAP S/4HANA or LoB applications is via APIs. Service task is the BPMN task type to call APIs in Workflow and SAP Cloud Platform Connectivity service is the medium to establish the connection between these systems. If the external service is OData or Rest based, then it can be directly consumed from Workflow using destination. For any other interface, cloud integration service is recommended to be used. (learn more about the service task)
External APIs can also be called from user task UI and it could be little tricky to call these APIs as it is not as simple as filling the configuration properties of the service task. I would now explain you step-by-step how it can be achieved.
Prerequisite:
- You have already created an MTA project with workflow module
- You have already created and designed Fiori Module and configured your workflow user task to this module.
- You have already created a FLP Module with app-router configurations to access workflow applications
Step 1: Create destination
Destination is to be created at sub-account level for connecting to different systems. These systems can be accessed via internet or on-premise. There could be different protocols to access the APIs like Basic Authorization, OAuth, Client Certificate etc. The destination has to be appropriately created based on the supported authentication protocol.
Below as the samples for these different destinations. I have picked 3 examples,
- first one is the northwind with No Authentication,
- then is SuccessFactors destination with Basic Authorization
- Finally, on-premise S/4HANA destination with Basic Authorization.
Note: For on-premise system there need to be a cloud connector setup.
Step 2: Update xs-app.json of Fiori Application
- Create a destination route in xs-app.json
{
"source": "^/NorthWind_Dest/(.*)$",
"target": "/$1",
"destination": "northwind",
"authenticationType": "none"
}
Similarly create any other routes for other destinations.
Step 3: Update mta.yaml of MTA project
As you are trying to access the destination from CF application, you therefore need to add the dependency of destination service and/or connectivity service instance to the app-router from where you are accessing the My Inbox application.
Note: If you are accessing internet based destination then you need only destination service instance dependency. If you are using on-premise based destination then you also have to use connectivity service instance together with destination service.
For this first add the service instance details in the resources section
Then add the dependency of the destination and/or connectivity service instance in the app-router.
Caution: if you miss this step then the Component.js of your user task UI wont load and you will get 500 – Internal Server Error as the app-router will try and look for the destination.
cdm.js:66 2020-09-07 23:55:46.422770 Cannot create componentsap.demo.bpm.taskui for smart template rendering. Showing standard task in the detail screen as a fallback: failed to load ‘sap/demo/bpm/taskui/Component.js’ from /sapdemobpmtaskui/Component.js: 500 – Internal Server Error
Step 4: Code Fiori Application to call External API
In the final step, you now have to code your Fiori application to call the needed service. In this example I have coded jQuery.ajax method to call Http URL endpoint for Northwind.
Note the URL. It has application ID followed by the route name and then the relative URL
/<applicationID>/<route-name>/<relative-URL>
For Example: I wanted to call this URL in my custom task UI: https://services.odata.org/V3/Northwind/Northwind.svc/Suppliers?$format=json
- This would be broken up as follows:
- The destination northwind (in cockpit), will have the url as https://services.odata.org
- Routes in xs-app.json of the Fiori application will have a route of name Northwind_Dest pointing to above northwind destination created in the cockpit
- In the AJAX call, the URL will be formed as “/sapdemobpmtaskui/Northwind_Dest/V3/Northwind/Northwind.svc/Suppliers?$format=json
- where sapdemobpmtaskui is theapplication ID and Northwind_Dest is the source name of the destination route given in xs-app.json
- Use manifest.json to sap.app –> id to get the application ID
<<<<< NEW >>>>>>
If you are using SAP Managed app-router based application then your prefix will be as follows.
/<app-modulepath>/<route-name>/<relative-URL>
For Example: /workflow-sample.sapdemobpmtaskui-1.0.0/Northwind_dest/Northwind.svc/Suppliers
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- In my example, I adjusted the view.xml as well to bind the data from the service call to the UI5 control
After you build and deploy the MTA, open the task in the My Inbox and click on the country drop down, you will see the countries getting loaded. (ignore the duplicate country names).
This is how you code your workflow custom task UI application to work with any external API call for any GET, POST, PATCH etc. methods. The same will be applicable with SFSF or any Lob Application APIs or any backend on-premise APIs.
- For easy learning purpose, I have uploaded the code used in this blog as example in GitHub.
- Download the content from resources folder, import into SBAS, build and deploy.
Related Resources
- starting workflow from custom task UI
- how to add start workflow custom UI as a tile in Portal Fiori Launchpad,
- how to use custom task UI as user task in your workflow
Great blog series Archana!
I would also like to see in such blog the information about how to get csrf token for POST calls - especially for on premise calls.
Hello Vladimir,
This blog is about calling external API from custom task UI and not from workflow service task. To answer you question:
My fault - I didnt realized that I`m speaking about service task and you about UI task.
I just searched info about that topic recently, so it came to my mind.
Btw - thank you for the answer anyway.
Hi Archana.
It's necessary create a destination in cloud foundry if I want to call bpmworkflowruntime? Because when I execute my function to start my workflow I get the error 404.
Thanks in advance.
No, bpmworkflowruuntime does not need a destination. You may want to refer another blog of mine which explains how to start the workflow from custom application
https://blogs.sap.com/2020/08/27/starting-workflow-from-custom-fiori-application-in-cloud-foundry/
Thank you so much Archana.
My error was my ID app in URL, I ignored the capital words and finally is working =).
Hi there!
I followed all the instructions in this post, but I always get an error when running the application:
"Route references unknown destination "
I am trying to call a CPI (Integrator) endpoint which gets data from an SAP system.
Could you help me out please?
Thanks in advance!
Have a great day,
Jozsef
It's difficult to suggest anything with this limited information. Can you post the route & destination snapshot that you are creating.
We created the destination in the Cloud Platform (in a subaccount), and then we are trying to call that destination in our sap business application studio. This destination have a few properties: WebideEnabled - true, Html5.dynamicDestination - true.
Our xs-app.json:
Hello Jozsef,
The explanation is simple. Your UI5 application is routed via app-router. There will be two xs-app.json (a) one inside the UI5 application and (b) one in app-router. If you are using destination inside your UI5 application, then (a) you have add the route inside the xs-app.json of your application and (b) the authentication method has to be "route" and not "none" (as in your case).
Regards,
Archana
We solved it, the problem was that we had to include the namespace ("ns") when calling a destination.
So for example, insted of GET("/dest"), we had to write GET("/ns/dest").
Have a great day!
Hi Archana,
eventhough I have added the connectivity dependency, the route for the cc destination in xs-app.json causes the problem that you have described:
Cannot create componentcom.qperior.workflowsample.uifor smart template rendering. Showing standard task in the detail screen as a fallback: failed to load 'com/qperior/workflowsample/ui/Component.js' from /comqperiorworkflowsampleui/Component.js: 500 - Internal Server Error -
What can be the cause? The destination works fine in a different MTA project with portal and ui modules. Can I see the 500 error with more detail somewhere? I have tried to run cf logs on approuter and ui-deployer it didn't brought anything up.
Thanks and Regards,
Koray
Hi Archana,
I could solve my problem. The thing is I have two approuters, actually two MTAs. One for standard workflow tiles (inbox, definitions, manage instances) and one for the specific application. For task UIs I had to bind conn/dest to the approuter, which belonged to the workflow tiles project. Thanks again for the CF workflow blogs.
Regards,
Koray
Hi Archana,
I try to consume this Odata service which is running on the cloud multi-environement as API as you see below.
https://xxxxxxxxxx.cfapps.eu10.hana.ondemand.com/api/outbound/odata/v1/com.emea.gtt.app.gttft1.gttft1Service
I can call this service on the browser with technical user and password. Also I developed an application in NEO environment by defining destination , and it is also running there without any problem.
But when i try to call this service Cloud Foundry by defining the destination with basic auth method, I always receive 401 error. Even if I deploy the application in the same Multi-Enviroment.
I guess, my configuration is also correct if you check it below.
Where am I doing wrong? Is it possible having a restriction on this cloud service? If yes, why I am not allowed to use it in the same environment?
Thanks in advance.