Skip to Content
Event Information
Author's profile photo DJ Adams

Annotated links: Episode 41 of Hands-on SAP dev with qmacro

This is a searchable description of the content of a live stream recording, specifically “Ep.41 – Business Rules API on the BTP” in the “Hands-on SAP dev with qmacro” series. There are links directly to specific highlights in the video recording. For links to annotations of other episodes, please see the “Catch the replays” section of the series blog post.

This episode was streamed live on Fri 25 Oct 2019 and is approximately one hour in length. The stream recording is available on YouTube.

Brief synopsis: Continuing on from where we left off in Ep.40, we dig further into the Business Rules APIs and start our journey to the Cloud Foundry environment.

02:50 Explaining the path we want to take over the next few live stream episodes, on the way to consuming Business Services on the SAP Cloud Platform (SCP) Cloud Foundry (CF) environment, given that SCP is the Business Technology Platform that helps us extend and build business apps in the cloud, in particular to look at a couple of classic business services, the orchestration pair Workflow and Business Rules.

06:10 Mentioning the excellent openSAP – the goto learning place for SAP technology subjects, and looking specifically at the course “Build Mobile Applications with SAP Cloud Platform Mobile Services” with @Martin Grasshoff and others. That course has just recently come to an end, so it’s now available as a self-paced course (this is my favourite feature of openSAP), and has a rating of 4.49 (out of 5) – recommended! We also looked briefly at a current course “Introduction to SUSE Linux Enterprise Server (SLES)” which appeals to me generally and specifically because my hardware hacker tentacles were vibrating having seen this really interesting blog post on the SAP Community by Kimveasna Pen – “Another DIY for geeks: build your home Data Center and install S/4HANA.

13:40 Briefly noting that you can still submit an article or blog post for me to read out on the Tech Aloud podcast – see this blog post for more details on how to do it and what’s required: “Submit suggestions for Tech Aloud during SAP TechEd 2019”.

14:25 Starting our journey by looking where the destination is – the business services in a trial CF subaccount on SCP. We can see in there that there’s the Business Rules service available, with a “lite” service plan, which is the CF equivalent service to where we’re starting from in Neo.

16:55 Starting up the administrative UI “Manage Rules Project” where we take a look at a simple project I’d already created: “airlinediscounts”. In this UI we explore how a Business Rules project is set up, looking at the project itself and what it contains, i.e. Data Objects, Rules, Rulesets and Rule Services.

In the Data Objects context we have a couple of structures, each with a single attribute. The first structure is used for the data flowing into an invocation call, and the second is to convey the results:

Data Objects
 |
 +-- structure: flightinfo (used for Input)
 |    |
 |    +-- attribute: airline (String)
 |
 +-- structure: discountinfo (used for Result)
      |
      +-- attribute: discount (Number)

These structures (and attributes) are used in the Rule “discountrule” which is rolled up into the Ruleset “discountruleset”, which in turn is made available in the deployable unit, the Rule Service “discountruleservice”. The deployment is done using the runtime (execution) API.

29:40 Looking at the Business Rules API Package on the SAP API Business Hub and we see there are multiple APIs because of the dimensions of: Neo and CF, Authoring and Execution (or designtime and runtime) plus the fact that the Execution API for Neo has gone from v1 to v2 and v1 is still around, albeit deprecated (and still supported until May 2020).

33:40 Taking a closer look at v1 of the Rule Execution API for Neo, and the different categories of API endpoints (Deploy and Undeply Rule Service, Get Rule Services, Invoke Rule Service and XSRF Handling), then diving in specifically to examine the Invoke Rule Service category, which has a single verb/noun combination:

POST /v1/rule-services/java/{projectName}/{ruleserviceName}

Remember this is the deprecated v1 version but it provides us with a good first step to start our journey from, and appreciate the changes in v2. Note also that the “java” part of the path conflicts with the philosophies expressed in Tim Berners-Lee’s classic article “Cool URIs Don’t Change” which you can listen to on Tech Aloud in this episode “Cool URIs Don’t Change” … and one of the changes in v2 is to address this.

Note that the project name is “airlinediscounts” and the rule service name is “discountruleservice”.

37:20 Talking briefly about Cross Site Request Forgery (CSRF) protection via the token mechanism, which is used for this API and many others on the SAP API Business Hub, and noting the subtle reference to validity for “the current session”.

39:10 Trying a fetch request for a CSRF token in the API Hub itself, passing this header in the request:

X-CSRF-Token: Fetch

In the response, a corresponding header is returned:

X-CSRF-Token: 01ECAF[...]

We can (and must) use this token in subsequent POST requests, i.e. requests with side-effects (think “REST”).

41:30 Examining briefly what the payload of a call to the Invoke Rule Service endpoint needs to look like, in v1:

[
  {
    "__type__": "flightinfo",
    "airline": "BA"
  }
]

