Not sure if this comes down to a question/bug report or enhancement, but I though the following worth creating an issue over. I'm currently working on an autoconfiguration-library for a large number of applications that are using the same scaffolding (JMS setup, same entities etc). This autoconfiguration-library is part of a release train of certain 'core' libraries in our environment. As part of this autoconfigure, we added an @EnableJpaRepositories annotation to one of the configuration classes so we can automatically register the repositories for the 'core' libraries.

When using this autoconfiguration-library in an actual application however (which has repositories of it's own in it's own, different than autoconfiguration, packages). The application itself is using the @SpringBootApplication annotation to identify the application. Normally, Spring Boot automatically registers any repository that is found in any (sub)package relative to the @SpringBootApplication annotation.

Having specified a @EnableJpaRepositories in the autoconfiguration-library however, this behaviour seems to be disabled. This leaves the application no choice but to also specify @EnableJpaRepositories, which then has the desired effect.

I had expected spring boot to take into account that if an @EnableJpaRepositories annotation is found, it still tries to setup repositories found under the default scan path. This doesn't appear to be the case however. I am wondering if this is desired behaviour, or if this is something that could at some point be added/corrected in spring boot?

Comment From: snicoll

Yes this is the expected behaviour. @EnableJpaRepositories isn't a Spring Boot thing so whenever you specify that in your configuration, you're asking this to be enabled (it's not called @EnableIfXyz). Adding the annotation means that you are taking control.

Perhaps the code of our auto-configuration would help.

Comment From: hawkeye-bot

While I understand the reasoning behind it and it makes sense from a Spring boot 'work with defaults' point of view, we're working in an environment where people are using Spring configuration from libraries on their classpath to reduce the workload & dependencies. This in turn results in unexpected behaviour, as these libraries use the @EnableJpaRepositories annotation.

Looking at alternatives, I can see that the org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfigureRegistrar contains the actual logic to active the @EnableJpaRepositories. It would be beneficial if we could simple leverage this class in our situations, since this will minimise the coupling on spring boot while achieving the desired functionality. However, this class seems to have default access level. I take it this is deliberate, any chance that this could be modified?

Comment From: philwebb

@hoeckxer We generally prefer to keep those import classes package-private whenever possible so I'm not keen to make it public.

Stepping back a bit, if I understand you correctly you have a shared library that declared JpaRepository interfaces (and possibly @Entity classes)? You want users to include a dependency on this library and get those beans defined automatically.

If I've understood that correctly, one option might be to use the AutoConfigurationPackages class. This class is used by JpaRepositoriesAutoConfigureRegistrar (and many others) as an indicator of what packages to scan. Normally this class is triggered by the @AutoConfigurationPackage, but you could easily call AutoConfigurationPackages.register yourself (say from an BeanFactoryPostProcessor).

Comment From: hawkeye-bot

Thanks @philwebb, the logic you're describing is an accurate description of the situation we are in. I can imagine that you don't want to expose this kind of internal mechanics of spring boot in public unless for a good reason.

The only thing that still tingles in the back of my mind with the solution suggested (which we could make work I'm sure) is that it takes more custom code 'on top' of spring boot, which is something we're trying to minimize to client-specifics. From a more general user perspective I can imagine that using multiple @EnableJpaRepositories alongside the default spring boot behaviour might be desirable.

The reason this is a more susceptable issue for our users is that it is hidden from them in the custom autoconfigure module. This means that their repositories works with the default spring boot behaviour, but sometimes doesn't (when a part of the custom autoconfigure starts using @EnableJpaRepositories itself). This results in somewhat unpredictable and unexpected behaviour to end users of our autoconfigure module.

Hope this gives a bit more insight into why this seems like unexpected behaviour for our users (granted, it is a result of our custom configuration)

Comment From: snicoll

Just to chime in because I already mentioned that and I am not sure that was taken into account. @EnableJpaRepositories is not a Spring Boot concept. You can't rely on that and expect at the same time that Boot's auto-configuration kicks in as you want. You need a way to tell boot to back off so using that annotation (that gives a clear signal you are in control) isn't the right call IMO.

Comment From: hawkeye-bot

Thanks for the response. I did read your initial point on that it is not Spring Boot functionality, I'm just mostly trying to point out that by actually activating the @EnableJpaRepositories behaviour from Spring Boot, users will expect Spring Boot to act a certain way even though they're not explicitly specifying it. On that vision, it would've been more clear to NOT trigger the @EnableJpaRepositories from Spring Boot in the first place at all, since it's not part of Spring Boot! :)

I'll look into the suggestion @philwebb made, since we'll probably have to look into scanning for repositories ourselves anyway it seems (I'm fine with that, merely trying to convey my personal expectation of Spring Boot's behaviour on this matter, which isn't necessarily how it should work :))

Comment From: odrotbohm

I've been brought here from this Spring Data ticket. The comment thread is a bit dated and it looks like what hasn't been able back in the days now already works.

tl;dr: it shouldn't be necessary to manually interact with the APIs for auto-configuration packages as the annotation based model supports adding packages to the overall bootstrap already.

You can find an example of this in the Salespoint repository, a TU Dresden project I am involved with. The repository contains a Boot based implementation of some simple e-commerce system, providing services, repositories, etc. The library is supposed to be used from the student's projects, which just include it as dependency. As those might live in a completely separate package, there's some glue configuration inside Salespoint that makes this possible:

  1. Salespoint ships an @EnableSalespoint annotation, that acts as replacement for @SpringBootApplication in the student's projects. It triggers component scanning and auto-configuration the the student's project's package space as they use it on their application class in their root package.
  2. @EnableSalespoint imports a configuration class (Salespoint) that lives in the root package of the library and is annotated with @EntityScan, @EnableAutoConfiguration. This will cause the root package of Salespoint to end up also to be scanned for components, entities, repositories, etc.

I forgot when exactly the feature of being able to register multiple packages for entity scanning and auto-configuration was added, but I remember the Boot team did so after careful consideration.

Comment From: netdragonboberb

Here's an example. I renamed classes

@SpringBootApplication(scanBasePackages = {"com.aaa.service.foo3","com.aaa.service.foo1", "com.aaa.service.foo2"})
@EnableEurekaClient
@EnableAspectJAutoProxy
@EntityScan(basePackages = {"com.aaa.service.foo1.domain", "com.aaa.service.foo2.domain"})
@EnableJpaRepositories(basePackages = {"com.aaa.service.foo1.data","com.aaa.service.foo2.data"})
@Import(KafkaConfig.class)

Comment From: snicoll

@netdragonboberb I don't know what example you're trying to report but a code snippet like this doesn't make one. If you believe you've found a bug in Spring Boot and continue to do so after reading this issue history, please create a new issue with a sample that reproduces the problem (that is a zip with the project attached to the issue or a link to a GitHub repository).