Quarkus: 開発環境構築とHelloWorld作成

Quarkus(カーカス）はマイクロサービス、コンテナー向けのスパー軽量Javaフレームワークである。APIサーバーを作りたい時、フレームワークを検討している際 強い候補になるでしょう

https://ja.quarkus.io/about/

## 主な特徴
- 軽量：SpringBootとかに比較し、起動時間が速い、使用メモリも少なめ、アプリサイズも小さめ
- ネイティブアプリとして実行可能：GraalVMを使ってコンパイルすれば　ネイティブアプリになる。SpringBootもできるが、Quarkusは最初からGraalVMのために設計された。SpringBootだとGraalVMのための設定が難しめ。ネイティブになった場合は　起動時間は爆速、使用メモリも激少。JVM上で動かないので
- JavaかKotlin言語で開発可能。MavenかGradleでプロジェクト管理可能
- ネイティブコンパイルに対応したライブラリが豊富になってきた
- Apache License version 2.0ライセンスのOSSである。Red Hat社か主に開発推進

## Quarkus

### 1. CLIをインストール


[公式ガイド](https://quarkus.io/guides/cli-tooling)の一つ SDKMANを使ってQuarkus CLIをインストールする。SDKMAN自体がない場合は[ここをみると良い](https://qiita.com/nacho4d/items/a9f0e1a0ec5e22e6f16d)

```
sdk install quarkus
```

バージョンを確認
```
quarkus --version
```

私の場合は、3.18.4が出力された。これから作るプロジェクトの`.sdkmanrc`にも入れたいのでに入れたいので今覚えておく。

### 2. Quarkus CLIでhello worldを作成

```bash 
quarkus create app --kotlin --gradle-kotlin-dsl --package-name <パッケージ名> <アプリ名>
```

説明
- `create app`でAPIサーバーとして使われるプロジェクトを作成. これだけ必須
- `--kotlin` 開発言語。指定しなかったらJavaになる（Supersonic Subatomic Javaだよ）
- `--gradle-kotlin-dsl` プロジェクト管理に使う設定。MavenとGradleとGradle with kotlin DSL選べる。指定しなかったらMavenになる
- `--package-name <パッケージ名>` パッケージ名（Java/Kotlinファイルの上に出る１行のベース）. 指定しなかったら org.acmeとなる
- `<アプリ名>` アーティファクトIDだが、簡単言えばアプリ名. 指定しなかったら code-with-quarkusとなる

任意のパラメーターが多く指定しなかったら　おもちゃプロジェクトにより近くなる. より詳細は `quarkus create app --help` 

私の場合は:
```
quarkus create app --kotlin --gradle-kotlin-dsl --package-name com.ibm.jp bff-server
```
プロジェクトに入って、ファイル構成を確認してみる

```bash
cd bff-server
tree .
├── README.md
├── build.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src
    ├── main
    │   ├── docker
    │   │   ├── Dockerfile.jvm
    │   │   ├── Dockerfile.legacy-jar
    │   │   ├── Dockerfile.native
    │   │   └── Dockerfile.native-micro
    │   ├── kotlin
    │   │   └── com
    │   │       └── ibm
    │   │           └── jp
    │   │               └── GreetingResource.kt
    │   └── resources
    │       └── application.properties
    ├── native-test
    │   └── kotlin
    │       └── com
    │           └── ibm
    │               └── jp
    │                   └── GreetingResourceIT.kt
    └── test
        └── kotlin
            └── com
                └── ibm
                    └── jp
                        └── GreetingResourceTest.kt
```


### 3. GraalVMをインストール

:::note info
とりあえず「試してみるだけ」という目的であれば、通常のJVMがセットアップ済であればこのステップをスキップしても良い。
:::

このステップでは、GraalVMをインストールする。SDKMANを使ってインストール＋管理をする。


事前に調べたので 私はGraalVMのComunity Editionの最新バージョンが欲しいので以下のコマンドで一発。（availableなバージョンのリストを調べたい場合は `sdk list java | grep graal`で一覧取得）
```bash
sdk install 23.0.2-graalce
```
そして sdkmanrcファイルに入れることで チームで同じ設定にすることができる。Quarkusも一緒に入れる

```bash
echo java=23.0.2-graalce >> .sdkmanrc
echo quarkus=3.18.4 >> .sdkmanrc
```
自分の.sdkmanrcはこんな感じ
```.sdkmanrc
java=23.0.2-graalce
quarkus=3.18.4
```

これからローカルで開発をする際に、`sdk env`だけをやればいい。(java,quarkusインストールしていない初回は`sdk env install`で)
```
sdk env
```


### 4. アプリケーションを起動

基本的な動作・コマンド

#### 4.1 JVM上で動く開発モードで実行
ライブコーディングができる.

```bash
./gradlew quarkusDev
```

![quarkusDev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83390/b9dac589-c4ad-49cb-bd93-e81894c79a6b.png)

#### 4.2 JVM上で動くjarをビルドして実行

buildすると `build/quarkus-app/`にjarが配置される。このjarは普通のjarでdependencyを含まない。dependencyは`build/quarkus-app/lib/`に配置される

```zsh
./gradlew build # ビルド
java -jar build/quarkus-app/quarkus-run.jar # 実行
```


#### 4.3 JVMで動くuber jarをビルドして実行

uber jarとは、全てのdependencyを含むjar。何かの理由で手軽に共有したい場合は、これは便利。

```zsh
./gradlew build -Dquarkus.package.jar.type=uber-jar # ビルド
java -jar build/*-runner.jar # 実行
```

#### 4.4 ネイティブビルドして実行

ネイティブビルドをするのはGraalVMが必要。ネイティブビルドの実行速度はすごい、メモリ使用量も低、アプリサイズも小さめ。

私たちは上記で GraalVMをインストールしたので、ローカルでもビルドできる
```zsh
./gradlew build -Dquarkus.package.type=native # ビルド
./build/bff-server-1.0.0-SNAPSHOT-runner # 実行
```

#### 4.5 コンテナー上でビルド
なんらかの理由でローカルにGraalVMがない場合、コンテナー上でもビルドできる
```zsh
./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true # ビルド
```

### 5. テスト実行

普通のユニットテストを実行。プロジェクトのtestディレクトリー配下のテストが実行される。

```zsh
./gradlew test
```

普通の`test`タスク以外に`quarkusTest`, `quarkusIntTest`もある。

```zsh
./gradlew quarkusTest
# OR
./gradlew quarkusTest --continue
# OR
./gradlew quarkusIntTest
# OR
./gradlew quarkusIntTest --continue
```

それぞれの目的とユースケースのまとめは以下の通り

| 観点 | `quarkusDev`| `test` | `quarkusTest` | `quarkusIntTest` |
|---|---|---|---|---|
| 目的 | 開発向け | テスト向け | テスト向け | テスト向け |
| ユースケース | デバッグ　| `test`ディレクトリ配下のユニットテストを実行 | `test`ディレクトリ配下のユニットテストを実行 | `native-test`ディレクトリ配下の統合テストを実行 |
| 実行環境　| JVM| JVM + Junit test runner | JVM + Quarkus test runner | Native (GraalVMコンパイル) + Quarkus test runner|
| ホットリロード対応 | あり | なし | なし | なし　| 
| テストを実行するか | いいえ | はい | はい | はい |
| 対話的か | いいえ | いいえ | はい。`--continue`フラグでオフ可能|はい。`--continue`フラグでオフ可能|


以上！

See you later!🐊