I have Springboot multi module library project with Gradle 7.4 and Springboot 3.2 as below
buildscript {
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.21.0"
}
}
plugins {
id "com.diffplug.spotless" version "6.8.0"
id 'io.spring.dependency-management' version '1.1.4'
id 'org.springframework.boot' version '3.2.0' apply false
id "org.openapi.generator" version "6.0.0"
id "org.hidetake.swagger.generator" version "2.19.2"
}
ext.versions = [
springBoot : '3.2.0',
springCloud : '2022.0.4',
micrometer : '1.10.3',
commonLogging : '1.2',
]
allprojects {
apply plugin: 'io.spring.dependency-management'
group 'com.springboot.web.library'
version = '0.0.3-SNAPSHOT'
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:${versions.springBoot}")
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${versions.springCloud}")
}
dependencies {
//dependency group: 'io.micrometer', name: 'micrometer-registry-prometheus', version: versions.micrometer
dependency group: 'commons-logging', name: 'commons-logging', version: versions.commonLogging
}
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: "com.diffplug.spotless"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
withSourcesJar()
}
//https://dev.to/ankityadav33/standardize-code-formatting-with-spotless-2bdh
spotless {
java {
//googleJavaFormat("1.15.0")
target fileTree('.') {
include '**/*.java'
exclude '**/build/**', '**/build-*/**'
}
importOrder()
toggleOffOn()
palantirJavaFormat()
removeUnusedImports()
trimTrailingWhitespace()
endWithNewline()
}
}
afterEvaluate {
def spotless = tasks.findByName('spotlessApply')
if (spotless) {
tasks.withType(JavaCompile) {
finalizedBy(spotless)
}
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
}
repositories {
mavenLocal()
mavenCentral()
}
test {
useJUnitPlatform()
}
jar {
enabled = true
archiveClassifier=''
}
}
Below is my module-commons build.gradle file
plugins {
id 'java-library'
}
dependencies {
compileOnly 'com.fasterxml.jackson.core:jackson-databind:2.16.0'
compileOnly 'com.fasterxml.jackson.core:jackson-core:2.16.0'
compileOnly 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.0'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testImplementation 'org.mockito:mockito-core:5.8.0'
testImplementation 'org.projectlombok:lombok:1.18.30'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
compileOnly 'org.projectlombok:lombok:1.18.30'
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact jar
}
}
repositories {
mavenLocal()
}
}
I have the below class in module-commons
package com.springboot.web.library.commons.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonUtils {
public String serialize(Object object) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(object);
}
}
I am running the command gradle build jar module-commons:publishToMavenLocal
to publish the JAR to local maven repo.
I am importing the module-commons library in springboot-demo project as implementation 'com.springboot.web.library:module-commons:0.0.3-SNAPSHOT'
and below is the springboot-demo project build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.springboot.web'
version = '1.0-SNAPSHOT'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation 'org.projectlombok:lombok:1.18.28'
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'com.springboot.web.library:module-commons:0.0.3-SNAPSHOT'
}
test {
useJUnitPlatform()
}
I am importing JsonUtils
in springboot-demo project Main class as below
package com.springboot.web.library.commons;
import com.springboot.web.library.commons.utils.JsonUtils;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
@lombok.SneakyThrows
public static void main(String[] args) {
JsonUtils jsonUtils = new JsonUtils();
jsonUtils.serialize("test");
System.out.println("Hello world!");
}
}
While running the Main class am getting below compiler error since the module-commons
jar doesnt have maven.com.springboot.web.library.module-commons
directory with pom.xml inside META-INF
directory hence the Gradle is not resolving the jackson library thats referenced in module-commons
. I have tried many solutions thats available in Github and Stackoverflow but no luck so far. I appreciate if anyone can help resolve this issue.
Full project can be found here https://github.com/JavaSpringBooteer/springboot-gradle-library
D:\Git\springboot-gradle-library\springboot-demo\src\main\java\com\springboot\web\library\commons\Main.java:12: error: cannot access JsonProcessingException
jsonUtils.serialize("test");
^
class file for com.fasterxml.jackson.core.JsonProcessingException not found
Tried solutions from Github and Stackoverflow to tweak the build.gradle
Your project should be:
You need to modify your
module-commons
build script to include dependency information in the published artifact. That can be achieved by configuring themaven-publish
plugin correctly.Your
module-commons/build.gradle
would be:That would include the main Java component (
from components.java
), which makes sure the compiled classes and resources are part of the publication.And it adds a custom section to the generated POM file that lists all compile classpath dependencies.
Run the command
./gradlew module-commons:publishToMavenLocal
. After publishing the updatedmodule-commons
artifact to your local Maven repository, build and run yourspringboot-demo
project. It should now correctly resolve the dependencies.I suppose the
pom.withXml
block in yourbuild.gradle
is appending a new<dependencies>
node to the existing POM structure, which already has a<dependencies>
tag defined.Let's modify the
pom.withXml
block in themodule-commons/build.gradle
to handle existing<dependencies>
tags correctly.It is important to check if the
group
andversion
of a dependency are not null before appending them to avoid including invalid entries.Apply the updated script to your
module-commons/build.gradle
, and run./gradlew clean build
to make sure all changes are properly applied and old artifacts are cleared.Execute
./gradlew module-commons:publishToMavenLocal
. After publishing, check thepom.xml
in the local Maven repository to make sure it is correctly formed without duplicated tags.Run your
springboot-demo
project to check if the issue is resolved.As an alternative approach, instead of appending a new
<dependencies>
node or trying to find and enhance an existing one, you might consider clearing any existing<dependencies>
node and recreating it. That will make sure no duplication occurs.Your
module-commons/build.gradle
would be: