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.