问题
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