QUARKUSを早速試してみた

## QUARKUSとは何者か？
実行VMにGraalVMをおいた新しいJavaのフレームワークです。
Red Hatが開発元です。

>The goal of Quarkus is to make Java a leading platform in Kubernetes and serverless environments while offering developers a unified reactive and imperative programming model to optimally address a wider range of distributed application architectures.

>Quarkusのゴールは、Kubernetesやサーバレスなどの環境において、分散環境の幅広いアプリケーションアーキテクチャに適合するため、デベロッパーに対してリアクティブとインペラティブなプログラミングモデルを統合して提供することで、Javaを先進的なプラットフォームにすることだ。

と公式ブログにあるようにSpringやPlayがやや遅れているサーバーレスなどの実行環境に対応したようです。

また、従来通りのインペラティブなモデルでの書き方と
リアクティブな書き方の両方に対応しているのも大きな魅力の一つでしょう。

RxJavaを使うことによってより柔軟でレイテンシを感じにくいアプリケーションの挙動が実現できるようになるはずです。

既存のライブラリにも柔軟に対応しているのでサクッと何かを作るには十分すぎるのではないでしょうか？

Hibernate ORMをデフォルト仕様で使えるほか
MariaDB, PostgreSQLに対応してるようです。

ちなみにKotlinでも書くことができます。

詳しくはこちらから。
↓↓↓
https://quarkus.io/get-started/

## 実行環境
macOS Mojave 10.14.3

### QUARKUSを動かすのに必要なもの
- JDK1.8 with JAVA_HOME 以上
- Maven3.5.3以上
- GraalVM

### Mavenセットアップ
Macなのでhomebrewでインストール

```
brew update && brew install Maven
```

インストールされたか確認

```
mvn --version
```
こう返ってくれば成功

```
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00)
Maven home: /usr/local/Cellar/maven/3.6.0/libexec
Java version: 1.8.0_162, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.14.3", arch: "x86_64", family: "mac"
```
### GraalVMのセットアップ
GraalVM（graalvm-ce-1.0.0-rc13-macos-amd64.tar.gz）をインストールする
↓↓↓
https://github.com/oracle/graal/releases

GraalVMの環境変数（GRAALVM_HOME）を設定
お使いのshellにあわせてパスを通してください。
bash -> bashprofile
zsh -> zshrc

```
GRAALVM_HOME=/Library/Java/JavaVirtualMachines/graalvm-ce-1.0.0-rc13-macos-amd64/Contents/Home
```

## 新規プロジェクトの立ち上げ
プロジェクトを置きたいディレクトリに移動して

```
$ mvn io.quarkus:quarkus-maven-plugin:0.11.0:create \
    -DprojectGroupId=jp.acme \
    -DprojectArtifactId=getting-started \
    -DclassName="org.acme.quickstart.GreetingResource" \
    -Dpath="/hello"
```

これでQUARKUSををベースにしたMavenでビルドするアプリケーションが立ち上げられる。
ディレクトリ構造はこんな感じ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/186817/4b923ac9-e5fa-7ffa-3e92-b9e1659f0285.png)

/dockerにはDockerfile
/javaの中に必要なJavaのコードを置いていく感じここではGreetingResource.javaがあり中身は↓↓

```GreetingResource.java
package org.acme.quickstart;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}
```

/helloでGETすると"hello"を返す簡単なコードが入っている。


## ビルド
```
# 開発モードで起動
$ mvn compile quarkus:dev
```

開発モードで立ち上げるとホットリロードがきく。
（ホットリロードは変更が入るたびに差分を都度コンパイルして反映してくれる機能）

起動に成功したら確認

デフォルトの設定で8080ポートで立ち上がるので curlを叩いてhelloを返すか確認する

```
curl http://localhost:8080/hello
```

## ネイティブバイナリの生成
```
$ mvn package -Pnative -Dnative-image.docker-build=true
```

そもそもネイティヴバイナリとは何かというと
実行マシーンごとに用意される実行に必要な命令を下す機械語のことをさす。
つまりGraalVMを使うことによりLinuxにはLinuxに最適化された機械語を吐き出してくれるよっていうこと

ちなみにこの処理にはやや時間がかかる。
本家のドキュメントでも15分時間をくれって書いてある。

## Dockerビルド
ここまできたらDockerビルドしてみよう。
コマンドはこちら

```
$ docker build -f src/main/docker/Dockerfile -t <イメージ名> .
```

こうするとさっき作った初期のアプリケーションに含まれてたDockerfileを使ってイメージをビルドしてくれる。
Dockerfileの中はこんな感じ

```
####
# Before building the docker image run:
#
# mvn package -Pnative -Dnative-image.docker-build=true
#
# Then, build the image with:
#
# docker build -f src/main/docker/Dockerfile -t quarkus/getting-started .
#
# Then run the container using:
#
# docker run -i --rm -p 8080:8080 quarkus/getting-started
#
###
FROM registry.fedoraproject.org/fedora-minimal
WORKDIR /work/
COPY target/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
```

`COPY target/*-runner /work/application`
とあるようにtarget配下にあるネイティブバイナリを使っていくよって記載をしてくれている。



## Dockerコンテナ起動
```
$ docker run -i --rm -p 8080:8080 <イメージ名>
```

このコマンドを叩くことで先ほどのイメージを起動できる。ポートは8080番
このとき実行スピードを表示してくれるが、めちゃくちゃ早い。

僕の手元だと0.005秒で起動した。


## まとめ
QUARKUSを使うことでDockerにデフォルト対応したJVMの弱点であった起動速度を克服したアプリケーション開発ができそう。
また作ったDockerイメージを元に共通の開発環境ができるので大規模開発にも向いていると言えそう。

これを機にJavaがさらに楽しめる環境がで揃うといいなぁと思っています。
GraalVMについて興味がかなり湧いたのでGraalVMについての記事はまた今度書きます。