Skip to Content
Technical Articles
Author's profile photo Priyanka Chakraborti

Cloud Integration with SAP Build App (AppGyver)

Introduction:

This blog post shows the steps to create a simple CPI monitoring App using AppGyver.

Final App Preview:

 

Configuration Guide:

High level set up guide for AppGyver:

  1. Use REST API Direct Integration to connect with API endpoint from SAP API Management, which is in turn connected to SAP CPI.

Data%20Tab

Data Tab

Request%20Schema

Request Schema          Response%20SchemaResponse Schema

Sample Request Data   Sample%20Response

Sample Response

** Please note, the data used in the blog post, are fake/test data.

If no record is found for the inputted data, the response will look like below:

          No%20Record

No Record

2. A data variable is created which will store the request data from user’s input.

        Data%20Variable

Data VariableSelect%20Interface

Select Interface from Dropdown Menu        Select%20Status%20from%20Dropdown%20Menu

Select Status from Dropdown Menu          Pick%20Start%20Date

Pick Start Date          Pick%20End%20DatePick End Date

3. In ‘Search’ button component tap event, a few checks are done using IF conditions.

IF condition

After that, ‘Create Record’ is used and the response is stored in App variable.     Component%20Tab%20Event

Component Tap Event

This app variable contains similar structure for success case. ‘Open Page’ will open the ‘Message View’ page.

4. List Item in the ‘Message View’ will be repeated based on the number of occurrence of records in MessageProcessLog. This page also contains a text “No records found for the selected criteria” which will be populated if no record is found.

Message%20View%20List%20Item

Message View List Item

Visible Condition for Text: IS_EMPTY(appVars.MessageProcessingLogs.MessageProcessingLog)

        Text%20for%20no%20record%20found

Text for no record found

5. On component tap event of list item, the current item is stored to another app variable. ‘Open Page’ opens the ‘Detailed View’ page.

Component%20Tap%20event%20of%20List%20Item

Component Tap event of List Item         App%20variable%20for%20storing%20current%20selected%20item

App variable for storing current selected item

6. Container in ‘Detailed View’ page will be repeated based on the number of occurrences of Message.

Detailed%20View

Detailed View

    • Text Content (1st cell) : IF(IS_EMPTY(repeated.current.ApplicationMessageType),”Not defined”, repeated.current.ApplicationMessageType)
    • Text Content (2nd cell) : IF(IS_EMPTY(repeated.current.ApplicationMessageId),”Not defined”, repeated.current.ApplicationMessageId)
    • Text Content (3rd cell): current.MessageGuid

Implementation guide for Cloud Integration:

IFlow

IFlow

 

Step 1:

Configure HTTPS sender channel to get request data from SAP API Management.

Step 2:

Use Router step to check if the method is POST or not.

If it is POST, then proceed, else terminate the message.

Router

Router

Step 3:

Use Groovy script to set filter criteria for ODATA API call.

