目的
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
/*
* 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)
}
/*
* 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)
}
/*
* 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タスクを追加します。
:
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ライブラリ使って実行する予定です。
もっといい方法ありましたら教えてください!