AWS Lambda
BoxLang Runtime for AWS Lambda! Serverless for the win!
Last updated
Was this helpful?
BoxLang Runtime for AWS Lambda! Serverless for the win!
Last updated
Was this helpful?
AWS Lambda is a serverless computing service provided by Amazon Web Services (AWS) that lets you run code without provisioning or managing servers. It automatically scales applications by running code in response to events and allocates compute resources as needed, allowing developers to focus on writing code rather than managing infrastructure (https://docs.aws.amazon.com/lambda/).
The BoxLang AWS Runtime allows you to code in BoxLang and create Lambda function in this ecosystem. We provide you a nice template so you can work with serverless: https://github.com/ortus-boxlang/bx-aws-lambda-template. This template will give you a turnkey application with features like:
Unit and Integration Testing
Java dependency management
BoxLang depenency management
Automatic shading and packaging
GitHub actions to: test, build and release automatically to AWS
Our BoxLang AWS Handler acts as a front controller to all incoming Lambda executions. It provides you with:
Automatic request management to an event
structure
Automatic logging and tracing
Execution of your Lambda classes by convention
Automatic error management
Automatic response management and serialization
The BoxLang AWS runtime provides a pre-built Java handler for lambda already configured to accept JSON in as a BoxLang Struct and then output either by returning a simple or complex object or using our response
convention struct. Our runtime will automatically convert your results to JSON.
The default handler you configure your lambda with is:
You can see the code for the handler here: https://github.com/ortus-boxlang/boxlang-aws-lambda/blob/development/src/main/java/ortus/boxlang/runtime/aws/LambdaRunner.java#L161
The handler will look for a Lambda.bx
in your package and execute the run()
method by convention.
The following are all the environment variables the Lambda runtime can read and detect. If they are set by you or the AWS Lambda runner, then it will use those values to alter operations. This doesn't mean that they will exist at runtime, it just means you can set them to alter behavior.
BOXLANG_LAMBDA_CLASS
Absolute path to the lambda to execute. The default path is:
Which is your lambda deployed within your zip file.
BOXLANG_LAMBDA_DEBUGMODE
Turn runtime debug mode or not.
BOXLANG_LAMBDA_CONFIG
Absolute path to a custom boxlang.json
configuration for the runtime.
You can also leverage ANY env variable to configure the BoxLang runtime using our runtime environment conventions.
The BoxLang default template for AWS lambda can be found here: https://github.com/ortus-boxlang/bx-aws-lambda-template. The structure of the project is the following
The BoxLang AWS Lambda runtime will look for a Lambda.bx
in your package by convention and execute the run()
method for you.
The Lambda function is a BoxLang class with a single function called run()
.
It accepts three arguments:
event
Struct
All the incoming JSON as a BoxLang struct
context
com.amazonaws.services.lambda.runtime.Context
response
Struct
A BoxLang struct convention for a response.
You can find more information about the AWS Context object here: https://docs.aws.amazon.com/lambda/latest/dg/java-context.html
The event
structure is a snapshot of the input to your lambda. We deserialize the incoming JSON for you and give you a nice struct.
This is an Amazon Java class that provides extensive information about the request. For more information, check out the API in the Amazon Docs (https://docs.aws.amazon.com/lambda/latest/dg/java-context.html)
getRemainingTimeInMillis()
– Returns the number of milliseconds left before the execution times out.
getFunctionName()
– Returns the name of the Lambda function.
getFunctionVersion()
– Returns the version of the function.
getInvokedFunctionArn()
– Returns the Amazon Resource Name (ARN) that's used to invoke the function. Indicates if the invoker specified a version number or alias.
getMemoryLimitInMB()
– Returns the amount of memory that's allocated for the function.
getAwsRequestId()
– Returns the identifier of the invocation request.
getLogGroupName()
– Returns the log group for the function.
getLogStreamName()
– Returns the log stream for the function instance.
getIdentity()
– (mobile apps) Returns information about the Amazon Cognito identity that authorized the request.
getClientContext()
– (mobile apps) Returns the client context that's provided to Lambda by the client application.
getLogger()
– Returns the logger object for the function.
The response
argument is our convention to help you build a nice return structure. However, it is completely optional. You can easily return a simple or complex object from your lambda, and we will convert it to JSON.
Now you can go ahead and build your function. You can use TestBox to unit test your Lambda.bx
or we even include a src/test
folder in Java, that simulates the full life-cycle of the runtime. Just run gradle test
or use VSCode BoxLang IDE to run the tests. Now we go to production!
The runtime also allows you to create other functions inside of your Lambda that can be targeted if your AWS Lambda is exposed as an URL, which we recommend. You will be able to target different functions in your Lambda.bx
by using the following header when executing your lambda:
This makes it incredibly flexible where you can respond to that incoming header in a different function than the one by convention.
You can deploy your lambda by manually uploading the build package or using our GitHub Action in your template. Below is the action that does an automatic update.
Please note that you MUST create the lambda function in the AWS console FIRST for this to work. This does not create; it only updates.
Our automated approach will require storing your credentials in your repository's secrets.
AWS_REGION
- The region to deploy to
AWS_PUBLISHER_KEY_ID
- The AWS access key
AWS_SECRET_PUBLISHER_KEY
- The AWS secret key
When creating the lambdas, make sure you create two lambdas:
{projectName}-staging
- A staging lambda based on the development
branch
{projectName}-production
- A production lambda based on the main
branch
Please also note that our build process allows you to have a development
branch and a master/main
production branch. This will enable you to have a deployment of a staging
and a production
tier function in the lambdas console in AWS.
The {projectName}
comes from the settings.gradle
file in your root project.
Log in to the Lambda Console and click on Create function
button.
Now let's add the basic information about our deployment:
Add a function name: {projectName}-staging or production
Choose Java 21
as your runtime
Choose x86_64
as your architecture
TIP: If you choose ARM processors, you can save some money.
Now, let's upload our test code. You can choose a zip/jar or s3 location. We will do a simple zip from our template:
Now important, let's choose the AWS Lambda Runtime Handler in the Edit runtime settings
And make sure you use the following handler address: ortus.boxlang.runtime.aws.LambdaRunner::handleRequest
This is inside the runtime to execute our Lambda.bx
function.
Please note that the RAM you chose for your lambda determines your CPU as well. So make sure you increase the RAM accordingly. We have seen great results with 4GB+.
Now click on the Test
tab and an event name MyTestEvent
. You can also add anything you like in the Event JSON
to test the input of your lambda. Then click on Test
and watch it do its magic. Now go have some good fun!
The AWS Runtime source code can be found here: https://github.com/ortus-boxlang/boxlang-aws-lambda
We welcome any pull requests, testing, docs, etc.
The AWS context object. You can find much