Spring Boot Packaging Failure: In-depth Analysis and Solution for META-INF/spring.factories Missing Issue

Dec 07, 2025 · Programming · 10 views · 7.8

Keywords: Spring Boot | Maven Plugin | Auto-configuration | JAR Packaging | META-INF/spring.factories

Abstract: This article provides a comprehensive analysis of common Spring Boot packaging failures, particularly the "Failed to process import candidates for configuration class" exception caused by missing META-INF/spring.factories files. Through a detailed case study, it explains the Spring Boot auto-configuration mechanism, compares maven-assembly-plugin with spring-boot-maven-plugin, and offers complete solutions and best practices. The discussion also covers the essential differences between HTML tags like <br> and character \n, helping developers fundamentally understand and avoid similar issues.

Problem Background and Phenomenon Analysis

In Spring Boot development practice, a common yet perplexing issue occurs when a project runs successfully within an IDE (such as IntelliJ IDEA) but fails to start after being packaged into an executable JAR via Maven. This article delves into the root cause of this problem through a representative case study.

The case project uses Spring Boot 1.4.0.RELEASE with @EnableAutoConfiguration annotation. When attempting to run the packaged JAR, the console outputs the following critical error:

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [el.dorado.App]; nested exception is java.lang.IllegalArgumentException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.

The stack trace clearly indicates that Spring Boot cannot locate auto-configuration classes in the META-INF/spring.factories file during startup, directly causing application context initialization failure.

Spring Boot Auto-configuration Mechanism Explained

To understand this issue, one must first grasp how Spring Boot's auto-configuration works. Spring Boot enables auto-configuration through the @EnableAutoConfiguration annotation, which triggers the execution of the EnableAutoConfigurationImportSelector class.

Here's a simplified version of the core logic:

public class EnableAutoConfigurationImportSelector {
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
            EnableAutoConfiguration.class, getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories.");
        return configurations;
    }
}

As shown in the code, the SpringFactoriesLoader.loadFactoryNames method loads configuration classes from META-INF/spring.factories files in all JARs on the classpath. If no configuration classes are found, it throws the exception we observed.

Root Cause: Packaging Tool Selection

The case project initially used maven-assembly-plugin for packaging with the following configuration:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>el.dorado.App</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
</plugin>

While maven-assembly-plugin can create dependency-inclusive JARs, it doesn't handle Spring Boot-specific resource files, particularly META-INF/spring.factories. This file typically resides in Spring Boot starter JARs and contains content like:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
...

When using the jar-with-dependencies descriptor, these critical resource files may be overwritten or lost, causing the auto-configuration mechanism to fail.

Solution: Using Spring Boot Maven Plugin

The correct solution is to use the official spring-boot-maven-plugin provided by Spring Boot. This plugin is specifically designed for Spring Boot applications and properly handles all necessary resources and configurations.

The updated pom.xml build configuration is as follows:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>
                <mainClass>dz.lab.jpmtask.App</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

The repackage goal of spring-boot-maven-plugin performs these critical operations:

  1. Preserves all classes and resources from the original JAR file
  2. Correctly merges META-INF/spring.factories files from all dependency JARs
  3. Creates an executable "fat JAR" with embedded Tomcat server (if using web starter)
  4. Sets up proper class loaders to ensure Spring Boot auto-configuration works correctly

Build and Verification Steps

With the updated configuration, the build and run steps are:

# Clean and package the project
mvn clean package

# Run the generated JAR file
java -jar target/ElDorado-1.0-SNAPSHOT.jar

If everything is configured correctly, the application should start normally, displaying Spring Boot startup logs instead of the previous exception.

Deep Understanding: Importance of HTML Escaping

In technical documentation, proper handling of special characters is crucial. For example, when discussing HTML tags, it's important to distinguish between tags as code examples and as textual content.

Consider these two scenarios:

# As code example (no escaping needed)
<p>This is a paragraph tag</p>

# As textual description (escaping required)
The article discusses the difference between HTML tag <br> and character \n.

In the second case, <br> is part of the textual content, not an HTML instruction. Without escaping, it would be parsed by browsers as a line break tag, disrupting document structure. The correct approach is to use HTML entities: &lt;br&gt;.

Similarly, in JSON output, all strings must be properly escaped. For instance, double quotes should be converted to \" and backslashes to \\ to ensure JSON parsers correctly understand the data structure.

Best Practices and Conclusion

Based on this analysis, we summarize the following best practices:

  1. Always Use Official Spring Boot Plugins: For Spring Boot projects, prioritize spring-boot-maven-plugin or corresponding Gradle plugins over generic packaging tools.
  2. Understand Auto-configuration Mechanism: Deeply comprehend the role of META-INF/spring.factories to help debug other auto-configuration related issues.
  3. Test Packaged Applications: Regularly test packaged JAR files during development to ensure they run correctly in production environments.
  4. Handle Special Characters Properly: Pay attention to HTML and JSON special character escaping when writing technical documentation and code to avoid parsing errors.

By adopting the right tools and understanding underlying mechanisms, developers can avoid common yet tricky packaging issues like "Failed to process import candidates for configuration class," ensuring Spring Boot applications run stably across different environments.

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.