Skip to content

@ComponentScan in application class overrides default excludeFilters specified in @SpringBootApplication #10933

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ccronemberger opened this issue Nov 6, 2017 · 11 comments
Assignees
Labels
type: documentation A documentation update
Milestone

Comments

@ccronemberger
Copy link

ccronemberger commented Nov 6, 2017

This enhancement idea is based on the findings after this question in Stack Overflow:

https://stackoverflow.com/questions/47054716/componentscan-in-application-class-breaks-webmvctest-and-springboottest

For me it was not obvious that when adding @ComponentScan in the application class it would override the defaults set by @SpringBootApplication (mainly the defaults set for excludeFilters).

I think there are multiple possibilities to make this clearer:

  1. When Spring Boot finds a @ComponentScan in the application class and it does not have the two default exclude filters (TypeExcludeFilter and AutoConfigurationExcludeFilter) it should throw an exception. An attribute could also be added to @SpringBootApplication to let the developer bypass this check if desired.

  2. Would it make sense to simply deny the use of @ComponentScan in the application class?

  3. Spring Boot could automatically consider the two default filters even if they are not specified in the @ComponentScan annotation when it is in the application class.

  4. Would it make sense to move the default exclude filters from the @SpringBootApplication annotation to the @ComponentScann annotation?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 6, 2017
@snicoll
Copy link
Member

snicoll commented Nov 6, 2017

Your finding is not fully complete, actually. It's not about the exclude not being added, it's about you having an opinion as which packages should be scanned on the source of the context for the test. This section of the 2.0 documentation provides more details.

With that in mind, I don't think that we should change anything.

@ccronemberger
Copy link
Author

ccronemberger commented Nov 6, 2017

Well, in fact the documentation that you pointed also does not cover the complete picture as well when it says: "This effectively overrides the default component scan directive with the side effect of scanning those two packages regardless of the slice that you chose.". It gives the impression that scanning both packages is the only side effect.

In the case of Stack Overflow question, the package scan is the same for both cases and the reason for adding ComponentScan was to effectively add a custom excludeFilter. Without the default excludeFilters specified in the SpringBootApplication annotation the filter TestTypeExcludeFilter will not be used in the tests and this is what caused the problem and not the fact that it was scanning other things.

@snicoll
Copy link
Member

snicoll commented Nov 6, 2017

It gives the impression that scanning both packages is the only side effect.

In the context of that section, this is the only side effect. If you think there is a phrasing that would be more complete/accurate, I am happy to review a PR.

This is what caused the problem and not the fact that it was scanning other things.

It doesn't matter what packages you scan. If you put it in your @SpringBootApplication class you are providing a hard-coded opinion. If you can move it to a separate @Configuration class, then the doc covers exactly that use case.

If you can't, please share more details, perhaps we can improve that then.

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Nov 6, 2017
@ccronemberger
Copy link
Author

ccronemberger commented Nov 6, 2017

@SpringBootApplication has an internal @CompoentScan on its declaration where there are two exclude filters (TypeExcludeFilter and AutoConfigurationExcludeFilter).

If you specify a @ComponentScan on the class annotated with @SpringBootApplication those two default exclude filters will be overwritten by whatever is in the new @ComponentScan annotation.

If TypeExcludeFilter is missing it will break the tests. I am not sure about what may go wrong when AutoConfigurationExcludeFilter is missing.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 6, 2017
@wilkinsona
Copy link
Member

wilkinsona commented Nov 6, 2017

I am not sure about what may go wrong when AutoConfigurationExcludeFilter is missing.

Generally speaking, nothing. This filter just prevents accidentally component scanning on auto-configuration classes that should, instead, be found via entries in spring.factories.

the reason for adding ComponentScan was to effectively add a custom excludeFilter

Boot deliberately backs off when we see the user expressing their own opinion. In this case you've expressed an opinion about the exclude filters so the defaults no longer apply. If we always kept the defaults, there'd be no way to switch them off. The approach we've taken means that you can either take complete control and remove the defaults, or you can keep them by explicitly declaring them in your excludeFilter configuration.

I think we should update the documentation to make it clearer that using @ComponentScan will replace the default exclude filters and that, if you want to keep them, you should declare them explicitly.

@ccronemberger
Copy link
Author

On the other hand, if you don't want to touch the filters and think the @ComponentScan("x.y.z") is equivalent to @SpringBootApplication(scanBasePackages="x.y.z") then you felt on Spring Boot's evil trap.
They look equivalent, but they are not.
I think that if the developer does not specify a different excludeFilter in @ComponentScan it should get the default one for @SpringBootApplication instead of getting the default overridden by empty filters.

@ccronemberger
Copy link
Author

ccronemberger commented Nov 6, 2017

Initially in our project we did not have excludeFilters and we were already using @ComponentScan because we thought it was equivalent.

@ccronemberger
Copy link
Author

Another option would be:

  1. Add a warning message to the ComponentScan javadoc saying that if it is used in a class already annotated with SpringBootApplication it will override the default excludedFilters.

@philwebb
Copy link
Member

philwebb commented Nov 7, 2017

5 is not an option because @ComponentScan is part of Spring Framework and it doesn't know about any Spring Boot concepts.

@ccronemberger
Copy link
Author

Option #4 is invalid for the same reason then.

@philwebb philwebb added type: documentation A documentation update priority: low and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels Feb 2, 2018
@philwebb philwebb modified the milestones: 2.0.0.RC2, 1.5.11 Feb 2, 2018
@philwebb
Copy link
Member

philwebb commented Feb 2, 2018

I don't think there's much we should do here other than add a note to the documentation.

@philwebb philwebb modified the milestones: 1.5.11, 1.5.x Mar 21, 2018
@snicoll snicoll modified the milestones: 1.5.x, 1.5.14 Jun 6, 2018
@snicoll snicoll self-assigned this Jun 6, 2018
@snicoll snicoll closed this as completed in 584d2de Jun 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

5 participants