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
.
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.
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.
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?
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.
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
).
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.
No need for @EnableJpaRepositories
or @EntityScan
.
No need to declare anything in the main application.
Both the library and the app can declare their own repositories/entities independently.
Clean separation of concerns; the library is truly modular and plug-and-play.