Gradleでメインクラスを変えてFatjarを作る

## 目的
Javaでしか使えないライブラリがあって、それをKotlinで実装したアプリケーションが既存でありました。
今回はその一部の機能をPythonのバッチから呼んで使いたかったので、
Kotlinアプリケーションのメインクラスを変えてjarを作り、
PythonからjavaコマンドでKotlinを叩こうと思いました。

Gradleをうまく使えば、メインクラスを変更してFatjarを作ることができるみたいなので、
チャレンジしてみます

## 環境
Kotlin JDK 8
java8
jdk14
Gradle 6.4.1

## 構造
試してみる用に簡単なプロジェクトを作成してみました

```
app
├── gradle
│   └── wrapper
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── build.gradle
└── src
    ├── main
    │   ├── kotlin
    │   │   └── automated_data_create
    │   │       ├── App.kt
    │   │       ├── App2.kt
    │   │       └── model
    │   │           └── Osushi.kt
    │   └── resources
    └── test
        ├── kotlin
        │   └── automated_data_create
        │       └── AppTest.kt
        └── resources
```
```app/src/main/kotlin/automated_data_create/App.kt
/*
 * This Kotlin source file was generated by the Gradle 'init' task.
 */
package automated_data_create

import automated_data_create.model.Osushi

class App {
    val greeting: String
        get() {
            return "Hello world."
        }

}

fun main(args: Array<String>) {
    println(App().greeting)
    val osushi = Osushi("マグロ", 100)
    println("こちらを選択しました。: " + osushi.name + " -> " + "￥" + osushi.price)
}
```
```app/src/main/kotlin/automated_data_create/App2.kt
/*
 * This Kotlin source file was generated by the Gradle 'init' task.
 */
package automated_data_create

import automated_data_create.model.Osushi


class App2 {
    val greeting: String
        get() {
            return "Hello world."
        }

}

fun main(args: Array<String>) {
    println(App2().greeting)
    val osushi = Osushi("ウニ", 200)
    println("こちらを選択しました。: " + osushi.name + " -> " + "￥" + osushi.price)
}
```
``` app/build.gradle
/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Kotlin application project to get you started.
 */

plugins {
    // Apply the Kotlin JVM plugin to add support for Kotlin.
    id 'org.jetbrains.kotlin.jvm' version '1.3.61'

    // Apply the application plugin to add support for building a CLI application.
    id 'application'
    id 'com.github.johnrengelman.shadow' version '5.0.0'
    id 'java'
}

repositories {
    // Use jcenter for resolving dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // Align versions of all Kotlin components
    implementation platform('org.jetbrains.kotlin:kotlin-bom')

    // Use the Kotlin JDK 8 standard library.
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'

    // Use the Kotlin test library.
    testImplementation 'org.jetbrains.kotlin:kotlin-test'

    // Use the Kotlin JUnit integration.
    testImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
}

application {
    // Define the main class for the application.
    mainClassName = 'automated_data_create.AppKt'
}
```
## メインクラスをそのままでjarファイルの作成
以下のコマンドでプロジェクトをビルドできます

```
$ ./gradlew shadowJar
# or
$ gradle shadowJar
```
この場合、app/build.gradleファイルでmainClassNameにAppKtファイルが指定されているので
App.ktがメインクラスとして実行されます。

ビルドしたjarを実行するコマンド

```
$ java -jar xxx-1.0-SNAPSHOT-all.jar
Hello world.
こちらを選択しました。: マグロ -> ￥100
```

## メインクラスを別のクラスに変更してビルド
gradle.buildファイルにbuildタスクを追加します。

```app/build.gradle
:
application {
    // Define the main class for the application.
    mainClassName = 'automated_data_create.AppKt'
}
# ここから下を追加↓
task customFatJar2(type:Jar) {
    // メインクラスの設定
    manifest {
        attributes 'Main-Class': 'automated_data_create.App2Kt'
    }
    baseName = 'second'
    // 依存ライブラリの追加
    from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }


    with jar
}
```
ここでは、メインクラスをApp2.Ktに指定した。
baseNameは任意のjarファイル名を指定。

依存ライブラリの追加方法は、gradleのバージョンによって変わってくるので注意。

`compile`: dependenciesの中で設定しているcompileをリストとして取得する。
※ただ、Gradle3.4以降はcompileの使用は非推奨

`compileClasspath` : implemention等で登録されているdependenciesをリストで取得する。
※gradle4.9以降から

参考：　compileとimplementionとの使いわけ
　　　　https://qiita.com/opengl-8080/items/6ad642e0b016465891de
　　　　cofigrations.compileとconfigrations.compileClasspathがどう見えるかわかりやすかった
　　　　https://qiita.com/MirrgieRiana/items/d3271f6979c1451207a6



- gradleタスクの実行

```
$ ./gradlew customFatJar2
or
$ gradle customFatJar2

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.4.1/userguide/command_line_interface.html#sec:command_line_warnings


BUILD SUCCESSFUL in 1s
```
- jarの実行

```
$ java -jar build/libs/second.jar
Hello world.
こちらを選択しました。: ウニ -> ￥200
```

## 終わりに
これで、Kotlinのアプリケーションをjavaコマンドで叩けるようになったので、
あとはPythonから実行できるようにするだけになりました！
ちなみに、Pythonからはsubprocessライブラリ使って実行する予定です。
もっといい方法ありましたら教えてください！