With the following gradle file within a multi project or multi module build, (lets call it web)
plugins {
id 'groovy'
id 'org.springframework.boot'
id 'io.spring.dependency-management'
}
dependencies {
implementation "org.codehaus.groovy:groovy:2.5.14"
implementation(project(':persistence'))
}
I'm unable to resolve the class files present in the project 'persistence' and get the following error while compiling
unable to resolve class XXX
This is the gradle file of the 'persistence' module
plugins {
id 'groovy'
id 'org.springframework.boot'
id 'io.spring.dependency-management'
}
dependencies {
implementation "org.codehaus.groovy:groovy:2.5.14"
}
What could be the problem?
Also, here is the settings.gradle and directory structure
// settings.gradle
pluginManagement {
plugins {
id 'org.springframework.boot' version "2.3.3.RELEASE"
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
}
}
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}
rootProject.name = 'gradle-bug'
include 'commons'
include 'persistence'
include 'security'
include 'web'
When gradle sees a "implementation" dependency on a project, it uses the jar of that dependency for compilation.
When you add the org.springframework.boot plugin, it by default disables the jar creation task for that module, but gradle continues to depend on that jar for its compilation, even though the classes of that module have been generated in the build/classes folder.
To fix this, you have to enable the jar creation by adding the following snippet to the persistence module
jar {
enabled = true
}
Related
I have root gradle project which needs to have a small Spring Boot subproject. This subproject will be deployed in the same pod as root project, so it needs to be built whenever root project is built. I tried by creating the following structure:
subproject/
├─ src/...
├─ build.gradle
settings.gradle
with the following contents:
settings.gradle:
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = 'root'
include 'subproject'
build.gradle:
plugins {
id 'org.springframework.boot' version '2.7.0'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.demo'
version = '1.0.0-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
But when I refresh the project from within the IDEA, it shows Task 'wrapper' not found in project ':subproject'. What did miss? This subproject cannot exist by itself and shouldn't have a 'wrapper', it should be build by the root project.
$ ./gradlew -q projects
Root project 'root'
+--- Project ':subproject'
Gradle version: 6.8.3, Java version: 11
The problem actually does not exist. Everything is correct, except that IDEA added subproject as separate gradle project (I guess). So when I hit refresh, it could not be performed because IDEA was trying to find wrapper in the subproject. Simply saying, if you have such problem, check how many projects you have in your IDEA's Gradle view. In my case, there was two - root and subproject, the latter is unneeded.
I've done web search for "plugin request for plugin already on the classpath must not include a version site:stackoverflow.com" and found nothing that particular. Search for "plugin request for plugin already on the classpath must not include a version" (w/out SO) found:
https://discuss.gradle.org/t/error-plugin-already-on-the-classpath-must-not-include-a-version/31814 where I've read in answers e.g.:
I didn’t find any reference to this use case in Grade plugins
documentation.
The error
Build file '/Users/username/github/OpCon/app/build.gradle'
line: 4 Error resolving plugin [id: 'com.android.application',
version: '3.4.1']
Plugin request for plugin already on the classpath must not include a version
appears in IntelliJ IDEA, build.gradle (OpCon):
buildscript {
repositories {
jcenter()
maven {
url 'https://maven.google.com/'
name 'Google'
}
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenCentral()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}
repositories {
jcenter()
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
app/build.gradle:
plugins {
id 'com.android.application' version '3.4.1' apply true
}
... and then other stuff
I don't understand, classpath 'com.android.tools.build:gradle:3.5.2' does not seem to include 'com.android.application'...
"classpath" has only one occurrence if searched in the project.
ADDED:
Interestingly on https://maven.google.com/web/index.html I can find 'com.android.tools.build:gradle:3.5.2' but no 'com.android.application' branch.
ADDED 2:
I've downloaded (quite many files actually was downloaded for some reason) by command taken from here How can I download a specific Maven artifact in one command line?:
mvn org.apache.maven.plugins:maven-dependency-plugin:2.8:get -DrepoUrl='https://maven.google.com/' -Dartifact='com.android.tools.build:gradle:3.4.1'
found path com.android.tools.build:gradle in file manager and looked inside only jar there:
username$ jar tvf /Users/username/.m2/repository/com/android/tools/build/gradle/3.4.1/gradle-3.4.1.jar | grep application
1115 Wed May 01 20:30:18 MSK 2019 com/android/build/gradle/internal/tasks/ApplicationIdWriterTask$applicationIdSupplier$1.class
55 Wed May 01 20:29:18 MSK 2019 META-INF/gradle-plugins/com.android.application.properties
So there is a mention gradle plugin com.android.application in jar META-INF.
File com.android.application.properties is one liner: implementation-class=com.android.build.gradle.AppPlugin.
Web search for "implementation class java" finds info on interfaces. In wiki https://en.wikipedia.org/wiki/Interface_(Java):
An interface in the Java programming language is an abstract type that
is used to specify a behavior that classes must implement.
So gradle plugin could be an interface? How can I dig in further?
Gradle doesn't allow multiple versions of a plugin to be present on the classpath. So if you have a multi module build, there could be a chance that more than one module has declared the same plugin with a different version.
To fix this, you will need to specify a single version in a single place i.e settings.gradle
For example, you will put the following in settings.gradle
pluginManagement {
plugins {
id 'org.springframework.boot' version "2.3.3.RELEASE"
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
}
}
And then in the individual module gradle files, you will do the following (no version mentioned)
plugins {
id 'org.springframework.boot'
id 'io.spring.dependency-management'
}
Just for the record, the error mentioned in the question may also show up with this message
plugin was loaded multiple times in different subprojects, which is
not supported and may break the build
I was facing same problem, I was using spring boot with plugins as follows
plugins {
id 'org.springframework.boot' version '2.2.0.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
id 'war'
}
Since this plugin was present in one dependency gradle was complaining about it. I simply removed those dependencies and it worked:
plugins {
id 'java'
id 'war'
}
Put configuration into build.gradle in the root project with apply false.
plugins {
id 'org.springframework.boot' version "2.5.1" apply false
id 'io.spring.dependency-management' version '1.0.11.RELEASE' apply false
}
Then you can just put it everywhere without the version
plugins {
id 'org.springframework.boot'
id 'io.spring.dependency-management'
}
More information:
->Example 3. Applying plugins only on certain subprojects
I am trying to build a Spring Boot/Gradle project and create a jar without a main class. My purpose is that this project is a library that will be pulled in by other projects therefore the library project does not require a main class to run. Unfortunately, no matter what kind of gradle config I write I keep getting errors when I try to build install about not having a main class or not being able to find the bootJar task.
Here's what my gradle file looks like:
plugins {
id 'org.springframework.boot' version '2.1.7.RELEASE' apply false
}
apply plugin: 'io.spring.dependency-management'
apply plugin: 'maven'
dependencyManagement {
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}
repositories {
mavenCentral()
}
jar {
enabled = true
}
bootJar.dependsOn fooTask
But when I run this I get the following error:
Could not get unknown property 'bootJar' for root project
'foo-library' of type org.gradle.api.Project.
What in my configuration needs to change?
Disable bootJar in your build.gradle
bootJar {
enabled = false
}
With Gradle it is possible to build a .war archive from a Java project. I've always been using a project setup as follows to pack some JavaScript SPA (Angular, vue.js...) frontend and a Spring Boot backend together into one .war file:
Directory structure
/
build.gradle
settings.gradle
/server
/build/libs/server.war
/src ...
build.gradle
/client
/dist/** <== This is where e.g. webpack puts the SPA build
build.gradle
/src ...
Topmost settings.gradle
include 'client', 'server'
'server' build.gradle
plugins {
id 'java'
id 'idea'
id 'org.springframework.boot' version '2.0.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.5.RELEASE'
id 'war'
}
repositories {
mavenCentral()
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
dependencies {
compileOnly('org.projectlombok:lombok:1.16.16')
annotationProcessor('org.projectlombok:lombok:1.16.16')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')
runtime('org.springframework.boot:spring-boot-devtools')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
war.dependsOn(':client:build')
war {
from '../client/dist/'
}
'client' build.gradle
plugins {
id 'com.nickcharles.yarn-run' version '1.0.1'
}
This is working just fine. But I can't imagine that this is the cleanest solution for that kind of task.
Backdraws of my solution are:
Final result of build is stored in build/libs of the :server subproject, not in the root project where it semantically belongs
The built client must be refered to in a static way.
How would a clean solution/the contents of the topmost build.gradle file look like, in order to avoid those backdraws?
I am trying to use Google checkstyle configuration (https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml) but I am constantly getting an error on gradle check:
Unable to create a Checker: cannot initialize module TreeWalker - Unable to instantiate EmptyCatchBlock
I used Gradle to build the project. Below is my gradle.build.
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'checkstyle'
sourceCompatibility = 1.8
version = '1.0'
checkstyle {
toolVersion = "6.3"
}
task "create-dirs" << {
sourceSets*.java.srcDirs*.each { it.mkdirs() }
sourceSets*.resources.srcDirs*.each { it.mkdirs() }
}
jar {
manifest {
attributes 'Implementation-Title': 'xyz',
'Implementation-Version': 0.01
}
}
repositories {
mavenCentral()
}
dependencies {
compile (
['org.apache.logging.log4j:log4j-api:2.2'],
['org.apache.logging.log4j:log4j-core:2.2']
)
testCompile(
['junit:junit:4.11'],
['org.mockito:mockito-core:1.+']
)
}
test {
systemProperties 'property': 'value'
}
uploadArchives {
repositories {
flatDir {
dirs 'repos'
}
}
}
Also, when I try to add XML config file to Checkstyle plugin in IDEA I get similar error but with a stack trace:
org.infernus.idea.checkstyle.exception.CheckStylePluginException: <html><b>The CheckStyle rules file could not be loaded.</b><br>cannot initialize module TreeWalker - Unable to instantiate EmptyCatchBlock</html>
at org.infernus.idea.checkstyle.checker.CheckerFactory.blacklistAndShowMessage(CheckerFactory.java:234)
at org.infernus.idea.checkstyle.checker.CheckerFactory.createChecker(CheckerFactory.java:188)
at org.infernus.idea.checkstyle.checker.CheckerFactory.getOrCreateCachedChecker(CheckerFactory.java:98)
at org.infernus.idea.checkstyle.checker.CheckerFactory.getChecker(CheckerFactory.java:73)
at org.infernus.idea.checkstyle.checker.CheckerFactory.getChecker(CheckerFactory.java:41)
I cannot figure out what am I doing wrong. Any help would be appreciated.
Gradle version: 2.2
You can add this configuration into your build.gradle file:
configurations {
checkstyleOverride
}
dependencies {
checkstyleOverride('com.puppycrawl.tools:checkstyle:6.11.2')
}
tasks.withType(Checkstyle) {
checkstyleClasspath = project.configurations.checkstyleOverride
}
Enjoy!
The problem lies in the fact that com.puppycrawl.tools.checkstyle.checks.blocks.EmptyCatchBlockCheck was indeed added to checkstyle but for version 6.4-SNAPSHOT. As it can be seen in checkstyle repository (pom.xml history) version 6.4-SNAPSHOT was introduced on the 02.02.2015 and EmptyCatchBlockCheck class was created on 18.02.2015.
Gradle still uses version 6.3 as in the following log extract:
:checkstyleMain
Download https://repo1.maven.org/maven2/com/puppycrawl/tools/checkstyle/6.3/checkstyle-6.3.pom
So there's simply no class You'd like to use.
According to the docs checkstyle classpath can be specified with checkstyleClasspath property - you can try to set it up manually.
I've also prepared a demo with 6.4-SNAPSHOT version, it can be found here. Checkstyle jar was built with mvn clean package with source taken from this repo.
Here is an approach that works with the (currently) latest versions of Gradle & Checkstyle (Gradle 6.1.1 & Checkstyle 8.29):
plugins {
id 'java'
id 'checkstyle'
}
configurations {
checkstyleConfig
}
dependencies {
checkstyleConfig("com.puppycrawl.tools:checkstyle:8.29") { transitive = false }
}
checkstyle {
toolVersion '8.29'
config = resources.text.fromArchiveEntry(configurations.checkstyleConfig, 'google_checks.xml')
}
Note that the Checkstyle dependency excludes transitive dependencies, otherwise the resources.text.fromArchiveEntry will fail since multiple JAR files will be present, and it will be unable to select a single one.