VsCode で F5 を押して Kotlin の Spring Boot を起動するための手順

# 概要
IntelliJ を使い続けていていましたが、Cursor で Kotlin の Spring Boot アプリケーションを起動させてみようと思いました。起動するまでに意外にハマってしまったので備忘録で記述します。

# バージョン
Sqauia 15.3.2 に下記 Cursor をインストールしました
```
Version: 0.48.8 (Universal)
VSCode Version: 1.96.2
```

# プロジェクト構成
Spring Initializr で生まれたプロジェクトそのままの構成です。

```
Root
├── build.gradle.kts
├── gradlew
├── gradlew.bat
├── HELP.md
├── settings.gradle.kts
└── src
    ├── main
    │   ├── kotlin
    │   │   └── com
    │   │       └── example
    │   │              └── demo
    │   │                   └── DemoApplication.kt
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       └── templates
    └── test
        └── kotlin
            └── com
                └── example
                        └── demo
                            └── DemoApplicationTests.kt
```

# プラグインのインストール
VsCode に必要なプラグインをインストールします。

## マストと思われるプラグイン
いろいろと調べながらインストールしていったのでもしかしたらマストではないかもしれませんが、インストールする必要があると思われるプラグインを列挙します。

### Java
Oracle 社が出しているプラグイン

### Kotlin
コード補完、デバッグができるプラグイン

### Kotlin Language
Kotlin を VsCode で利用するためのプラグイン

### Debugger for Java
Microsoft 社が出している Java のデバッガー

### Gradle for Java
Microsoft 社が出している gradle のプラグイン

### Test Runner for Java
テストの実行とデバッグができるプラグイン

## オプション
個人の好みによってインストールしたプラグイン

### IntelliJ IDEA KeyBindings
IntelliJ のキーバインドに慣れていてもう VsCode のキーバインドを覚えたくないのでインストール

### Vim
以前の VsCode のプラグインよりも利用しやすくなっていました。ctrl + { が以前使えず、ESC を余儀なくされていたと思うが、ctrl + { ができるようになっていました

### Material Deep Oceans
単純に見慣れた UI であるため

# 各種設定ファイルの設定
GUI ではないこと、gradle が勝手に動かないことに違和感がありつつ、そういうものかと設定ファイルを作成しました。

## settings.json
IntelliJ でいうところの、command + ; でプロジェクトの JVM を決めたり Kotlin のバージョンを決めたりするものであると思われます。command + shift + P で、[Preferences: Open User Settings(JSON)] をクリックして編集します。

```settings.json
{
    "window.commandCenter": true,
    "workbench.colorTheme": "Material Deep Ocean",
    "kotlin.codegen.enabled": true,
    "kotlin.compiler.jvm.target": "17",
    "java.configuration.runtimes": [
        {
          "name": "JavaSE-17",
          "path": "/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home",
          "default": true
        }
    ]
}
```

## tasks.json
アプリケーションを実行する前に定義できるタスクです。IntelliJ デイいうところの、[Build, Execution, Deployemen] -> [Build Tools] -> [Gradle] です。IntelliJ ではデフォルトで実行していると思われる、gradle の build (テスト実行なし) を定義します。
command + shift + P で、[Tasks: Open User Tasks] をクリックして、tasks.json を開きます。
下記を記述します。

```tasks.json
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "./gradlew build -x test",
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}
```

この設定を入れても下記がでていたので、fix with ai をすると直りました。

```
Cannot inline bytecode built with JVM target 17 into bytecode that is being built with JVM target 1.8. Please specify proper '-jvm-target' option
```

## launch.json
IntelliJ でいうところの、option + ctrl + r の Edit Configuration を定義します。ただし下記注意点がありました。

### 注意点
kotlin をエントリーポイントにすると vmArgs および env がきかないようです。


#### 詳細
メインクラスを kotlin にして下記を定義しました。

```DemoApplication.kt
package com.example.demo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class DemoApplication

fun main(args: Array<String>) {
	val jvm = System.getProperty("spring.profiles.active")
	println(jvm)
	val env = System.getenv("SPRING_PROFILES_ACTIVE")
	println(env)
	runApplication<DemoApplication>(*args)
}

```

その上で、launch.json を定義しましたが、**vmArgsならびにenvが効かず値を取得できず NULL になって**しまいました (args もききませんでした)。プロファイルを使う必要がある場合、起動時引数の方法でローカル起動を考えるとエントリーポイントを Java にせざるを得ないように思われます。type を kotlin にして Spring Boot のプロファイルを渡す場合は、環境変数をセットして VsCode を起動する、などして、launch.json に頼らずに環境変数に Spring Boot のプロファイルをセットする必要があるように思われます。

```launch.json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [

        {
            "request": "launch",
            "name": "Kotlin Launch",
            "type": "kotlin",
            "projectRoot": "${workspaceFolder}",
            "vmArgs": ["-Dspring.profiles.active=local"],
            "mainClass": "com.example.demo.DemoApplicationKt",
            "console": "internalConsole",
            "preLaunchTask": "build",
            "internalConsoleOptions":"openOnSessionStart",
            "env": {
                "SPRING_PROFILES_ACTIVE": "local"
              }
        }
    ]
}
```

なお、下記のようにエントリーポイントを定義してもやはり vmArgs と env は渡りませんでした。Kotlin でまだうまく動かない？

```EntryPoint.kt
object EntryPoint {

    @JvmStatic
	fun main(args: Array<String>) {
		val jvm = System.getProperty("spring.profiles.active")
		println(jvm)
		val env = System.getProperty("SPRING_PROFILES_ACTIVE")
		println(env)
		runApplication<DemoApplication>(*args)
	}
}
```


### Java のエントリーポイントは OK
エントリーポイントを Java にする場合問題なく動きます。type を java にして projectRoot を削除します。

```launch.json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [

        {
            "name": "Java Launch",
            "request": "launch",
            "type": "java",
            "vmArgs": ["-Dspring.profiles.active=local"],
            "mainClass": "root.EntryPoint",
            "console": "internalConsole",
            "preLaunchTask": "build",
            "internalConsoleOptions":"openOnSessionStart",
            "env": {
                "SPRING_PROFILES_ACTIVE": "local"
              }
        }
    ]
}
```

```EntryPoint.java
package root;


import org.springframework.boot.SpringApplication;

public class EntryPoint {
    public static void main(String[] args) {
		var jvm = System.getProperty("spring.profiles.active");
		System.out.println(EntryPoint.class.getName() + ":'" + jvm + "'");
		var env = System.getenv("SPRING_PROFILES_ACTIVE");
		System.out.println(env);
		SpringApplication.run(EntryPoint.class, args);
    }
}
```

### その他注意
* preLaunchTask に tasks.json で定義した build をセットします。
* console を指定しないとコンソールでログが出てきません。
* kotlin のエントリーポイントを mainClass にして、launch.json の type を java にしてしまうと、アプリケーション実行時に、java.lang.ClassNotFoundException: com.example.demo.DemoApplicationKt がでます。

# 実行
F5 を押します

# 参考
java の launch.json の定義です

https://code.visualstudio.com/docs/java/java-debugging