The Problem
Through Spring Boot 2.3.9.RELEASE
, org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
was a public
class, with no deprecation.
In 2.4.0
, the keyword "public" was dropped, making it package-private.
I assume this is an improvement and 3 SRs into 2.4.x is too late to change.
But isn't the policy is that class and methods that should no longer be used as of future release X are to be deprecated in release X-1 (or is it X-2)? I think this qualifies, and so was a miss.
Side note
FWIW, my particular problem is a @Configuration
class in a library (which I didn't write), itself conditional (another class is used for Webflux):
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
with this additional annotation:
@AutoConfigureBefore({SecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class,
SecurityFilterAutoConfiguration.class, SpringBootWebSecurityConfiguration.class})
(I'm not sure what issue listing SpringBootWebSecurityConfiguration
solved, back when the library was updated for Spring Boot 2.0, but I'm removing mention of SpringBootWebSecurityConfiguration
and proceeding from there.)
To Reproduce
Add @AutoConfigureBefore(SpringBootWebSecurityConfiguration.class)
to some configuration class.
Expected Behavior
Well, the best case would be the absence of compilation errors like this:
... org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration is not public in org.springframework.boot.autoconfigure.security.servlet; cannot be accessed from outside package
But more to the point, I would have expected to see this class deprecated (with a comment explaining that it was to be made package-private, not removed) prior to this change.
tl;dr
This is really just a plea for developers to be more cautious about making classes and methods less public.
Comment From: philwebb
We're generally quite careful about removing things like public
, but auto-configuration classes are a bit special. We consider them somewhat internal and tend to be a bit more aggressive about changes like this. Generally speaking most users should only be referencing the public classes to either set @AutoConfigureBefore
/@AutoConfigureAfter
or to exclude them.
This particular class is a good example of something that should really be package-private. Defining @AutoConfigureBefore(SpringBootWebSecurityConfiguration.class)
will actually have no effect because @AutoConfigureBefore
/@AutoConfigureAfter
only changes the order of top-level auto-configuration classes. Since SpringBootWebSecurityConfiguration
isn't an auto-configuration class itself (it's only imported by one) trying to apply ordering wont work. We had a really old issue (#7697) to try and detect this kind of error but it was quite hard to implement and we decided to drop it in the end to focus on other enhancements.
It's annoying that we sometimes need to make classes we'd rather keep internal as public
just so that we can use them ourselves. Some projects use an @Internal
annotation to flag classes like that. I've never been too keen on this approach in Spring Boot. People just tend to ignore them anyway.
Comment From: larrywest
@philwebb Good explanation, thanks.
And I agree y'all are generally quite careful; this is the first (albeit spurious) counter-example I've ever come across.
Off-topic
Speaking of undesirably-exported-class problems, I imagine Spring will be going thru a major effort to utilize Jigsaw whenever Java 8 is left behind. It would be very interesting to see what lessons a project the size of Spring has for the rest of us, if someone is motivated to write them up.