spring-bootmavenspring-data-jpamulti-modulespring-boot-autoconfiguration

Spring Boot auto-configuration module disables app's own @Repository detection


I have a multi-module Maven project using Spring Boot 3.4.4 with the following structure:

my-project/
├── pom.xml
├── lib-model/
│   ├── pom.xml
│   ├── src/main/java/com/example/libmodel/
│   │   ├── Model.java
│   │   ├── ModelRepository.java
│   │   ├── ModelController.java
│   │   └── LibModelAutoConfiguration.java
│   └── src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
├── app-main/
│   ├── pom.xml
│   ├── src/main/java/com/example/app/
│   │   ├── AppMainApplication.java
│   │   ├── Other.java
│   │   ├── OtherRepository.java
│   │   └── OtherController.java
│   └── src/main/resources/application.properties

The library lib-model is intended to be plug-and-play, auto-configuring its own @Entity, @Repository, and @RestController. It uses Spring Boot’s auto-configuration mechanism:

// com.example.libmodel.LibModelAutoConfiguration
@Configuration
@EntityScan(basePackages = "com.example.libmodel")
@EnableJpaRepositories(basePackages = "com.example.libmodel")
public class LibModelAutoConfiguration {
}

And is declared in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:

com.example.libmodel.LibModelAutoConfiguration

The main app (app-main) has its own entities and repositories, all under com.example.app.

The Problem

When I add lib-model as a dependency, Spring Boot no longer detects the repositories in my application module:

Parameter 0 of constructor in com.example.app.OtherController required a bean of type 'com.example.app.OtherRepository' that could not be found.

If I manually add:

@EnableJpaRepositories(basePackages = "com.example.app")
@EntityScan(basePackages = "com.example.app")

...to the main application class, it works again — but I would like to avoid this, since it was working fine before adding the library.

What I Think Is Happening

It seems that @EnableJpaRepositories in the library's @Configuration class overrides Spring Boot's default behavior, preventing it from scanning the main application package for repositories.

But I want the library to only configure its own stuff, and not interfere with the application’s own configuration.

Desired Behavior

Question

Is there a way to isolate the @EnableJpaRepositories (and @EntityScan) in the library module so that it only applies to itself, and doesn’t break repository scanning in the main application?


Solution

  • Finally I solved this issue without using Spring Boot auto-configuration at all (and without needing to explicitly annotate the application with @EntityScan or @EnableJpaRepositories).

    I dropped the use of auto-configuration entirely and instead contributed the library’s base package to Spring Boot’s component scan manually.

    My Solution (No AutoConfiguration Involved)

    Step 1: I removed @EnableJpaRepositories, @EntityScan, and any *AutoConfiguration class in the library.

    I no longer needed this:

    @Configuration
    @EntityScan(...)
    @EnableJpaRepositories(...)
    public class LibModelAutoConfiguration { ... }
    

    or this:

    META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
    

    Step 2: I added a registrar that registers the library’s package for scanning.

    // com.example.libmodel.LibModelScanRegistrar
    public class LibModelScanRegistrar implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, "com.example.libmodel");
        }
    }
    

    Step 3: I registered the registrar via a plain @Configuration class.

    // com.example.libmodel.LibModelConfiguration
    @Configuration
    @Import(LibModelScanRegistrar.class)
    public class LibModelConfiguration {
    }
    

    Since this is a regular @Configuration class, it is picked up automatically if the app explicitly imports it or if a bean in the library causes it to be scanned (e.g. a @Component or @RestController).

    Why This Works

    Spring Boot uses AutoConfigurationPackages to determine the base packages for things like entity scanning and JPA repositories. By calling AutoConfigurationPackages.register(...), we add our library’s package to this list — rather than overriding it.

    Result