Best Practices for Using Spring Boot Executable JAR as a Dependency: Resolving ClassNotFoundException Issues

Dec 07, 2025 · Programming · 10 views · 7.8

Keywords: Spring Boot | Maven | JAR Dependency | ClassNotFoundException | Repackage Mechanism

Abstract: This article delves into the common ClassNotFoundException issue in Spring Boot applications, which often arises when using an executable JAR as a dependency due to its internal structure causing class loading failures. By analyzing the repackage mechanism of the Spring Boot Maven Plugin, we explain how the default configuration packages application classes and dependencies into BOOT-INF/classes and BOOT-INF/lib directories, respectively, making it unusable for direct referencing by other projects. The article details the solution of configuring the classifier parameter to generate two separate JAR files: one as a standard Maven artifact and another as an executable JAR. We provide Maven plugin configuration examples for different Spring Boot versions (1.x, 2.x, 3.x) and emphasize the importance of maintaining dependency compatibility in modular development. Additionally, the article discusses the fundamental differences between HTML tags like <br> and characters like \n to help developers better understand formatting in technical documentation.

Problem Background and Root Cause

In Spring Boot development, developers often need to package a module as a JAR file and use it as a dependency in other projects. However, when attempting to invoke methods from this JAR, a ClassNotFoundException exception may occur. The root cause of this issue lies in the default packaging behavior of the Spring Boot Maven Plugin.

Analysis of Spring Boot's Repackage Mechanism

Spring Boot uses the spring-boot-maven-plugin to repackage the standard Maven-built JAR into a "fat JAR" or "executable JAR." This process places the application's class files in the BOOT-INF/classes directory, while all dependency libraries are consolidated into the BOOT-INF/lib directory. This structure allows the JAR to run as a standalone application but also disrupts its standard Maven structure as a dependency library.

As quoted from technical documentation: "Application classes are packaged in BOOT-INF/classes so that the dependent module cannot load a repackaged jar's classes." This means that when other projects try to reference this executable JAR, the class loader cannot find the class files in the expected locations, leading to ClassNotFoundException.

Solution: Using the Classifier Configuration

To address this issue, the Spring Boot Maven Plugin provides a classifier configuration option. By setting classifier in the repackage goal, the plugin generates two JAR files: one maintains the standard Maven structure for dependency referencing, and another with the classifier appended (e.g., exec) as the executable JAR.

Here is a basic configuration example for Spring Boot 1.4.1:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <version>1.4.1.RELEASE</version>
  <executions>
    <execution>
      <goals>
        <goal>repackage</goal>
      </goals>
      <configuration>
        <classifier>exec</classifier>
      </configuration>
    </execution>
  </executions>
</plugin>

With this configuration, the Maven build produces two artifacts: the main artifact (e.g., myapp.jar) and the classified artifact (e.g., myapp-exec.jar). The main artifact retains the standard classpath structure and can be safely referenced as a dependency by other projects.

Configuration Differences Across Spring Boot Versions

As Spring Boot evolves, the plugin configuration methods have also changed. Here are key points for major versions:

Developers should adjust configurations based on the Spring Boot version used in their project, referring to official documentation. For instance, in Spring Boot 2.x, the configuration might look like:

<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>

Practical Recommendations and Considerations

When implementing this solution, developers should consider the following points:

  1. Dependency Management: Ensure that the dependencies of the main JAR are correctly resolved in the referencing project. Use Maven's dependency transitivity mechanism to avoid version conflicts.
  2. Testing Validation: After including the JAR as a dependency in other projects, run unit or integration tests to confirm no ClassNotFoundException or other class-loading issues.
  3. Documentation: Document the dual purpose of the JAR in project documentation to help team members understand the build artifact structure.
  4. Continuous Integration: In CI/CD pipelines, verify that build artifacts meet expectations, such as checking if two JAR files are generated.

Additionally, the article discusses the fundamental differences between HTML tags like <br> and characters like \n, emphasizing that in technical documentation, when describing tags as text objects, HTML escaping is necessary to prevent parsing errors. For example, in code samples, the string print("<T>") should be escaped as print("&lt;T&gt;") to ensure the DOM structure is not disrupted.

Conclusion

By configuring the classifier parameter of the Spring Boot Maven Plugin, developers can easily resolve ClassNotFoundException issues when using executable JARs as dependencies. This approach maintains the JAR's executability while ensuring its compatibility as a dependency library. In practical development, combining version-specific configurations and best practices can effectively enhance the maintainability and reliability of modular projects. For more complex scenarios, such as multi-module projects or custom packaging needs, it is recommended to refer to the Spring Boot official documentation for more detailed guidance.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.