AWS Compute Blog
Writing AWS Lambda Functions in Clojure
Tim Wagner, AWS Lambda General Manager
Bryan Moffatt, AWS Lambda Software Developer
AWS Lambda’s Java support also makes it easy to write Lambda functions in other jvm-based languages. Previously we looked at doing this for Scala; today’ll we’ll see how it can be done with Clojure.
Getting Started with Clojure
We’ll build our Clojure project with Leiningen, but you can use Boot, Maven, or another build tool as well. To follow along below, make sure you’ve first installed leiningen, that lein is on your path (for example):
PATH=%PATH%;C:\Users\timwagne\.lein\bin
and that you have a Java 8 SDK installed.
Next, open a command line prompt where you want to do your development (for example, “C:\tmp\clojure-demo”) and create the following directory structure:
C:\tmp\clojure-demo src java
At the same level as src, create a file named ‘project.clj’ with the following content:
Ok, time to write some code…
Clojure Meets Lambda: Hello World!
Let’s start with the classic: Create a file in your src directory named ‘hello.clj’ with the following content:
Now at the root of your tree, execute
lein uberjar
When this completes, it should have created a subdirectory called ‘target’ containing the file ‘lambda-clj-examples-0.1.0-standalone.jar’, which is ready to be uploaded to AWS Lambda.
You can use a command line or the Lambda console to do the upload/creation. If you’re using the cli, the command will look like the following, but you’ll need to use a valid role argument (this also assumes you’re currently in the clojure-demo directory). If you use the console, the handler is the same as the one in the command below (“hello::handler”).
You can invoke and test from the command line or the console; the console view looks like this if I test it with a sample input of “Tim” (including the quotes):
Fun with Java
With HelloWorld under our belt, let’s tackle Java integration, as a first step on the road toward processing some Amazon S3 events. First, let’s extend our code slightly as follows:
Next, create a subdirectory called “example” in src/java, and in it create a file called “MyEvent.java” with the following content:
Again in ‘C:\tmp\clojure-demo’, execute
lein uberjar
and create a new Lambda function from the command line or console; the cli command looks like
if you test this this function with Lambda test input like
you should get a response like “Hello Tim Wagner”. Now that we have Java integration working, let’s tackle a more real-world example.
Processing an Amazon S3 Event in Clojure
Now we’ll process a more interesting type – a bucket notification sent by Amazon S3 when an object is added. We’ll also see how to make a POJO (in this case the S3 event class) fit more gracefully into Clojure.
The S3 event itself is fairly complex; here’s the sample event from the Lambda console:
We could tackle this just like we handled the name POJO in the previous section. To do that, add
to the list of dependencies in your lein configuration and proceed as we did above for the name POJO.
Alternatively, we can treat this complex type in a more idiomatic way within Clojure. We’ll need to integrate with Lambda’s Java environment using a raw stream handler and then craft a “native” type by parsing the content. To see this in action, let’s create a new file in src called “stream_handler.clj” that contains the following:
Again, build with
lein uberjar
and then upload with a command (or console actions) like
To test this in the Lambda console, configure the sample event template to be “S3 Put” (which is shown above) and invoke it. You should get
as a result.
You can see the “Clojure-ified” form of the S3 event in the logs; here’s what it looks like if you’re testing in the Lambda console:
We hope this article helps developers who love Clojure get started using it in Lambda. Happy Lambda (and Clojure) coding!
-Tim and Bryan
Follow Tim’s Lambda adventures on Twitter