Spring Boot で main class が複数ある場合のエラー

Spring Boot を実行した際に遭遇したエラー。

今回の検証内容のリポジトリ

./mvnw spring-boot:run
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.4.1:run (default-cli) on project non-web: Execution default-cli of goal org.springframework.boot:spring-boot-maven-plugin:2.4.1:run failed: Unable to find a single main class from the following candidates [com.kiyotakeshi.non.web.Runner3, com.kiyotakeshi.non.web.Runner2, com.kiyotakeshi.non.web.Runner1] -> [Help 1]
[ERROR] 

run failed: Unable to find a single main class とあるように、main class を指定する必要がある。


今回試してみた、 work around は以下の二つ( README.md に記載)。

いずれも、 pom.xmlspring-boot-maven-plugin にて mainClass を指定します。

 <properties>
        <java.version>11</java.version>
        <spring.boot.mainClass>com.kiyotakeshi.non.web.Runner1</spring.boot.mainClass>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>${spring.boot.mainClass}</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

1つ目はビルドした jar のメインクラスの情報を更新してあげるやり方。

まずは、ビルドした jar を解凍し、どのクラスを読み込むかを確認します。

./mvnw clean package

# 任意のディレクトリにて jar を解凍
cp target/non-web-0.0.1-SNAPSHOT.jar /tmp/ 

cd /tmp/ 

unzip non-web-0.0.1-SNAPSHOT.jar

grep -Ei "start|main" META-INF/MANIFEST.MF

mainClass で指定している Runner1 になっています。

Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.kiyotakeshi.non.web.Runner1

この .jar を実行する際に、 JVM Options でメインクラスを指定することで、別クラスを実行できます。

java -cp non-web-0.0.1-SNAPSHOT.jar \
-Dloader.main=com.kiyotakeshi.non.web.Runner3 \
org.springframework.boot.loader.PropertiesLauncher

2つ目は Profile 指定により切り替える方法です。

 <properties>
        <java.version>11</java.version>
        <spring.boot.mainClass>com.kiyotakeshi.non.web.Runner1</spring.boot.mainClass>
    </properties>
    <profiles>
        <profile>
            <id>2</id>
            <properties>
                <spring.boot.mainClass>com.kiyotakeshi.non.web.Runner2</spring.boot.mainClass>
            </properties>
        </profile>
        <profile>
            <id>3</id>
            <properties>
                <spring.boot.mainClass>com.kiyotakeshi.non.web.Runner3</spring.boot.mainClass>
            </properties>
        </profile>
    </profiles>

実行時に Profile を指定して実行します。

./mvnw spring-boot:run -P 2

参考にした stack overflow