Skip to Content
Technical Articles

Serverless Extensions – Part 4: Set up functions in SAP Cloud Platform Functions and connect to messaging queues

Serverless Extensions
Part 1 – Introduction and Set up messaging queue in SAP Cloud Platform Enterprise Messaging
Part 2 – Configure SAP Cloud Platform Open Connectors to connect to Whatsapp and Twitter.
Part 3 – Set up SAP Cloud Platform Backend service and connect the APIs to SAP Cloud Platform Functions.
Part 4 – Set up functions in SAP Cloud Platform Functions and connect them to the queues and open connectors 
Part 5 – Bring it all together – Testing the extension end to end.

Let us continue by creating two more functions before bringing it all together.

Set up Functions to call tweet using open connectors.

Go to Functions Dashboard. Click Functions -> Create Function.

 

Write a simple node.js handler function to call the open connectors to post the tweet. Use the POST URL and the authorisation string which we noted down when the open connectors was set up for twitter in part 2.

 

const request = require('request');
module.exports = { 
 handler: function (event, context) { 
     var myJSONObject = {"status": event.data };
        var opts = {
            url: 'https://api.openconnectors.ext.hanatrial.ondemand.com/elements/api-v2/statuses',
            method: 'POST',
            body: JSON.stringify(myJSONObject),
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'User xxxxx, Organization xxxx, Element xx'
            }
        };
        request(opts, (err, res, body) => {
            if (err) { return console.log(err); }
            console.log(res.headers);
            console.log(res.body);
        });
  } 
 }

You will notice that this function uses the event data passed and post it to the twitter account. This function will be called from the ‘Master’ function we will be creating in the next step.

Set up the ‘Master’ function.

I call this ‘master’ function as this brings together everything. It performs the following:

  1. Calls the function (created in the previous blog) to connect to the backend API to get the contact numbers of the priority customers.
  2. Connects to the open connectors to send WhatsApp messages to the customer. We will be using the POST URL of the whatApp open connector from part2.
  3. Calls the function (which we created above) to tweet in the company’s twitter account if the customer group is set to “All”.
  4. Gets triggered by the message posted to the queue we created in Enterprise messaging in part 1 of the series.

Go to Functions Dashboard and create the last function we require. Click Functions -> Create Function.

Write a node.js handler function to perform all the functions -1,2 and 3 mentioned above. I have commented the code for easier understanding.

 

 

const request = require('request');

module.exports = {
    handler: function (event, context) {
  //get the contact number of priority customers from the backend
   const result = context.callFunction("connectbackend", { type: "text/plain", data: 'Priority' });
    console.log('contactno '+ result.data);
    //WhatsApp the customers
     var  contactno = result.data;
        var myJSONObject = {
  "Body": event.data.ptext + " " + event.data.pname,
  "From": "whatsapp:+14155238886",
 "To": "whatsapp:"+contactno
};
        var opts = {
            url: 'https://api.openconnectors.ext.hanatrial.ondemand.com/elements/api-v2/messages',
            method: 'POST',
            body: JSON.stringify(myJSONObject),
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'User xxxxx, Organization xxxxxx, Element xxxx'
            }
        };
        
        request(opts, (err, res, body) => {
            if (err) { return console.log(err); }
            console.log(res.headers);
            console.log(res.body);
            //If the customer group is chosen as 'All', then post a status to the company's //twitter account by calling the other function
             if(event.data.cgrp == "All"){
               console.log("all customers..");
               const result = context.callFunction("tweetpromotion", { type: "text/plain", data: event.data.ptext });
             }
        });
        
    }
    
}

Before we can create the triggers to connect the functions with the message queues, we need to  create a trust between Functions and Enterprise Messaging service by creating a “Secret”.

Enter a name for the Secret. Then, you would need to provide a key-value pair. For Key, provide the value as “dial” and for the value, provide the parameters in JSON format as shown below.

 