42:10 Looking at the invokeruleservice script that we’ll be spending our time using for the rest of this episode. Before we go on, here it is in its entirety:

#!/bin/bash

# Invokes the discountruleservice in the airlinediscounts Business Rule project

RULEPROJECTNAME=airlinediscounts
RULESERVICENAME=discountruleservice
AIRLINECODE=$1
USER=i347491
COOKIES=cookiejar-${USER}.dat
HEADERDATA=headers.dat

BPMRULESRUNTIME=https://bpmrulesruntimebpm-${USER}trial.hanatrial.ondemand.com
BPMRULESRUNTIMEPREFIX=/rules-service

ENDPOINT=${BPMRULESRUNTIME}${BPMRULESRUNTIMEPREFIX}

# Abort if no airline code has been specified
[ -z "$AIRLINECODE" ] && echo Specify an airline code \(e.g. BA\) && exit 1

# Retrieve CSRF token
rm -f $HEADERDATA
curl \
        --netrc \
        --header "X-CSRF-Token: Fetch" \
        --cookie-jar $COOKIES \
        --verbose \
        "${ENDPOINT}/v1/rules/xsrf-token" 2> >(grep -v Authorization > $HEADERDATA)

# Capture token
TOKEN=`grep '< X-CSRF-Token' $HEADERDATA | awk '{print $3}'`

# Invoke rule
curl \
        --netrc \
        --request POST \
        --header "X-CSRF-Token: $TOKEN" \
        --header "Content-Type: application/json" \
        --data "[{\"__type__\":\"flightinfo\",\"airline\":\"${AIRLINECODE}\"}]" \
        --cookie $COOKIES \
        --silent \
        "${ENDPOINT}/rest/v1/rule-services/java/${RULEPROJECTNAME}/${RULESERVICENAME}" | jq

46:05 Looking at the first HTTP request we’re about to make, with curl, to retrieve the CSRF token. This includes a brief foray into the .netrc support in curl for a more comfortable way of handling credentials. Here’s the relevant part of my .netrc file:

machine bpmrulesruntimebpm-i347491trial.hanatrial.ondemand.com
login i347491
password SEKRIT!

(that’s not the real password, obviously!)

47:40 Mentioning the use of process substitution in the redirection of STDERR from curl. If you want to learn more about process substitution, see the brief (10 minute!) bonus Ep.39.

49:55 The first invocation of the script, stopping deliberately once a token has been retrieved. What we also get is the cookie jar (which we’ll look at in a moment) and also the headers, captured in headers.dat. Note that outgoing (request) headers are denoted by curl with “>” symbols in the first column, and incoming (response) headers are denoted by curl with “<” symbols. Nice!

53:15 What we get back, as well as the CSRF token, are cookies! The Set-Cookie headers in the response supply cookies that represent the session within which, and only within which, the token is actually valid. So if we make our subsequent POST request with the token, without passing the cookies to contextualise the token, things won’t work (as we see – we try this out and we get a 403 HTTP response).

54:15 We use awk to pull out the token from the response line. For more on awk see this recent post “Shell power and simplicity.

55:10 Now we have the token, we can make the main POST invocation, which we do very quickly before the episode comes to an end (who knows where the time goes?!). We need to make sure that we pass the cookies we received (we do that with the --cookie parameter) as well as the token (in the --header parameter) and of course the actual payload, in the --data parameter:

curl \
        --netrc \
        --request POST \
        --header "X-CSRF-Token: $TOKEN" \
        --header "Content-Type: application/json" \
        --data "[{\"__type__\":\"flightinfo\",\"airline\":\"${AIRLINECODE}\"}]" \
        --cookie $COOKIES \
        --silent \
        "${ENDPOINT}/rest/v1/rule-services/java/${RULEPROJECTNAME}/${RULESERVICENAME}" | jq

If you blur your eyes slightly at the value of that --data parameter, you’ll see it resolves into the payload we saw earlier (with ${AIRLINECODE} representing the value passed in on the command line:

[
  {
    "__type__": "flightinfo",
    "airline": "${AIRLINECODE}"
  }
]

Next time we’ll go through a little bit of this again, a bit slower, to make sure we understand everything properly. Phew!

Assigned Tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      Hi DJ,

      i'm here more for cloud foundry than for business rules but just wanted to comment on the 32min or so of your very informative video chat.

      as far as i can tell Excel365 does come with a JSON parser, which personally i find quite wanting. it basically breaks when the file is not uniform and requires way too many clicks for the JSON file payload to end up as tabulated values in the actual worksheet as Paula here also nicely demonstrates: https://www.youtube.com/watch?v=q6sKs2KLnOo.

      thx for this episode and the whole series.

      cheers, gm

       

      Author's profile photo DJ Adams
      DJ Adams
      Blog Post Author

      Thanks Gregory!