[JAVA] Serverless Function with Micronaut

Micronaut Severless Function Micronaut has the ability to create Serverless Functions.

Serverless Functions

The advantage over other frameworks such as Spring seems to be that Micronaut has a mechanism to resolve dependencies at compile time and a light memory footprint.

It seems that the created Function can be deployed to AWS Lambda, OpenFaaS, etc.

Deploying Functions

I would like to easily try this function to create a Serverless Function of Micronaut.

environment

The environment is here.

$ mn -V
| Micronaut Version: 1.0.4
| JVM Version: 1.8.0_191

Project creation

Create a project with --profile as function-aws.

$ mn create-app --profile function-aws --build maven hello-function
$ cd hello-function

The Profile of function that can be specified seems to be only function-aws ...

$ mn list-profiles
| Available Profiles
--------------------
  cli           The cli profile
  federation    The federation profile
  function-aws  The function profile for AWS Lambda
  kafka         The Kafka messaging profile
  profile       A profile for creating new Micronaut profiles
  service       The service profile

If you just write function, you will get angry that there is no such profile.

$ mn create-app --profile function --build maven hello-function
| Error Profile [function] is designed only for extension and not direct usage

The resulting project also includes test code and more.

$ find -type f
./mvnw.cmd
./.mvn/jvm.config
./.mvn/wrapper/maven-wrapper.properties
./.mvn/wrapper/MavenWrapperDownloader.java
./.mvn/wrapper/maven-wrapper.jar
./.gitignore
./mvnw
./pom.xml
./micronaut-cli.yml
./src/main/java/hello/function/HelloFunctionFunction.java
./src/main/java/hello/function/Application.java
./src/main/resources/application.yml
./src/main/resources/logback.xml
./src/test/java/hello/function/HelloFunctionFunctionTest.java
./src/test/java/hello/function/HelloFunctionClient.java

The skeleton function looks like this.

src/main/java/hello/function/HelloFunctionFunction.java

package hello.function;

import io.micronaut.function.FunctionBean;
import java.util.function.Supplier;

@FunctionBean("hello-function")
public class HelloFunctionFunction implements Supplier<String> {

    @Override
    public String get() {
        return "hello-function";
    }
}

There seems to be a way to define a function, one is to create it as FunctionBean and the other is to create it using Factory.

FunctionBean

This time, it is implemented by the method using Function Bean.

In this case, it seems that you need to implement a function interface, but the available interfaces are like Supplier, Consumer, BiConsumer, Function, BiFunction.

A class with a main method looks like this.

src/main/java/hello/function/Application.java

package hello.function;

import io.micronaut.runtime.Micronaut;

public class Application {

    public static void main(String[] args) {
        Micronaut.run(Application.class);
    }
}

The function to execute is specified in the configuration file. This is the name of the Function Bean.

src/main/resources/application.yml

micronaut:
    function:
        name: hello-function

Looking at the documentation, it seems that if you have multiple functions, you need to set them explicitly.

Try running it as a CLI

Let's package and run it.

Functions as CLI Applications

The result is returned.

$ java -jar target/hello-function-0.1.jar 
12:56:07.817 [main] INFO  i.m.context.env.DefaultEnvironment - Established active environments: [function]
hello-function

Try accepting arguments or DIing other beans

Let's change the configuration a little and take arguments and DI other beans.

Create a bean that just processes the argument message.

src/main/java/hello/function/MessageService.java

package hello.function;

import java.time.LocalDateTime;
import javax.inject.Singleton;

@Singleton
public class MessageService {
    public String wrap(String message) {
        return String.format("[%s] ★%s★", LocalDateTime.now(), message);
    }
}

Let's make the original function DI this bean and receive arguments at runtime. The function interface implements Function.

src/main/java/hello/function/HelloFunctionFunction.java

package hello.function;

import io.micronaut.function.FunctionBean;

import java.util.function.Function;
import java.util.function.Supplier;
import javax.inject.Inject;

@FunctionBean("hello-function")
public class HelloFunctionFunction implements Function<HelloFunctionFunction.Request, HelloFunctionFunction.Response> {
    @Inject
    MessageService messageService;

    @Override
    public Response apply(Request request) {
        String replyMessage = messageService.wrap(request.getMessage());

        return new Response(replyMessage);
    }

    public static class Request {
        String message;

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }

    public static class Response {
        String message;

        public Response(String message) {
            this.message = message;
        }

        public String getMessage() {
            return message;
        }
    }
}

The code has changed, so this time I skipped the test and packaged it.

$ ./mvnw package -DskipTests=true

Run.

$ echo '{"message": "Hello World"}' | java -jar target/hello-function-0.1.jar 
13:00:23.558 [main] INFO  i.m.context.env.DefaultEnvironment - Established active environments: [function]
{"message":"[2019-03-05T13:00:24.185]★ Hello, world ★"}

I was able to DI and execute other beans while receiving arguments.

It seems that function can also be executed as a web application, but this time it passes.

Deployment to the execution environment will be soon ...

Recommended Posts

Serverless Function with Micronaut
Try DI with Micronaut
Hello World with Micronaut
With Kotorin ―― 7. Scoping Function
Get started with serverless Java with the lightweight framework Micronaut!
Introduced graph function with rails
Java to play with Function
Access Apache Kafka with Micronaut
Login function with Spring Security
Login function implementation with rails
Implement search function with form_with
Implemented authentication function with Spring Security ②
Real-time comment function with Action Cable (2/2)
Write a Reactive server with Micronaut
Implemented authentication function with Spring Security ③
Implemented mail sending function with rails
Fibonacci sequence with (memoization) recursive function
Create pagination function with Rails Kaminari
Implemented authentication function with Spring Security ①
Add Bean Validation with Micronaut (Java)
Real-time comment function with Action Cable (1/2)
Try to implement login function with Spring-Boot
Add pdf file posting function with carrierwave
How to implement TextInputLayout with validation function
Implement paging function with Spring Boot + Thymeleaf
Create an or search function with Ransack.