Use Spring Boot Project as a Dependency Use Spring Boot Project as a Dependency

Page content

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 library
  • springboot-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!