Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpringBoot with multi-project Gradle --> Main class name has not been configured and it could not be resolved

I have the following project structure:

RootProject
├── lib
     └── src
          └── main
               └── java
                    └── ...
├── test-project
     └── src
          └── main
               └── java
                    └── ...

└── build.gradle

I trying to follow Gradle best practices for multi project builds, and therefore I describing the whole build process in single build.gradle file.

"RootProject" is just a root project without any code and its single purpose is to provide a single build.gradle for its subprojects: "lib" and "test-project".

"test-project" is a SpringBoot project (micro service) using "lib" as compile dependency.

My common build.gradle looks as the following:

plugins{
    id 'java'
    id 'org.springframework.boot' version '2.1.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.6.RELEASE'
}


allprojects {
    repositories {
        jcenter()
    }
}


subprojects {

    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'org.springframework.boot'

    group = 'com.xxx.yyy'
    version = '1.0'

    sourceCompatibility = 1.8
    targetCompatibility = 1.8
}


project(":lib"){

    apply plugin: 'java-library'

    dependencies {

        implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
        implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
        testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test'
    }

    bootJar { enabled = false }
    jar { enabled = true }
}

project(":test-project"){

    apply plugin: 'java'

    dependencies {
        implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
        implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
        implementation project(":lib")
        implementation ('mysql:mysql-connector-java')
    }
}

Both "lib" and "test-project" are built successfully. However, when I trying to execute "bootJar" task on root project (which supposed to trigger "build" task on all subprojects) I getting the following error:

Main class name has not been configured and it could not be resolved

Any ideas?

like image 903
Illidan Avatar asked Jan 10 '19 18:01

Illidan


People also ask

How do I run multiple main classes in spring boot?

Spring Boot allows us to define the Main class in the configuration when we have multiple main classes declared in the application. As we are using a MAVEN build, we have to configure the POM. xml for Spring Boot to identify the main class of the application. Voila!

How do I use Gradle project in spring boot?

When we apply the java plugin, the Spring Boot Gradle plugin takes multiple actions like: creating a bootJar task, which we can use to generate an executable jar file. creating a bootRun task, which we can use to run our application directly. disabling jar task.

Can Gradle be used with spring boot?

The Spring Boot Gradle Plugin provides Spring Boot support in Gradle. It allows you to package executable jar or war archives, run Spring Boot applications, and use the dependency management provided by spring-boot-dependencies . Spring Boot's Gradle plugin requires Gradle 6.8, 6.9, or 7.


1 Answers

An intro on multi-project build best practices

When you say:

I trying to follow Gradle best practices for multi project builds, and therefore I describing the whole build process in single build.gradle file.

I don't think this is actually is a good practice, and this is not what is really recommended inthe guide you mentioned.

In the guide intro:

While each subproject could configure itself in complete isolation of the other subprojects, it is common that subprojects share common traits. It is then usually preferable to share configurations among projects, so the same configuration affects several subprojects.

=> Indeed, common traits shared between subprojects should be configured in a central place in root project build.

Later in the guide (in this section ) there is a example with subprojects specific configuration defined in the root project script , but there is a note in the example description:

All the build logic is in the build script of the root project.(2)

(2): We do this here, as it makes the layout a bit easier. We usually put the project specific stuff into the build script of the respective projects.

Regarding your issue

I make assumption that your lib project is a plain "simple" java lib project (no Spring or SpringBoot dependencies), and test-project is the project containing the SpringBoot application classes (specially the @SpringBootApplication main application class). Following best practices described above, you should then have three distinct project build scripts:

  • root project: used to defined common configuration share in subproject (java plugin configuration, repositories, shared dependencies, etc...)
  • lib project : specific configuration for this lib project (java-library plugin, specific dependencies, ...)
    • there is no reason to apply spring-boot plugin to this sub-project, and this is actually the cause for your error "cannot find main class"
    • if this project has dependencies on Spring-core modules , you could simply apply the io.spring.dependency-management plugin (in this cas it would make sense to apply this dependecy plugin in the root project build, to use same Spring version in both subprojects)
  • test-projectproject: configuration related to Spring Boot application (SpringBoot plugin and dependencies)

Example

root project build

ext{
    slf4jVersion = "1.7.25"
}

subprojects {
    apply plugin: "java"
    // if both subprojects share some Spring related dependencies, apply the Spring `io.spring.dependency-management` here.

    group = 'com.xxx.yyy'
    version = '1.0'

    sourceCompatibility = 1.8
    targetCompatibility = 1.8

    repositories {
        jcenter()
    }
}

'lib' project build

plugins{
    id 'java-library'
}

dependencies {
    implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion
    // lib dependencies
}

'test-project' build

plugins {     
    id "org.springframework.boot"  version "2.1.1.RELEASE"
}
apply plugin: 'io.spring.dependency-management'

dependencies {
    implementation project(":lib")
    implementation('org.springframework.boot:spring-boot-starter-web')
    testImplementation('org.springframework.boot:spring-boot-starter-test')
    implementation ('mysql:mysql-connector-java')
    // ...
}

EDIT as per your comment: if lib project requires Spring Data related stuff, apply the io.spring.dependency-management as follows ( see more details in Spring reference guide)

plugins{
    id 'java-library'
    id "org.springframework.boot"  version "2.1.1.RELEASE" apply false
}
apply plugin: 'io.spring.dependency-management'

dependencyManagement {
    imports {
        mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
    }
}

dependencies {
    implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 
    // lib dependencies
}
like image 171
M.Ricciuti Avatar answered Oct 15 '22 04:10

M.Ricciuti