Intellij/Gradle/Spring Boot - slf4j not available on classpath - spring-boot

I have used maven earlier (and am a beginner with gradle). When I generate Spring Boot Project with maven as build tool using springinitializer, i could use slf4j library out of box. But with Gradle this does not seem to be the case.
Plz see below screenshot of gradle based project and build.gradle file. Plz suggest me what additional stuff i need to do to use slf4j in my project.
Clearly you can see in below screenshot that both org.slf4j.Logger and org.slf4j.LoggerFactory are in external libraries and hence should be usable by the app.
build.gradle file -
plugins {
id 'org.springframework.boot' version '2.7.2'
id 'io.spring.dependency-management' version '1.0.12.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.liquibase:liquibase-core'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
Further - i am curious why spring initialiser is adding lombok twice
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
Edit following - Deinum comment. Intellij is suggesting other logger(as can be seen in below screenshot), then why would it have issue with slf4j alone.. its quite difficult to understand and fix.
EDIT -2
gradle seems to be fine providing slf4* to app --
$ ./gradlew dependencies --configuration compileClasspath | grep slf
| | | | \--- org.slf4j:slf4j-api:1.7.32 -> 1.7.36
| | | +--- org.apache.logging.log4j:log4j-to-slf4j:2.17.2
| | | | +--- org.slf4j:slf4j-api:1.7.35 -> 1.7.36
| | | \--- org.slf4j:jul-to-slf4j:1.7.36
| | | \--- org.slf4j:slf4j-api:1.7.36
| | | \--- org.slf4j:slf4j-api:1.7.30 -> 1.7.36
| | | \--- org.slf4j:slf4j-api:1.7.32 -> 1.7.36
| | \--- org.slf4j:slf4j-api:1.7.32 -> 1.7.36
| +--- org.slf4j:slf4j-api:1.7.28 -> 1.7.36

Related

gradle multi project build query - exclude compile based on env

I'm using gradle-7.2 with multi-project build feature, where my main service consists of multiple sub modules where i've defined structure like this:
MYSERVICE
----abc-api
|
---build.gradle
----abc-impl
|
---build.gradle
----xyz-api
|
---build.gradle
----xys-impl
|
---build.gradle
lib
<<all libs used by service extracted from subprojects compile/runtime classpath and placed here>>
bin
<<service startups scripts reside here>>
conf
<<service configuration files reside here>>
settings.gradle
build.gradle
settings.gradle
rootProject.name = 'MYSERVICE'
include 'abc-api'
include 'xyz-api'
include 'abc-impl'
include 'xyz-impl'
build.gradle
apply plugin: 'java'
apply plugin: 'application'
subprojects {
task allDeps(type: DependencyReportTask) {}
}
configurations {
runtimeClasspath.transitive = false
}
dependencies {
/**
* some additional runtime libs used by those subprojects
*/
/** deps needed for spring framework **/
runtimeOnly "com.partygaming.thirdparty:aopalliance:1.0"
runtimeOnly "com.partygaming.thirdparty:spring-aop:5.3.22"
runtimeOnly "com.partygaming.thirdparty:spring-tx:5.3.22"
runtimeOnly "com.partygaming.thirdparty:spring-expression:5.3.22"
runtimeOnly "com.partygaming.thirdparty:osgi.core:8.0.0"
runtimeOnly "com.partygaming.thirdparty:disruptor:3.4.4"
runtimeOnly "com.partygaming.thirdparty:commons-beanutils:1.9.4"
runtimeOnly "com.partygaming.thirdparty:commons-io:2.11.0"
runtimeOnly "com.partygaming.thirdparty:commons-logging:1.2"
runtimeOnly "com.partygaming.thirdparty:guava:31.1-jre"
runtimeOnly "com.partygaming.thirdparty:jakarta.activation-api:1.2.2"
runtimeOnly "com.partygaming.thirdparty:objenesis:3.3"
runtimeOnly "com.partygaming.thirdparty:jakarta.xml.bind-api:2.3.3"
runtimeOnly "com.partygaming.thirdparty:jaxb-impl:2.3.6"
}
task getFlatDependencies(type: Copy) {
from {
subprojects.findAll { it.getSubprojects().isEmpty() }
.collect { it.configurations.runtimeClasspath + it.configurations.compileClasspath }
}
into 'lib'
from configurations.runtimeClasspath
into 'lib'
exclude "sourceanalyzer-1.0.jar"
}
build.dependsOn(getFlatDependencies)
All this works fine, but i want to do one additional improvement here. When i run gradle build at service level, its compiling all the sub projects and preparing lib.
I want to avoid this compilation stuff in case of QA environment (i download jars from artifactory for QA env) but needed for local environment setup.
How can i achieve this?

Gradle sub projects won't compile with dependencies on sub-projects

I have following project structure with gradle 6.8.3 version and spring-boot 2.4.3
Project-A
|
|___ Project B
|
|___ Project C
Project A being root project and project B is being dependent on project C.
Project C build.gradle
plugins {
id 'org.springframework.boot' version '2.4.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'maven'
}
group = 'com.test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.springframework.boot:spring-boot-starter-logging'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
Project B build.gradle file
plugins {
id 'org.springframework.boot' version '2.4.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'maven'
}
group = 'com.test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation project(':PROJECT-C')
implementation 'org.springframework.boot:spring-boot-starter'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.springframework.boot:spring-boot-starter-logging'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'project-c:0.0.0-SNAPSHOT'
}
test {
useJUnitPlatform()
}
When trying to build project-c it throws
Following are the details for more information.
JDK11
IntelliJ Idea
Error thrown
What went wrong:
A problem occurred evaluating root project 'project-c'.
Project with path ':project-b' could not be found in root project 'project-c'.
Any help is highly appreciated.
settings.gradle file at root level
rootProject.name = 'Project-A'
include 'Project-B', 'Project-C'
Also I have a settings.gradle file in all sub modules also. Content of settings.gradle in sub modules contains only name of the project
Assuming that your setup in the settings.gradle file is correct:
In your dependencies block in project B build.gradle file, instead of
implementation project(':PROJECT-C')
try
implementation project(':Project-A:Project-C')
as project a is the root project.
In my case I had a rouge settings.gradle inside one of the child project dir 🤦‍♂️ and it managed to waste couple of my hours. 😔

