Monday, December 21, 2020

#819 Invoking Oracle Functions from OIC


 

Introduction

From the Oracle website -

Oracle Cloud Functions is a serverless platform that lets developers create, run, and scale applications without managing any infrastructure. Functions integrate with Oracle Cloud Infrastructure, platform services and SaaS applications. Because Functions is based on the open source Fn Project, developers can create applications that can be easily ported to other cloud and on-premises environments. Code based on Functions typically runs for short durations, and customers pay only for the resources they use.

These Functions can be written in a variety of languages - Java, Python, Node etc. You write and deploy the code, Oracle takes care of provisioning, scaling etc.

Think of blocks of code that generally do one thing, e.g. applying a discount to an order. These are stored as Docker images in a docker registry. They can be executed via CLI or HTTP request. We will be using the latter in our example.


So how do Functions enhance the OIC experience? 

Here's one use case - Say you are porting SOA Composites to OIC and you make use of Java Embedding in your BPEL process. Where shall I put that code in OIC?

Net, net - Functions can be leveraged to implement business logic that cannot be defined using the standard OIC actions. I realise that we do have the ability to upload Javascript libraries to OIC and then call the functions within, from an OIC process; however, that also has its limitations.

So let's implement a simple example - 

Here is my Java class -







I realise the above is banal, but we can all extrapolate, correct?

Functions: creating an Application

Starting point is access to Oracle Functions










Here I create an application - So what is an application?

Essentially a bucket for your functions e.g. HCM Functions, ERP Functions etc. It is also a unit at which resources can be allocated and configured. These resources can include subnet(s) allocated, whether logging is enabled etc.

.














Functions: creating a Function

I click on Getting Started






















Launch Cloud Shell - 










Note the initial setup cmds - you only need to do this once.

I do a fn list apps command and see my 3 apps, including oic-discount-app.

I now enter a cmd to create a Java function skeleton - fn init --runtime java oicdiscount-java




So what has been generated?





Let's look at the /src directory structure -




Let's look at main -





So here it has generated an example Hello World java








I make a copy of this file, calling it OICDiscountFunction.java

I vi the result -











I can now delete the HelloWorld function -




So now I have my Java code defined, what about the other directory - /test?
















As you can see, a tester class that invokes HelloWorld.
I could get remove the /test directory, but for the moment, let's amend to call our OICDiscountFunction. Same procedure- copy the existing Java file and amend as necessary.













Now I can remove the Hello tester -





Now back up to the top app directory -




I need to amend both these files, as they reference the HelloWorld demo.

func.yaml 

As you can see here, I will need to change the cmd line.








to 







pom.xml

All I need to change here is artifactId












This I change to oicdiscount
I could also add a property here to skip testing - 








Thanks - Angelo Santagata - for pointing this out to me.

Now to deployment - 



















Validate it was successful - 



























I activate logging at Application level -








































Calling Functions from OIC

My colleague Daniel Teixeira wrote a great blog post which helped me out. you can read it here  

Step 1 is to create a REST Connection to OCI Functions -












So what will we need here?
1. base url
2. tenancy ocid
3. user ocid
4. private key
5. fingerprint

3 -5 can be found here -


 
























API Keys can be created/uploaded here - 




















As you can see, the Fingerprint is also available here.

What about the base url?

Check out the Functions screen again - note the Invoke Endpoint url 



take that url up to, but not including /20181201

For Security - we use OCI Signature Version 1

For Tenancy OCID - 























I enter all the required fields - then Save and Test the REST Connection -












I create an App-Driven Orchestration in OIC - 

Rest Trigger - Request -














Response - 

















I drop the OCI Functions REST Connection and configure as follows -

relative resource uri will be set to /2018.../invoke from the Invoke Endpoint.











Naturally I could do this somewhat more elegantly - but this is a simple demo, isn't it?























Request is defined as follows - 



















Use the same definition for the Response.

Now to the Mapping - 












Source is the country from the Request -

Mapping will use the following OIC Advanced Mapping Functions -

oraext:decodeBase64ToReference (
oraext:encodeBase64 (/nssrcmpr:execute/nssrcdfl:request-wrapper/nssrcdfl:country ) )

















Response Mapping - essentially we do the opposite - 

oraext:decodeBase64 (oraext:encodeReferenceToBase64 ($ComputeDiscount/nsmpr0:executeResponse/ns25:streamReference ) )

















Deploy and Test - 


























I can check out the OCI Logs - 














A simple and effective combination - OIC and Oracle Functions.

Happy Christmas 2020 and may 2021 bring you more  Health, Wealth and Happiness.





No comments: