9.1 Writing Functions

Using the CLI

If you are creating your project using the Micronaut CLI, use the create-function command to include the required dependencies and configuration for a serverless function. See the CLI documentation for Creating a Project.

There are a few approaches to building functions depending on the target Function-as-a-Service (FaaS) system.

Functions with Standard In/Out Streams

One common approach and supported by many FaaS systems is to read from standard in and write to standard out to control function input and outputs.

When creating a function with the create-function command Micronaut will setup an application that does exactly this by default. For example the following steps:

  1. $ mn create-function hello-world
  2. $ ./gradlew assemble
  3. $ echo '{"name":"hello"}' | java -jar build/libs/hello-world-0.1-all.jar

Result in the following output being printed to standard out:

  1. {"name":"hello"}

The output is produced by hello-world/src/main/java/hello/world/HelloWorldFunction.java which is a supplier that returns a value of {"name":"hello"}.

Typically in this arrangement to test your function locally you would have the micronaut-http-server-netty and micronaut-function-web dependencies in place as provided scope dependencies. This would allow you to run the function as a local web server and access it via the /hello-world URI.

  1. developmentOnly("io.micronaut:micronaut-http-server-netty")
  1. <dependency>
  2. <groupId>io.micronaut</groupId>
  3. <artifactId>micronaut-http-server-netty</artifactId>
  4. <scope>provided</scope>
  5. </dependency>
  1. developmentOnly("io.micronaut:micronaut-function-web")
  1. <dependency>
  2. <groupId>io.micronaut</groupId>
  3. <artifactId>micronaut-function-web</artifactId>
  4. <scope>provided</scope>
  5. </dependency>

FaaS systems that support the standard in/out approach include OpenFaas, Project.Fn and Riff (amongst others).

Functions by Implementing SDK Interface

Other FaaS systems require that you implement custom interfaces for a particular SDK rather than read from standard in/out. For example to deploy the above function to AWS Lambda you need the micronaut-function-aws dependency in place:

  1. implementation("io.micronaut:micronaut-function-aws")
  1. <dependency>
  2. <groupId>io.micronaut</groupId>
  3. <artifactId>micronaut-function-aws</artifactId>
  4. </dependency>

In this arrangement you would set your Lambda handler to io.micronaut.function.aws.MicronautRequestStreamHandler.

See the Micronaut Request Handlers documentation for an explanation on how this approach works.

When using this approach the FaaS system (in this case AWS Lambda) will directly invoke the MicronautRequestStreamHandler class and pass the input as stream rather than requiring the function to read from standard in.

Lambda Functions Using AWS API Gateway Proxy

Using the CLI

You can create a AWS API Gateway service using mn create-app myapp —features aws-api-gateway

Another approach to FaaS is to build a regular REST application and then deploy the application using tools offered by the FaaS system such as AWS API Gateway.

See the AWS API Proxy Support documentation for an explanation on how this approach works.