How can I add dependencies to kotlinCompilerClasspath?

I am using the kotlin-gradle-plugin, configuring it as follows in build.gradle:
buildscript {
ext {
springBootVersion = '2.1.2.RELEASE'
kotlinVersion = '1.3.11'
}
repositories {
mavenLocal()
mavenCentral()
maven { url "http://repo.spring.io/plugins-release" }
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
classpath "org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}"
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
When I run gradle dependencies I get the following kotlinCompilerClasspath among other things:
kotlinCompilerClasspath
\--- org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.11
+--- org.jetbrains.kotlin:kotlin-stdlib:1.3.11
| +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.11
| \--- org.jetbrains:annotations:13.0
+--- org.jetbrains.kotlin:kotlin-script-runtime:1.3.11
\--- org.jetbrains.kotlin:kotlin-reflect:1.3.11
\--- org.jetbrains.kotlin:kotlin-stdlib:1.3.11 (*)
When I disabled transitive dependencies in my build.gradle as follows:
configurations {
all {
transitive = false
resolutionStrategy {
// fail eagerly on version conflict (includes transitive dependencies)
// e.g. multiple different versions of the same dependency (group and name are equal)
failOnVersionConflict()
}
}
}
Now when I run gradle dependencies I get the following kotlinCompilerClasspath
kotlinCompilerClasspath
\--- org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.11
How can I add dependencies to the above kotlinCompilerClasspath while still using transitive = false configuration?
For example, I have tried adding the dependency org.jetbrains.kotlin:kotlin-stdlib to the regular dependencies block and to the buildscript block but still the above kotlinCompilerClasspath does not change.
Gradle version
gradle --version
------------------------------------------------------------
Gradle 5.1.1
------------------------------------------------------------
Build time: 2019-01-10 23:05:02 UTC
Revision: 3c9abb645fb83932c44e8610642393ad62116807
Kotlin DSL: 1.1.1
Kotlin: 1.3.11
Groovy: 2.5.4
Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM: 1.8.0_191 (Oracle Corporation 25.191-b12)
OS: Mac OS X 10.14.2 x86_64
UPDATE
As recommended by hotkey below, I filtered out kotlin from the configuration, as follows.
configurations {
matching { !it.name.toLowerCase().contains('kotlin') }.all {
transitive = false
resolutionStrategy {
// fail eagerly on version conflict (includes transitive dependencies)
// e.g. multiple different versions of the same dependency (group and name are equal)
failOnVersionConflict()
}
}
}
I would recommend not to disable transitive dependencies for the kotlinCompilerClasspath configuration in the first place, the Kotlin Gradle plugin expects that configuration to pull the transitive dependencies of the Kotlin compiler as well:
configurations {
matching { it.name != 'kotlinCompilerClasspath' }.all {
transitive = false
/* ... */
}
}
If you still want to disable transitive dependencies for all configurations, you can instead manually add those dependencies which were reported as transitive for the kotlin-compiler-embeddable module:
dependencies {
kotlinCompilerClasspath 'org.jetbrains.kotlin:kotlin-stdlib'
kotlinCompilerClasspath 'org.jetbrains.kotlin:kotlin-script-runtime'
kotlinCompilerClasspath 'org.jetbrains.kotlin:kotlin-reflect'
kotlinCompilerClasspath 'org.jetbrains:annotations:13.0'
}

Standalone Kotlin Gradle plugin not found when trying to apply to other project

I'm trying to make a custom standalone Kotlin plugin for Gradle and am trying to apply that to another project, but am getting a Plugin with id 'my.id.license-tools' not found error when trying to apply it to another project.
This is the structure of the plugin's project:
license-tools
+--src
+--main
| +--java
| |
| +--kotlin
| | +--my.id
| | +--LicenseTools.kt
| |
| +--resources
| +--META-INF.gradle-plugins
| +--my.id.license-tools.properties
+--test
+--build.gradle
This is my build.gradle file:
buildscript {
ext.kotlin_version = '1.2.21'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
group 'my.id'
version '0.1'
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'maven'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
compile gradleApi()
testCompile group: 'junit', name: 'junit', version: '4.12'
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
Then we have the Plugin class LicenseTools.kt, which I've held very simple to make sure the error didn't come from there:
package my.id
import org.gradle.api.Plugin
import org.gradle.api.Project
open class LicenseTools: Plugin<Project> {
override fun apply(project: Project?) {
println("License-Tools plugin has been applied")
}
}
And lastly my.id.license-tools.properties:
implementation-class=my.id.LicenseToolsKt
I've also tried
implementation-class=my.id.LicenseTools
After building everything with ./gradlew clean build I've run ./gradlew install to install the whole thing to the local Maven repository, which it did successfully.
Then I went ahead and added the following to my other project's buildscript block:
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "my.id:license-tools:0.1"
}
And after that added
apply plugin: 'my.id.license-tools'
After trying out many different things, like changing to the new plugins block or making sure the artifacts get correctly installed to the local maven repository I can't find the root of the problem, since according to the many guides I've read through, this should be the correct way to go about making a standalone plugin.
you probably figured by now, but your my.id.license-tools.properties should be named my.id.properties
the content should then be implementation-class=my.id.LicenseTools
then the classpath should be named
classpath "my.id:license-tools:0.1" -> classpath "my.id:LicenseTools:0.1"
and
apply plugin: 'my.id.license-tools' -> apply plugin: 'my.id.LicenseTools'
so that it always is:
package: my.id
name: LicenseTools
I haven't actually tested all of that, though.

Spring-boot app with unkown #PastOrPresent annotation

in spring-boot web-app,
when i use #PastOrPresent STS shows me this error :
(PastOrPresent cannot be resolved to a type)
but org.springframework.boot:spring-boot-starter-validation entry is already among the dependencies.
Gradle file
buildscript {
ext {
springBootVersion = '1.5.9.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
group = 'com.domain'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
compileJava.options.encoding = "UTF-8"
compileTestJava.options.encoding = "UTF-8"
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-actuator-docs')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-validation')
compile('org.springframework.boot:spring-boot-starter-web')
runtime('org.springframework.boot:spring-boot-devtools')
runtime('org.postgresql:postgresql')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.security:spring-security-test')
}
UPDATE of Gradle file
...
compile('org.springframework.boot:spring-boot-starter-validation'){
exclude group: 'org.hibernate', module: 'hibernate-validator:5.3.6.Final'
}
compile 'org.hibernate:hibernate-validator:6.0.7.Final'
...
| \--- org.hibernate:hibernate-validator:5.3.6.Final -> 6.0.7.Final
| \--- org.hibernate.validator:hibernate-validator:6.0.7.Final
| +--- javax.validation:validation-api:2.0.1.Final -> 1.1.0.Final
| +--- org.jboss.logging:jboss-logging:3.3.0.Final -> 3.3.1.Final
| \--- com.fasterxml:classmate:1.3.1 -> 1.3.4
have i some thing else to do ? while inside the entity i still have the same error. with new one : The type NotEmpty is deprecated (as shows the doc here)
The problem is that #PastOrPresent constraint is a part of Bean Validation 2.0 (see here), while the Spring Boot is still using Hibernate Validator 5.3 by default (see the dependencies here), which is BeanValidation 1.1. If you'd like to use this new constraint you would need to have an explicit dependency for Hibernate Validator 6.0 and exclude 5.4 version from your current dependencies.

Resources