LoginSignup
3

More than 5 years have passed since last update.

MicronautでServerless Function

Last updated at Posted at 2019-03-05

Micronaut Severless Function

Micronautには、Serverless Functionを作成するための機能があります。

Serverless Functions

Springなどとの他のフレームワークに比べての利点は、Micronautはコンパイル時に依存関係を解決する仕組みや、メモリのフットプリントの軽さが売りのようです。

作成したFunctionは、AWS LambdaやOpenFaaSなどにデプロイすることができるようです。

Deploying Functions

このMicronautのServerless Functionを作成する機能を、簡単に試してみたいと思います。

環境

環境は、こちらです。

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

プロジェクト作成

--profilefunction-awsとして、プロジェクトを作成します。

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

指定できるfunctionのProfileは、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

単にfunctionとか書いたりすると、「そんなProfileはない」と怒られます。

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

できあがったプロジェクトには、テストコードなども含まれています。

$ 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

スケルトンのfunctionは、こんな感じです。

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";
    }
}

functionを定義する方法は、FunctionBeanとして作成する方法と、Factoryを使って作成する方法があるようです。

FunctionBean

今回は、FunctionBeanを使った方法で実装されているというわけですね。

この場合、関数インターフェースを実装する必要があるようですが、利用できるインターフェースはSupplierConsumerBiConsumerFunctionBiFunctionのようです。

mainメソッドを持ったクラスは、こういう感じで。

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);
    }
}

実行するfunctionは、設定ファイルで指定されています。これは、FunctionBeanの名前ですね。

src/main/resources/application.yml

micronaut:
    function:
        name: hello-function

ドキュメントを見ると、複数のfunctionを含む場合は明示的に設定する必要があるみたいです。

CLIとして実行してみる

パッケージングして実行してみましょう。

Functions as CLI Applications

結果が返ってきました。

$ 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

引数を受け取ったり、他のBeanをDIしたりしてみる

ちょっと構成を変えて、引数を受け取ったり他のBeanをDIしたりしてみましょう。

引数のメッセージを加工するだけの、Beanを作成します。

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);
    }
}

もとのfunctionは、このBeanをDIしつつ、実行時に引数を受け取るようにしてみましょう。関数インターフェースは、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;
        }
    }
}

コードが変わってしまったので、今回はテストをスキップしてパッケージング。

$ ./mvnw package -DskipTests=true

実行。

$ echo '{"message": "こんにちは、世界"}' | 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] ★こんにちは、世界★"}

引数を受け取りつつ、他のBeanをDIして実行できました。

functionをWebアプリケーションとしても実行できるようですが、今回はパスします。

実行環境へのデプロイは、そのうち…。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3