きしださんの記事を見て
このときはMicronautを使ってもネイティブ化できなかったみたいだけど、今のバージョンならできるんじゃないかなと思ってやってみたら、できたよ。ちょっとごにょっとしたけど。
バージョンはこんな感じ。GraalVMは1.0.0のRC15:
❯ mn --version | Micronaut Version: 1.1.0 | JVM Version: 1.8.0_202 ❯ sdk current java Using java version 1.0.0-rc-15-grl
コードはここに置いといた。あ、しまった。ネイティブイメージもpushしてしまった。まいっか。
じゃ、やったことを順番に書いておく。
## アプリを生成
postgres-reactive
と graal-native-image
をつけてCLIアプリを生成。
❯ mn create-cli-app micronaut-postgres-reactive \ --features postgres-reactive,graal-native-image
graal-native-image
をつけとくと、ネイティブ化用のライブラリーと設定ファイルがついてくる。
具体的には build.gradle
にこの2つが入ってくるのと
annotationProcessor "io.micronaut:micronaut-graal" ... compileOnly "com.oracle.substratevm:svm"
META-INFの中に
src/main/resources/META-INF/native-image/micronaut.postgres.reactive/micronaut-postgres-reactive-application/native-image.properties
ってファイルが作られてて(長い・・・プロジェクト名を短くすれば良かったな)
内容はこうなってる
Args = -H:IncludeResources=logback.xml|application.yml \ -H:Name=micronaut-postgres-reactive \ -H:Class=micronaut.postgres.reactive.Application
## PostgreSQLコンテナ
こんな感じのDocker ComposeでPostgreSQLを用意した。 docker
ってディレクトリに入れといた。
docker-compose.yml
db: image: postgres:11.2-alpine ports: - "5432:5432" environment: - POSTGRES_PASSWORD=mypass - POSTGRES_DB=mydb volumes: - "./initdb.d:/docker-entrypoint-initdb.d"
initdb.d
の中にはコンテナを初回起動したときに実行されるSQLを入れて:
CREATE TABLE IF NOT EXISTS users ( id SERIAL, first_name VARCHAR(30), last_name VARCHAR(30), CONSTRAINT pk_user PRIMARY KEY (id) ); INSERT INTO users VALUES (1, 'James', 'Carter') ON CONFLICT DO NOTHING; INSERT INTO users VALUES (2, 'Helen', 'Leary') ON CONFLICT DO NOTHING; INSERT INTO users VALUES (3, 'Linda', 'Douglas') ON CONFLICT DO NOTHING; INSERT INTO users VALUES (4, 'Rafael', 'Ortega') ON CONFLICT DO NOTHING; INSERT INTO users VALUES (5, 'Henry', 'Stevens') ON CONFLICT DO NOTHING; INSERT INTO users VALUES (6, 'Sharon', 'Jenkins') ON CONFLICT DO NOTHING;
あとコンテナのPrefixを指定したかったので .env
も置いといた。
COMPOSE_PROJECT_NAME=micronaut-postgres-reactive
ほんで、起動しとく
❯ docker-compose up
## CLIアプリの実装
これはきしださんのそのまま。DBの情報は少し違うけど。
application.yml
postgres: reactive: client: port: 5432 host: localhost database: mydb user: postgres password: mypass # maxSize: 5
インデントが変なのは、Issueあげといた
https://github.com/micronaut-projects/micronaut-profiles/issues/148
MicronautPostgresReactiveCommand.java
@Inject PgPool client; public void data() { client.rxQuery("select * from users") .map(rowSet -> { List<String> result = new ArrayList<>(); PgIterator ite = rowSet.iterator(); while(ite.hasNext()) { Row row = ite.next(); result.add(row.getString("first_name")); } return result; }) .blockingGet() .stream() .forEach(System.out::println); }
で実行すると
❯ ./gradlew assemble ... ❯ java -jar build/libs/micronaut-postgres-reactive-0.1.jar SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. James Helen Linda Rafael Henry Sharon
OKだね。じゃ、ネイティブ化してみよう
❯ native-image --no-server -cp build/libs/micronaut-postgres-reactive-0.1.jar
## ビルド失敗
Netty周りのエラーが出た。 Unsafe
とかのやつ。あれー?なんでだろう?この前見たとき対応入ってたのになー:
と思ってよく見てみたら、Nettyのネイティブ化用設定が入ったライブラリーがないやないか。入れてみるか。
compile "io.micronaut:micronaut-http-server-netty"
そしたらビルド通ったや。うーん。
## んで実行!
しても何も出力されない…あれー。なんでだろう?って見てたら。これか…さっきの native-image.properties
Args = -H:IncludeResources=logback.xml|application.yml \ -H:Name=micronaut-postgres-reactive \ -H:Class=micronaut.postgres.reactive.Application
エントリーポイントが Application
になってるからこれをこう書き換えて:
Args = -H:IncludeResources=logback.xml|application.yml \ -H:Name=micronaut-postgres-reactive \ -H:Class=micronaut.postgres.reactive.MicronautPostgresReactiveCommand
ビルドし直したら動いたー
❯ ./micronaut-postgres-reactive James Helen Linda Rafael Henry Sharon
うーん。なんかちょっとイマイチな感じもあるけど。まぁ、動いたからいっかな。