Search code examples
javaspring-bootgradlemulti-module

Jar built from Gradle multi-module project with Spring Boot doesn't work


I created spring-boot gradle multi-module project which consisted of 3 modules: controller, service, repository. Main file was situated in Controller-module and named MySpringBootApplication.

I could build this project (using gradle build) and could get jar-file. But after starting this jar in command line I took the next error:

Error: Could not find or load main class com.epam.esm.config.MySpringBootApplication Caused by: java.lang.ClassNotFoundException: com.epam.esm.config.MySpringBootApplication.

To fix this bug I added Main-Class attributte to MANIFEST.MF file in main build.gradle but this action didn't help. So could anybody help?

MAIN BUILD.GRADLE FILE

        plugins {
            id 'java'
            id 'io.spring.dependency-management' version '1.0.11.RELEASE'
            id 'org.springframework.boot' version '2.4.3'
            id 'application'
        }
        
        group = 'com.myproject'
        version = 'snapshot-1.0.0'
        
        repositories {
            mavenCentral()
        }
        
        bootJar {
            enabled = false
        }
        
        jar {
            enabled = true
            manifest {
                attributes(
                        "Main-Class": "com.myproject.config.MySpringBootApplication")
            }
        }
       
     dependencies {
            implementation 'org.springframework.boot:spring-boot-starter'
            implementation group: 'org.springframework.boot', name: 'spring-boot-starter-parent', version: '2.4.3', ext: 'pom'
        
        }
        
        test {
            useJUnitPlatform()
        }
        
        
        subprojects {
            apply plugin: 'org.springframework.boot'
            apply plugin: 'io.spring.dependency-management'
            apply plugin: 'java'
        
            group = 'com.epam.esm'
            version = '1.0.0'
        
            repositories {
                mavenCentral()
            }
            bootJar {
                enabled = false
            }
        
            jar {
                enabled = true
            }
            dependencies {
                implementation 'org.springframework.boot:spring-boot-starter'
                implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
                implementation 'org.springframework.boot:spring-boot-starter-hateoas'
                implementation 'org.springframework.boot:spring-boot-starter-actuator'
                implementation 'org.springframework.boot:spring-boot-starter-security'
                testImplementation 'org.springframework.boot:spring-boot-starter-test'
                implementation group: 'org.hibernate', name: 'hibernate-envers', version: '5.4.27.Final'
                implementation group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
                implementation group: 'org.openidentityplatform.commons', name: 'json-web-token', version: '2.0.11'
                compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.18'
                annotationProcessor 'org.projectlombok:lombok'
                implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1'
                implementation group: 'org.springframework.boot', name: 'spring-boot-starter-parent', version: '2.4.3', ext: 'pom'
            }
            test {
                useJUnitPlatform()
            }
        }

SETTINGS.GRADLE

    rootProject.name = 'module'
    include('repository', 'service', 'controller')

Solution

  • The Spring Boot application executable jar file is built by bootJar task, so adding the main-class information via jar won't work either.

    The bootJar task tries to create an executable jar, and that requires a main() method. As a result, you need to disable the bootJar task and enable the jar task (which creates an ordinary jar rather than an executable jar) only for your no executable jar modules.

    Since you did it under subprojects section, the controller module will produce a standard jar as well. You may produce standard jars for all modules but excluding the controller module as follows:

    subprojects {
        
        if (it.name != 'controller') {
            bootJar {
                enabled = false
            }
    
            jar {
                enabled = true
            }
        }
    }    
    

    In addition you have to remove the jar section below

     jar {
            enabled = true
            manifest {
                attributes(
                        "Main-Class": "com.myproject.config.MySpringBootApplication")
            }
        }
    

    and replace

    bootJar {
        enabled = false
    }
    

    with

        bootJar {
            mainClassName = 'com.myproject.config.MySpringBootApplication'
        }
    

    Reference

    Creating a Multi Module Project