{
"oa2": {
	"client": "XXX",
	"secret": "XXX",
	"endpoint": "https://com.authentication.eu10.hana.ondemand.com/oauth/token"
	"uri": "wss://enterprise-messaging-messaging-gateway.cfapps.eu10.hana.ondemand.com:443/protocols/amqp10ws"
}

 

The client parameter is the clientid and the secret parameter is the clientsecret.  obtained from the service key of the Enterprise Messaging instance (Refer part 1).

Now that the trust has been established, we can create the Triggers to connect the Enterprise Messaging queues with the functions.

Go to Triggers -> Create Trigger

Enter a Name and choose the type as ‘Event’.

Click ‘Next’. Choose Event Source as ‘Queue’ and enter the queue name which we set up in the enterprise messaging (‘promotions’). Select the function to be called when this trigger is triggered by the event posted in the connected queue. This would be the last master function we created above. Accept the proposed Config Map name. Click Next.

Choose ‘Use existing credentials’ and choose the secret we created above.

Review and click create.

Thats it. We have completed all the configurations required in the cloud platform services. Let me share code snippets from the legacy java application which post the events to the messaging queue.

Legacy application – Post the message to the queue

We perform the following steps.

  1. Get the authorisation token to connect to the messaging service. This uses the client id and secret from the service keys we set up in part 1[This is the same client id/secret we used to create Secret in the Functions service above).
private String getoauthToken() {
		
		String token = "";
//Get the token end point, client id and secret from the service key of Enterprise messaging service
		String tokenEndpoint = "https://aa5c9b38trial.authentication.eu10.hana.ondemand.com/oauth/token?grant_type=client_credentials";
		String client_id = "xxxx";
		String client_secret = "xxx";
		
		HttpClient httpClient = HttpClientBuilder.create().build();
		HttpPost httpPost = new HttpPost(tokenEndpoint);

		String base64Credentials = Base64.getEncoder().encodeToString((client_id + ":" + client_secret).getBytes());
       //1. Prepare the request headers
		httpPost.addHeader("Authorization", "Basic " + base64Credentials);

		
		//2. Post the request	
		HttpResponse response = null;
		try {
			response = httpClient.execute(httpPost);
		} catch (IOException e) {
			e.printStackTrace();
			return "2.." +base64Credentials + "/n" + e.getMessage();
			
		}
        //3. Retrieve the token from the response
		try {
			JSONObject tokenjson = new JSONObject(IOUtils.toString(response.getEntity().getContent(), "UTF-8"));
			token = tokenjson.getString("access_token");
		} catch (IOException e) {
			e.printStackTrace();
			return "3.." + e.getMessage();
		} catch (UnsupportedOperationException e) {
			e.printStackTrace();
			return "4.." + e.getMessage();
		} catch (JSONException e) {
			e.printStackTrace();
			return "5.." + e.getMessage();
		}
		return token;
	}

2. Post the message to the queue using the authorisation token. To build the Post URL, use the “url” parameter from the service key of the enterprise messaging service and suffix it with “/messagingrest/v1/queues/promotions/messages”. Refer the help url

/**
	 * This method is used to call the messaging service
	 * @return
	 */
	private String callService(HttpServletRequest http_request){
		//1. Get the oAuth token
		String token = getoauthToken(); 
		
		//2. Prepare the request headers
		String url = "https://enterprise-messaging-pubsub.cfapps.eu10.hana.ondemand.com/messagingrest/v1/queues/promotions/messages";
		HttpClient httpClient = HttpClientBuilder.create().build();
		HttpPost request = new HttpPost(url);

		request.addHeader("Authorization", "Bearer "+token);
		request.addHeader("Content-Type", "application/json");
		request.addHeader("x-qos", "0");
		
		String pname = http_request.getParameter("pname");
		String pid = http_request.getParameter("pid");
		String range = http_request.getParameter("range");
		String cgrp = http_request.getParameter("cgrp");
		String details = http_request.getParameter("ptext");
		
		//3. Prepare the body of the request
		 String json = "{  "
	        		+ "\"pname\": \"" + pname + "\", "
	        		+ "\"pid\": \"" + pid + "\", "
	        		+ "\"range\": \"" + range + "\", "
	        		+ "\"cgrp\": \"" + cgrp + "\" ,"
	        		+ "\"ptext\": \"" + details + "\" "
	        		+ "}";
        		
		StringEntity input = null;
		try
		{
			input = new StringEntity(json);
		}catch(UnsupportedEncodingException e)
		{
			e.printStackTrace();
			return "3.." + e.getMessage();
		}
		//6. Call the service and get he result
		request.setEntity(input);
		HttpResponse response = null;
		try
		{
			response = httpClient.execute(request);
		}catch(IOException e)
		{
			e.printStackTrace();
			return "4.." + e.getMessage();
		}
	
	
		return "promotion" +pname + "published to "+ cgrp +" Customer group(s)";
		}

As you can see you can pass a number of parameters to the queue, which will then be retrieved in the functions. For example, we read the promotion name from the ‘name’ parameter to send the WhatsApp message and to Tweet.

In the next blog, I will show you how it all fits and work together.

Be the first to leave a comment
You must be Logged on to comment or reply to a post.