Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileNotFoundException when loading a custom auto configuration with spring.factories

UPDATE: I have the same error if I simply add the extension project as a dependency of master.

UPDATE 2: I created a Github repo to reproduce the error: https://github.com/papagno/spring-factories-test


I am experimenting with Spring Boot and the spring.factories file. So I created two simple projects:

  • Master:
    • This is a Spring Boot application (1.4.3) with starter-web and starter-actuator as dependencies.
    • I also added <layout>ZIP</layout> as a configuration for spring-boot-maven-plugin.
  • Extension

    • This is a simple Spring Boot application (1.4.3) with only spring-boot-starter as a dependency.
    • It contains the following spring.factories file in resources/META-INF: org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ my.package.extension.ExtensionAutoConfiguration
    • It also contains the my.package.ExtensionAutoConfiguration class that is annotated with only @Configuration and declares a @Bean:

      package my.package.extension;
      
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      @Configuration
      public class ExtensionAutoConfiguration
      {
          @Bean
          ExtensionService extensionService()
          {
              return new ExtensionService();
          }
      }
      

I compile both projects with maven, put both jars in the same folder and then run master with the following command: java -Dloader.path=. -jar master-0.0.1-SNAPSHOT.jar

The spring.factories is recognized but when Spring tries to instantiate my auto configuration class I get the FileNotFoundException for that class.

This is the stacktrace:

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [my.package.master.MasterApplication]; nested exception is java.lang.IllegalStateException: java.io.FileNotFoundException: class path resource [my/package/extension/ExtensionAutoConfiguration.class] cannot be opened because it does not exist
    at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:482) ~[spring-context-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:184) ~[spring-context-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308) ~[spring-context-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228) ~[spring-context-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686) ~[spring-context-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524) ~[spring-context-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761) [spring-boot-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:371) [spring-boot-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1186) [spring-boot-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1175) [spring-boot-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at my.package.master.MasterApplication.main(MasterApplication.java:10) [classes!/:0.0.1-SNAPSHOT]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_101]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) [master-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) [master-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) [master-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:521) [master-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: java.lang.IllegalStateException: java.io.FileNotFoundException: class path resource [my/package/extension/ExtensionAutoConfiguration.class] cannot be opened because it does not exist
    at org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector.selectImports(EnableAutoConfigurationImportSelector.java:94) ~[spring-boot-autoconfigure-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:474) ~[spring-context-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    ... 22 common frames omitted
Caused by: java.io.FileNotFoundException: class path resource [my/package/extension/ExtensionAutoConfiguration.class] cannot be opened because it does not exist
    at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172) ~[spring-core-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:50) ~[spring-core-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:98) ~[spring-core-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:89) ~[spring-boot-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:76) ~[spring-boot-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:93) ~[spring-core-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
    at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClasses.<init>(AutoConfigurationSorter.java:110) ~[spring-boot-autoconfigure-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.boot.autoconfigure.AutoConfigurationSorter.getInPriorityOrder(AutoConfigurationSorter.java:54) ~[spring-boot-autoconfigure-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector.sort(EnableAutoConfigurationImportSelector.java:193) ~[spring-boot-autoconfigure-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    at org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector.selectImports(EnableAutoConfigurationImportSelector.java:89) ~[spring-boot-autoconfigure-1.4.3.RELEASE.jar!/:1.4.3.RELEASE]
    ... 23 common frames omitted

Am I doing something wrong? What can I do to understand what is happening? Thank you.

like image 349
Francesco Papagno Avatar asked Oct 25 '25 21:10

Francesco Papagno


1 Answers

Your extension must not be a Spring Boot Application (no parent spring-boot-starter-parent).

When you declare spring-boot-starter-parent as parent, the jar produced is repackaged with a Sring-Boot flavor and the classes are not in the expected folders. If you open extension-0.0.1-SNAPSHOT.jar, the classes are in BOOT-INF/classes, so when the jar is used as library, no classes are found. The classes need to be at the root inside the jar.

Use the following pom.xml for Extension project:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>extension</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>extension</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>1.4.3.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.example</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

In the code sample above, I still declared the spring-boot-starter-parent as dependencyManagement - import, so the version declarations are inherited. However, the spring-boot-maven-plugin will not be executed, the jar will not be repackaged and it will be usable as library.

like image 79
alexbt Avatar answered Oct 27 '25 15:10

alexbt