Oracle Application Container Cloud Service 用のアプリケーションを Gradle で作ってみた


## 説明
以前、Oracle の Application Container Cloud Serivce を使用していた時は、**Maven** を利用して以下のようなプラグインを使って Fat-JAR (Uber JAR) を作成し、また Application Container Cloud Serivce 用のパッケージになるように **manifest.json** を含む ZIP ファイルを作成していました。

- maven-assembly-plugin
- maven-shade-plugin

さて、「[ことりんと一緒 - 5. Spring Boot](https://qiita.com/shinyay/items/5d10a6dc50aa99256adf)」で Spring Boot の実行可能 JAR を作ったのですが、これを Application Container Cloud Service にデプロイしてみようと思います。
ところが、今回のプロジェクトは、**Maven** ではなく **Gradle** を使って作成しました。
というわけで、**Gradle** による Application Container Cloud Service のパッケージ作成を行ってみたいと思います。


## 前提
次の環境で作業しています。

|項目|内容|
|---|---|
|OS|MacOS|
|JDK|1.8.0_152|
|Gradle|4.3.1|
|Kotlin|1.2.10|
|Spring Boot|1.5.9|
|IDE|IntelliJ IDEA|

ソースコードは以下のものを使います。

- [kotlin-basics 1.0.0](https://github.com/shinyay/kotlin-basics/tree/1.0.0/04-springboot)

## 手順
### 1. メタファイル
Application Container Cloud Serivce のパッケージとデプロイメントには次の２つのメタファイルが必要です。

|ファイル名|説明|
|-----------|-----|
|manifest.json|ランタイムに関する情報<br>- ランタイムの種類とバージョン<br>- 起動コマンド など|
|deployment.json|アプリケーションインスタンスに関する情報<br>- 割当メモリサイズ<br>- インスタンス数<br>- 環境変数 など|

**src** ディレクトリの配下に **metafiles** というディレクトリを作り、そこに maniifest.json と deployment.json を配置する事にします。

#### 1.1. manifest.json
以下のような JSON ファイルを作成します。

```json
{
  "runtime": {
    "majorVersion": "8"
  },
  "type": "web",
  "command": "java -jar kotlinboot.jar",
  "startupTime": "30",
  "release": {
    "build": "171222-1900",
    "commit": "98a43e831ae915cafb5d342e75b3248278ba5a95",
    "version": "1.0.0"
  },
  "notes": "notes related to release",
  "mode": "rolling"
}
```

ポイントは２点です。

```json
"runtime": {
  "majorVersion": "8"
}
```

```json
"command": "java -jar kotlinboot.jar"
```

|ポイント|説明|
|---|---|
|majorVersion|Java のバージョン|
|command|アプリケーションの起動コマンド|

#### 1.2. deployment.json
以下のような JSON ファイルを作成します。

```json
{
  "memory": "2G",
  "instances": "1"
}
```

この内容は、文字通り 割り当てるメモリ容量を **2GB** で、インスタンス数を "1" にしています。

### 2. build.gradle
build.gradle には次の処理を行うタスクを追加します。

1. manifest.json と JAR ファイルを含む ZIP ファイルの生成
2. deployment.json を 1. で生成した ZIP ファイルと同一ディレクトリにコピー

#### 2.1. ZIP ファイルの作成
以下のようなタスクを作成しました。

```groovy
task packageForACCS(type: Zip, dependsOn: 'build') {
    archiveName = "distribution.${extension}"
    into('/') {
        from jar.outputs.files.singleFile
        from 'src/metafiles/manifest.json'
    }

}
```

 build/distributions 配下に **distrobution.zip** という名前で出力するように定義しています。
また **from** で JAR ファイルと manifest.json を指定し、ZIP ファイルの直下に配置するように **into** で指定しています。

#### 2.2. deployment.json のコピー
以下のようなタスクを作成しました。

```groovy
task prepareForACCS(type: Copy, dependsOn: 'packageForACCS') {
    from 'src/metafiles/deployment.json'
    into 'build/distributions'
}
```

作成したタスク `packageForACCS` が終了しないと、`build/distributions` ディレクトリが作成されません。そこで、**dependsOn** で `build/distributions` を指定し前提タスクとしています。

### 3. 実行
それでは、`prepareForACCS` を実行します。

```
19:18:07: Executing external task 'packageForACCS'...
:compileKotlin UP-TO-DATE
:compileJava NO-SOURCE
:copyMainKotlinClasses UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:jar
:bootRepackage
:assemble
:compileTestKotlin NO-SOURCE
:compileTestJava NO-SOURCE
:copyTestKotlinClasses UP-TO-DATE
:processTestResources NO-SOURCE
:testClasses UP-TO-DATE
:test NO-SOURCE
:check UP-TO-DATE
:build
:packageForACCS

BUILD SUCCESSFUL

Total time: 4.084 secs
19:18:11: External task execution finished 'packageForACCS'.
```

タスクが終了すると、以下のように build/distributions ディレクトリ配下に デプロイする際に必要な ZIP ファイルと deployment.json が配置されている事が確認できます。

![image](https://qiita-image-store.s3.amazonaws.com/0/127983/c19757a5-d0ee-79c6-e465-ed948bf1ddc4.png)

## まとめ
Maven で maven-assembly-plugin を使って生成するよりも、Gradle タスクで定義した方が簡単に Application Container Cloud Service 用のパッケージの準備ができました。

### 今回のソース
- [shinyay/oracle-accs-gradle-springboot
 1.0.0](https://github.com/shinyay/oracle-accs-gradle-springboot/tree/1.0.0)