import com.sap.gateway.ip.core.customdev.util.Message
def Message processData(Message message) {
  def body = message.getBody(String)
  def input = new JsonSlurper().parseText(body)
  def status = input.data.status
  def iflowname = input.data.iflowname
  def startDate = input.data.startDate.take(10) + 'T00:00:00.000'
  def endDate = input.data.endDate.take(10) + 'T00:00:00.000'
  StringBuffer str = new StringBuffer();
  str.append("LogStart ge datetime'" + startDate + "'")
  str.append(" and LogEnd le datetime'" + endDate + "'")
  if (!iflowname.equalsIgnoreCase('all'))
    str.append(" and IntegrationFlowName eq '" + iflowname + "'")
  if (!status.equalsIgnoreCase('all'))
    str.append(" and Status eq '" + status + "'")
  def queryFilter = str.toString()
  message.setProperty("queryFilter", queryFilter)
  return message

Step 4:

Use Request-Reply to call MessageProcessingLogs ODATA API.

ODATA%20Receiver%20Adapter

ODATA Receiver Adapter

Step 5:

Use Filter to remove records related to this iFlow.

Filter

Filter

Step 6:

Use Content Modifier to add root element.

Content%20Modifier

Content Modifier

Step 7:

Use Router to check if any records exist.

Router

Router

Step 8:

Use Groovy Script to modify the structure.

import com.sap.gateway.ip.core.customdev.util.Message
import groovy.xml.MarkupBuilder
import groovy.xml.XmlUtil

def Message processData(Message message) {
  def body = message.getBody(String)
  def input = new XmlSlurper().parseText(body)
  Writer writer = new StringWriter()
  def xmlMarkup = new MarkupBuilder(writer)
  xmlMarkup.MessageProcessingLogs {
        def list = input.MessageProcessingLog.IntegrationFlowName.collect().unique()
        list.each { this_item ->
            def statusList = []
            input.MessageProcessingLog.IntegrationFlowName.each { this_flow ->
                if (this_flow == this_item) {
                    statusList.push(this_flow.parent().Status)
                }
            }
            def groups = statusList.groupBy { it }
            statusList.unique().each { this_status ->
                groups.each { key, value ->
                    if (key == this_status) {
                        MessageProcessingLog {
                            IntegrationFlowName(this_item)
                            Status(this_status)
                            Count(value.size())
                            Messages {
                                input.MessageProcessingLog.IntegrationFlowName.each { this_iflow ->
                                    if (this_iflow == this_item && this_iflow.parent().Status == this_status) {
                                        Message {
                                            MessageGuid(this_iflow.parent().MessageGuid)
                                            ApplicationMessageType(this_iflow.parent().ApplicationMessageType)
                                            ApplicationMessageId(this_iflow.parent().ApplicationMessageId)
                                            LogStart(this_iflow.parent().LogStart)
                                            LogEnd(this_iflow.parent().LogEnd)
                                            CorrelationId(this_iflow.parent().CorrelationId)
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

    }
  message.setBody(XmlUtil.serialize(writer.toString()))
  return message
}

Step 9:

Use Content Modifier to set text body in case no record is found.

Content%20Modifier

Content Modifier

Step 10:

Use XML to JSON converter to convert it to JSON.

[Please note, instead of using Step 10, you can also directly convert to JSON structure using Groovy Script in Step 8 itself]

XML%20to%20JSON%20Converter

XML to JSON Converter

Set up guide for API Management:

Step 1:

Create an API Provider for SCPI.

API%20Provider

API Provider

Step 2:

Create an API based on the SCPI endpoint and assign the route rules in the proxy endpoint as below.

Credentials%20for%20connecting%20runtime%20URL%20of%20CPI

Credentials for connecting runtime URL of CPI

API%20Proxy

API Proxy

Step 3:

Apply API policy to handle CORS.

Assign%20Message%20Policy

Assign Message Policy

<AssignMessage async="false" continueOnError="false"
enabled="true" xmlns='http://www.sap.com/apimgmt'>
<Add>
 <Headers>
<Header name="Access-Control-Allow-Origin">*</Header>
 <Header name="Access-Control-Allow-Headers">setcookie, origin, accept, maxdataserviceversion, x-csrf-token,
apikey, dataserviceversion, accept-language, x-httpmethod,content-type,X-Requested-With</Header>
 <Header name="Access-Control-MaxAge">3628800</Header>
 <Header name="Access-Control-Allow-Methods">GET,
PUT, POST, DELETE</Header>
 <Header name="Access-Control-ExposeHeaders">set-cookie, x-csrf-token, x-http-method</Header>
 </Headers>
 </Add>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<AssignTo createNew="false"
type="response">response</AssignTo>
</AssignMessage>

Step 4:

Apply API policy to verify API key.

 <!--Specify in the APIKey element where to look for the variable containing the api key--> 
<VerifyAPIKey async='true' continueOnError='false' enabled='true' 
xmlns='http://www.sap.com/apimgmt'>
	<APIKey ref='request.header.apikey'/>
</VerifyAPIKey>

Step 5:

Create a conditional flow for pre-flight request.

Conditional%20flow

Conditional flow

Step 6:

Create an API Product and then add the API to it and publish.

Step 7:

Subscribe to the published API product by creating an application in API Business Hub Enterprise. It will generate an API key.

TakeAway Points:

  1. API Management is used for handling CORS.
  2. In Appgyver, app variables exist globally, in the context of the whole app. It can be used to share data between different pages.
  3. In Cloud integration, ODATA API is used for retrieving data related to message processing log.

Reference Links:

  1. Integrate SAP AppGyver with SAP Integration Suite, consuming an Integration Flow levering SAP API Management policies
  2. CORS

Thank you for reading this blog post. Please feel free to share your feedback or thoughts or ask questions in the Q&A tag below.

QA link

Regards,

Priyanka Chakraborti

Assigned Tags

      10 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ranjan Bose
      Ranjan Bose

      Very precise and informative blog.

      Author's profile photo Priyanka Chakraborti
      Priyanka Chakraborti
      Blog Post Author

      Thank you

      Author's profile photo Sunil John
      Sunil John

      Great Content Priyanka. Shows the simplicity and power of SAP solutions and integrations.

      Author's profile photo Priyanka Chakraborti
      Priyanka Chakraborti
      Blog Post Author

      Thank you

      Author's profile photo Syambabu Allu
      Syambabu Allu

      Hi Priyanka,

      Excellent blog..Thanks for sharing!!

      Thank you,

      Syam

      Author's profile photo Priyanka Chakraborti
      Priyanka Chakraborti
      Blog Post Author

      Thanks 🙂

      Author's profile photo Arvik Yune
      Arvik Yune

      Hi Priyanka,

      Thanks for such nice and descriptive blog.

      I am trying to replicate the same and have one doubt regarding the ODATA endpoint for Message Processing Logs. Could you please advise the format of the ODATA address or where can I find it over BTP cockpit ? and do I have to use OAUTH for authentication in ODATA channel ?

      Author's profile photo Priyanka Chakraborti
      Priyanka Chakraborti
      Blog Post Author

      Hi Arvik,

      Address format is https://<hosturl>/api/v1

      While creating, an instance of service 'Process Integration Runtime' with plan as 'api' in BTP sub account, you will get the host url along client id, client secret and token url.

      Yes, OAuth2 client credentials is used for authentication.

      Regards,

      Priyanka

      Author's profile photo Arvik Yune
      Arvik Yune

      I have kept all the parameters accordingly but while selecting the entity getting the error as "Failed to connect to the system"

      Please note that we have not subscribed APIM yet , Is it happening because of that ?

      Author's profile photo Priyanka Chakraborti
      Priyanka Chakraborti
      Blog Post Author

      No, it is not related to APIM. Please use the below troubleshooting steps to debug.

      1. Check if you are able to access API endpoint directly using any API testing tool , for e.g., Postman.
      2. If yes, try using local edmx in the flow and configure the flow. You can download the edmx directly from https://api.sap.com/api/MessageProcessingLogs/overview