Use Spring Boot Project as a Dependency
In this article, we will learn how to build a Spring Boot JAR as a library and use it as a dependency in other applications.
Overview
By default, Spring Boot use repackage goal to build an executable standalone Fat JAR:-
💼springboot-demo-0.0.1-SNAPSHOT.jar
📁 BOOT-INF
📂 classes
📄 ...compiled classes
📄 application.yml
📂 lib
📄 spring-boot-2.5.0.jar
📄 spring-core-5.3.7.jar
📄 ...other dependencies
📁 META-INF
📁 org
This FAT JAR has compiled classes in BOOT-INF/classes
and the dependent libraries in BOOT-INF/lib
location, which is very specific to Spring boot to execute it as a standalone application.
When you add this Fat JAR as a dependency in other applications and try to use its classes and methods, then it throws ClassNotFoundException
. It is because dependent modules are not able to load classes from these specific locations. You need a traditional library JAR for that.
Build Spring Boot JAR as a dependency
Maven
If you want to use Spring Boot JAR as a library and using Maven as dependency management then you need to overwrite the default Spring boot repackage goal behavior by adding a classifier in the spring-boot-maven-plugin
execution configuration in pom.xml as below:-
Spring Boot 1.x
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.20.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
...
</plugin>
Spring Boot 2.x
If you are using Spring Boot 2.x and spring-boot-starter-parent
, then it is essential to add execution id i.e. <id>repackage</id>
to overwrite the repackage goal default behavior in pom.xml as below:-
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
...
</plugin>
The above configurations build two JARs in the maven .m2 repository as follows:-
📁 .m2\repository\com\example\springboot-demo\0.0.1-SNAPSHOT
📄_remote.repositories
📄maven-metadata-local.xml
💼springboot-demo-0.0.1-SNAPSHOT.jar
📄springboot-demo-0.0.1-SNAPSHOT.pom
💼springboot-demo-0.0.1-SNAPSHOT-exec.jar
Where,
springboot-demo-0.0.1-SNAPSHOT.jar
is a Standard JAR that can be used as a dependent libraryspringboot-demo-0.0.1-SNAPSHOT-exec.jar
is a Fat JAR that can be used as a standalone executable
Please note the -exec suffix appended in the executable JAR name, which comes from <classifier>exec</classifier>
. You can provide any name in the classifier.
Only Dependent JAR
If the Spring Boot project is meant to be used as a dependent library only and it doesn’t have any Main class to be used as an application then it makes more sense to generate the standard JAR only and skip the repackaging to FAT JAR like this:-
Spring Boot 2.x (pom.xml)
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
The above configuration builds only dependency JAR as follows:-
📁 .m2\repository\com\example\springboot-demo\0.0.1-SNAPSHOT
📄_remote.repositories
📄maven-metadata-local.xml
💼springboot-demo-0.0.1-SNAPSHOT.jar
📄springboot-demo-0.0.1-SNAPSHOT.pom
Gradle
If you want to use Spring Boot JAR as a library and using Gradle as dependency management then follow this:-
Spring Boot 1.x
If you are using Spring Boot 1.x then use following Gradle configuration in build.gradle to build both standard and executable JARs:-
bootRepackage {
classifier = 'exec'
}
Disable bootRepackage
task to generate only Standard JAR without executable Fat JAR:-
bootRepackage {
enabled = false
}
Spring Boot 2.x
If you are using Spring Boot 2.x then you need to apply java
plugin with,
- Gradle
bootJar
task to build the executable Fat JAR - Gradle
jar
task to build the Standard JAR
Add following Gradle plugin configuration in build.gradle to generate both JARs:-
apply plugin: 'java'
tasks.named("bootJar") {
archiveClassifier = 'exec'
enabled = true
}
tasks.named("jar") {
archiveClassifier = ''
enabled = true
}
Gradle build generate below two JARs with above configuration:-
📁 springboot-demo\build\libs
💼springboot-demo-0.0.1-SNAPSHOT.jar
💼springboot-demo-0.0.1-SNAPSHOT-exec.jar
Only Dependent JAR
Use following Gradle plugin configuration if you want to generate only Standard JAR without executable Fat JAR:-
apply plugin: 'java'
tasks.named("bootJar") {
enabled = false
}
tasks.named("jar") {
enabled = true
}
Only Executable JAR
Use following Gradle plugin configuration if you want to generate only Executable Fat JAR without standard JAR:-
apply plugin: 'java'
tasks.named("bootJar") {
enabled = true
}
tasks.named("jar") {
enabled = false
}
Conclusion
We learned how to build a plain standard JAR from Spring Boot Project, which can be used as a library and can be added as a dependency in other applications. We also learned the internal structure of the standalone executable JAR, which is built by the Spring Boot project by default, whether you use Maven or Gradle as dependency management. We can either generate both Standard and Executable JAR or disable one of them from the Maven pom.xml and Gradle build.gradle configurations.
Thanks for reading!