Build executable jar of spring boot application from a gradle multi-project

127 Views Asked by At

I'm trying to build an executable jar to run my Spring application. I uploaded an MWE here: https://github.com/qnguba/testGradle1 (note that the MWE contains only the subproject 'main' within the 'code' folder)

The parent build.gradle looks like this:

plugins {
    id 'org.springframework.boot' version '3.2.1'
    id 'io.spring.dependency-management' version '1.1.4'
    id 'java'
}

apply plugin: 'io.spring.dependency-management'
apply plugin: 'application'


group = 'org.example'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-web')
}

tasks.test {
    useJUnitPlatform()
}

bootJar {
    manifest {
        attributes(
                'Class-Path': configurations.runtimeClasspath.files.collect { it.getName() }.join(' '),
                'Main-Class': 'org.example.Main'
        )
    }
}
sourceSets {
    main {
        java {
            srcDirs = ['./code/main/src/main/java']
        }
    }
}

The sub-project build.gradle looks like this:

plugins {
    id 'org.springframework.boot' version '3.2.1'
    id 'io.spring.dependency-management' version '1.1.4'
    id 'java'
}

apply plugin: 'io.spring.dependency-management'


group = 'org.example'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}
test {
    useJUnitPlatform()
}

gradle.taskGraph.whenReady {
    tasks.withType(JavaExec) {
        if (name.endsWith(".main()")) {
            println("Setting executable to java launcher for ${name}")
            it.setExecutable(javaLauncher.get().executablePath.asFile.absolutePath)
        }
    }
}

dependencies {

    implementation('org.springframework.boot:spring-boot-starter-web')
}

The Main.java looks like this:

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackages = "org.example")
public class Main {

    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

When I run gradle jar or gradle bootJar task, I get an executable jar but when I execute it, I get the following error:

java -jar testGradle-1.0-SNAPSHOT.jar 
Error: Could not find or load main class org.example.Main
Caused by: java.lang.ClassNotFoundException: org.example.Main

I added sourceSets to make the build of the bootJar finally compile but I'm not sure whether this excludes spring from the jar file.

1

There are 1 best solutions below

0
RenatoIvancic On

I created a PR with my proposal: https://github.com/qnguba/testGradle1/pull/1/files

I also tried to explain the configuration in the Readme.md file.

As I understand your project SpringBoot application is part of the main subproject. And it should be configured and treated like this (except if I'm missing your very unusual requirements). IMHO you should follow standard conventions in setting up the project. Jar file will be created in the code/main/build/libs folder and you should run it from there.

  1. Configure main class in your subproject as explained in SpringBoot Gradle plugin documentation: https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/#packaging-executable.configuring.main-class

  2. Build your project: ./gradlew clean build

  3. Execute boot jar file of the main subproject: java -jar code/main/build/libs/main-1.0-SNAPSHOT.jar