Package not found when Spring Boot plugin applied

无人久伴 提交于 2021-02-10 18:30:42

问题


I have a multi-module project with the following build.gradel files

core:

repositories {
    mavenCentral()
}

dependencies {
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
}

test-module:

dependencies {
    implementation project(":core")
}

app:

repositories {
    mavenCentral()
}

dependencies {
    implementation project(":core")
    implementation project(":test")
}

springBoot{
    mainClassName = "com.yenovi.dev.Main"
}

and then the root :

buildscript {
    repositories {
        mavenCentral()
    }
}

plugins {
    id "io.spring.dependency-management" version "1.0.4.RELEASE"
    id 'org.springframework.boot' version '2.3.3.RELEASE'
    id 'war'
}

repositories {
    mavenCentral()
}

subprojects {
    apply plugin: 'java'
    apply plugin: 'war'
    apply plugin: 'idea'
    apply plugin: "io.spring.dependency-management"
    apply plugin: 'org.springframework.boot'

    sourceCompatibility = 11

    repositories {
        mavenCentral()
    }

    dependencies {
        compile 'org.springframework.boot:spring-boot-starter-web'
        testImplementation('org.springframework.boot:spring-boot-starter-test') {
            exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
        }
    }
}

The core module is supposed to represent the spring boot application, the test module provides extra functionality by creating a Service that is used in Core via dependency injection. The app module has a main class that calls SpringApplication.run(Core.class, args);. I that app seems useless but at the end, this module will be replaced by separate projects that will use modules from this project.

The problem is that this way the compilation of test fails with an error saying that the package from core can not be found. After some googling I've found that applying the spring boot plugin to all modules causes this issue because it disables the jar task. However without that plugin, the build fails with an error that says that the spring boot starter web dependency can not be found but I need that in all my modules so I can use stuff like the @Service annotation.

How could I solve this?


回答1:


In Gradle, if you don't specify a version number to the dependencies you use, they need to be supplied by something else. In your case, that something else is the io.spring.dependency-management plugin. However, it only knows about Spring Boot if you also have the org.springframework.boot plugin applied. So once you remove that, the dependency management plugin cannot supply versions for the dependencies anymore.

There are many ways to get around this. Here are the main ones I can think of. All are in Groovy DSL. I list each as a general case, so you will have to adapt it a bit for your project. More specifically, you should remove all plugins from the root (or set them to apply false) and add them to the relevant sub-projects instead. You also likely won't need the war and idea plugins.

(I personally prefer option B by the way.)

A. Use the Spring Dependency Management plugin in isolation

Have the Spring Boot plugin in the list, but don't apply it. This makes the plugin classes available on the project classpath so you can reference it. Then you can give the Spring Boot bom to the dependency management plugin:

plugins {
    id 'org.springframework.boot' version '2.4.0' apply false // <- Apply false
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
}

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


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

See more here.

B. Don't use the Spring Dependency Management plugin

One of the strength of this plugin is if you are migrating from Maven as it mirrors the dependency management rules. There are also a few other features. However, if you are not using those features and are not migrating from Maven, you don't need it. Just use normal Gradle semantics:

plugins {
    id 'org.springframework.boot' version '2.4.0' apply false // <- Apply false
    id 'java'
}

dependencies {
    implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
    implementation 'org.springframework.boot:spring-boot-starter'
}

// OR:

plugins {
    id 'java'
}

dependencies {
    implementation platform("org.springframework.boot:spring-boot-dependencies:2.4.0")
    implementation 'org.springframework.boot:spring-boot-starter'
}

C. Use both plugins, but disable the boot jar task.

The Spring Boot plugin disables the normal jar task, but you can just re-enable it. Because the jar file name is the same in both jar and bootJar, you can't have them both at the same time. So either also disable bootJar or give it a classifier. Here I have disabled it.

plugins {
    id 'org.springframework.boot' version '2.4.0' // <- Apply true
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
}

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

jar {
    enabled = true
}

bootJar {
    enabled = false
}

See more here.

I apologize for the long answer. I got carried away :)



来源:https://stackoverflow.com/questions/65066211/package-not-found-when-spring-boot-plugin-applied

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!