This article is the second in a series on “serverless.” I recommend starting at the beginning of the series, as I introduce concepts incrementally. The links to previous articles are included here for your convenience:
- Introduction
- Feasibility
- …
I am writing this series because I think that serverless is a great complement to well-established technologies. I consider it to be a good step toward decentralization/distribution for any application, especially for long-running (on the order of minutes) or computationally intensive parts. Of course, it comes with pros and cons, but the cons are easier to manage than those of solutions based on fully decentralized architectures like microservices.
I would like to illustrate how to develop an application that relies on a serverless function. For a good example application, I’ll use the Bonita business application platform because I know it pretty well - but more than that, I want to show how much an application platform can benefit from a seamless integration with serverless (and push scalability beyond traditional scenarios).
For the serverless service, I chose AWS Lambda because it has an active community, it can be used by anyone with the free tier, and it comes with a lot of tooling (Maven plugin, Eclipse plugin)…all green to me!
In this article, I’ll show how an AWS Lambda function can be requested from a Bonita application. This can serve to verify the technical feasibility of this kind of integration overall. The Bonita runtime is built in Java, so I’ll use the Java SDK of AWS Lambda. For simplicity, I’ll use the synchronous mode when requesting the AWS Lambda function, as it limits the challenges (no need to handle the callback from AWS Lambda).
Enough talking, let’s do it!
Oops, false start. I also want to let you know that if you want to follow in greater detail, I’ve shared all development resources as a single archive file named “level1-1.0.zip” in the release “level1-1.0” of a dedicated GitHub project.
All good now, let’s do it for real this time!
AWS Lambda
I start with AWS.
Create and configure an AWS account
First I create an AWS account, it is pretty straightforward and takes no time.
I can now sign in to the AWS Console to administrate the AWS services associated with the account.
There is additional configuration to define the default AWS access to use with my local environment.
Create a new IAM user from the AWS Console.
- Name: “bonita”
- Access: “Programmatic access”
- Permissions: “AWSLambdaFullAccess” with no boundaries from existing policies
- Save the generated “Access key ID” and ”Secret access key” values in a safe location
Configure the local environment to link it to the newly created IAM user.
- Create a file named “credentials” in the folder “.aws” of the home directory
- Add access information in this file
[default] aws_access_key_id=A*********A aws_secret_access_key=B*****************B
Develop and deploy the AWS Lambda function
As stated in the documentation, AWS Lambda supports multiple languages. I choose Java for the implementation and Eclipse for the IDE among numerous options.
AWS Lambda functions are based on a handler that is executed at runtime. I implement one that returns the request as the result because it is simple and easy to debug. It looks like this:
public class RequestHandlerExample extends BonitaRequestHandler { @Override public HashMap<String, ?> executeRequest(HashMap<String, ?> request, Context context) { return request; } }
You can find the complete source in the “aws_lambda_example.zip” file of the ”level1-1.0.zip” archive file.
Next, I want to deploy the function on the AWS account. In the case of Java, it is necessary to build a JAR containing the compiled handler class and dependencies. You can find the compiled JAR in the ”level1-1.0.zip” archive file.
Create the function.
- Name: “example”
- Runtime: “Java 8”
- Role: “Create a new role from one or more templates”
- Role name: “serverless”
Deploy the function handler.
- Handler: “org.bonitasoft.serverless.aws.RequestHandlerExample::handleRequest”
- Function package: the JAR
I can launch a test directly from AWS Lambda console and it works just fine!
Bonita
Now that the AWS Lambda function is up and running, it’s time to switch and develop the application that will be using it. I want an application that automatically launches a request to the AWS Lambda function previously deployed, and displays the result to the end user.
Any application built with Bonita follows the MVC pattern.
- Model: structure of the data
- Controller: business logic
- View: responsive UI
If you’d like to know more about this approach, here are the key concepts.
I won’t explain in detail how I develop the application, but you can find all the resources in the “Serverless_Level1-1.0.bos” file of the ”level1-1.0.zip” archive file. This BOS file can be imported in any 7.7.4 or higher version of the Bonita Studio. If you do not have Bonita Studio installed yet, keep reading…
Install Bonita Studio
The Bonita Studio is a must have to develop a Bonita application and is provided with the Bonita platform. It is an IDE based on Eclipse RCP that provides dedicated tools for Bonita development (design, implementation, test).
The Community edition of Bonita is open source and available for download. Complete instructions can be found on the Bonita documentation website.
As of this writing, the latest version is 7.7.4.
Business Data
There are multiple methods for managing of a Bonita development project. Because this one is pretty basic, I’ll start with the definition of the Business Data Model. The only thing I want to persist is the result of the AWS Lambda function request, so I define the relevant Business Object and name it “LambdaResult”.
Business Logic
I’ll spare you the details about Bonita connectors here! The only thing to understand is that a Bonita connector is used by the business logic to interact with an external system. (Bonita comes with several of them by default but it is also possible to develop custom ones and share them across multiple Bonita developments.)
To make sure I can request the AWS Lambda function from the business logic of my application, I develop a custom Bonita connector from the Bonita Studio and name it “AWS Lambda.” Its implementation is pretty basic: I leverage the Java SDK provided by AWS (added in the dependency).
In a Bonita application, the business logic is defined using a process using the BPMN standard. For those who never had the chance to define business processes before: the flowchart-like standard mixes sequences, automatic/human activities, events, data and decision gates.
For this application, I define a business “process” containing a single task.
- Request the AWS Lambda function using the “AWS Lambda” Bonita connector
- Persist the result as a “LambdaResult” Business Object instance
- Provide a UI form that displays the persisted “LambdaResult” Business Object instance
User Interface
The UI of an application built with Bonita is usually made of multiple artifacts wired together. For this application, a simple form associated with the single task is enough. I use the UI Designer that is embedded in the Bonita Studio to develop it. To retrieve the data persisted in the business logic, I can use the REST API which is available by default.
Make it run
The standalone Bonita platform is generally used for qualification and production environments. This combined, with Bonita Continuous Delivery, makes Bonita platform administration and Bonita application build/deployment easy.
But another really nice feature of the Bonita Studio is the embedded Bonita server that can be used for development testing purpose (only). This means I can use it for a test. Also, instead of creating an application descriptor and deploying a full application, I can just start a new instance of the business process and retrieve the result it creates in the Bonita Portal.
As expected, the form in the task displays the result of the AWS Lambda function request.
- Content: the hard-coded content provides the request
- Status code: 200, the request has been executed with success
- Function Error: none, no errors
- Log Result: none, no logs
- Executed Version: $LATEST, it used the latest defined version of the function
On the AWS side, I’ll check the AWS Lambda function logs with AWS CloudWatch to make sure.
And as expected, I can see the logs of the request done by the task of the case I created.
This shows that it is indeed pretty simple to integrate serverless function requests in an application.
The next article of this series will focus on enhancements of this rather basic version, so check for updates!
I would appreciate your feedback in the comments: enhancements, new topics to cover, etc. If you like what you read, let us know and we will spread the word!