Skip to content
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

Revisit Servlet API baseline: Servlet 6.0 in the build, Servlet 5.0 compatibility at runtime #29435

Closed
jhoeller opened this issue Nov 5, 2022 · 5 comments
Assignees
Labels
in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: dependency-upgrade A dependency upgrade
Milestone

Comments

@jhoeller
Copy link
Contributor

jhoeller commented Nov 5, 2022

While Spring Framework 6.0 intends to retain a Servlet 5.0 (Jakarta EE 9) baseline for the time being, there is a breaking change in Servlet 6.0 (Jakarta EE 10) that we need to take into account: the removal of the deprecated HttpSessionContext interface which makes existing implementations of HttpSession non-resolvable against the Servlet 6.0 API, as long as they keep implementing the deprecated getSessionContext() method.

This affects our Servlet API mocks which effectively do not work in a Servlet 6.0 setup. By compiling against Servlet 6.0, we can avoid implementing the deprecated getSessionContext() method while still retaining compatibility with Servlet 5.0 based code - except for getSessionContext() which threw an UnsupportedOperationException before in any case.

This also enables us to use new Servlet 6.0 facilities where appropriate - any time in the Spring Framework 6.x generation. Aside from avoiding 5.0-deprecated methods for Servlet 6.0 compatibility (where they got removed), no specific support for Servlet 6.0 mechanisms (such as ServletRequest.getServletConnection() or Cookie attributes) has been introduced yet.

@iay
Copy link

iay commented Nov 9, 2022

This is a breaking change for us. We use the Spring Mocks in our tests too, and therefore had to update to compile vs. Servlet 6.

However, we have classes which implement and proxy HttpServletRequest. Our proxy implementation, compiled against Servlet 6, needed to implement the following method as part of the Servlet 6 version of the interface:

ServletConnection getServletConnection();

ServletConnection is itself introduced in Servlet 6, and does not exist in Servlet 5. This means that this proxy class cannot be loaded in a Servlet 5 container and contrary to your intention we do not have runtime compatibility with such containers as a result of this change.

Please reconsider.

@jhoeller
Copy link
Contributor Author

jhoeller commented Nov 9, 2022

Unfortunately, we have no choice here. Compiling against Servlet 5, some parts of our framework arrangement and in particular the mocks would be incompatible with Servlet 6 (due to having to refer to the now-removed HttpSessionContext), and we absolutely have to launch Boot 3.0 with Servlet 6 due to Tomcat 10.1 now (since the Servlet 5 based Tomcat 10.0 has been declared EOL already), and make mock usage possible with Servlet 6 on the classpath as a part of that offering.

On a forward-looking note, it is more important to be compatible with Servlet 6+ than to make Servlet 5 usage convenient. In all likelihood, Servlet 5 will be very short-lived in the Spring ecosystem, only really relevant for Jetty 11 purposes until Jetty 12 goes GA some time next year. If it wasn't for Jetty, we might have been able to launch with a Servlet 6 baseline right away.

Note that the framework itself is compatible with Servlet 5 containers at production level. It is literally just the mocks that bring in Servlet 6, and the mocks are not meant to be used in a Servlet container environment to begin with. For compilation purposes with a Servlet 5 compatibility impact, we recommend compiling your main sources against the Servlet 5.0 API jar and your mock-using test sources against the Servlet 6.0 API jar, side by side.

Last but not least, for custom purposes where our mocks leak through to production sources in some form, feel free to fork them for the time being, maybe even just fork MockHttpServletRequest if that is the key part. The mocks are not an essential part of our framework arrangement but rather just convenient test utilities that we happen to ship as well.

As a side thought, if you prefer building your main sources against Servlet 6 as well, you could possibly derive from HttpServletRequestWrapper for request proxy classes, avoiding a direct reference to the new ServletConnection type in your classes and therefore keeping them compatible with Servlet 5 at runtime.

P.S.: I clarified the issue description that our mocks mean to retain compatibility with Servlet 5 based code that is being tested, not with running against the Servlet 5.0 API themselves. The mocks are based on the Servlet 6.0 API now, requiring the latter on the test classpath. FWIW we had a similar situation before with Servlet 4.0 vs 3.1 where the mocks were 4.0 based as well.

@iay
Copy link

iay commented Nov 9, 2022

Thanks for the guidance. We're going to try to fork the relevant mock as suggested and see if that gets us back to the status quo for now.

If that doesn't work out, we may have to wait for Jetty 12 (Jetty's our preferred container, for various reasons) and skip Servlet 5. Again, knowing that you think Servlet 5 is not going to have a position longer term is useful information. There's something to be said for getting all the transitions out of the way at once rather than one by one.

JKatzwinkel added a commit to JKatzwinkel/tla-web that referenced this issue Nov 13, 2022
jetty 11 only runs against servlet api 5, but spring boot 3 will be launched with servlet api 6.
solution for now seems to be an explicit downgrade of our servlet api dependency and wait for jetty 12 to release.

background: spring-projects/spring-framework#29435
@anbusampath
Copy link

Servlet 5 will be very short-lived in the Spring ecosystem, only really relevant for Jetty 11 purposes until Jetty 12 goes GA some time next year. If it wasn't for Jetty, we might have been able to launch with a Servlet 6 baseline right away.

@jhoeller will Servlet 6(once Jetty 12 goes GA) become baseline for Spring Framework 6.1? Also dropping support for Servlet 5 containers in 6.1 timeframe.

@jhoeller
Copy link
Contributor Author

At this point, we have no intentions to drop Servlet 5 runtime compatibility at the core framework level since it is easy enough to retain still. We just intend to drop Jetty 11 support in WebFlux as of Spring Framework 6.1 due to incompatibities in the Jetty 12 APIs, just retaining Jetty 11 compatibility for Spring MVC as part of our general Servlet 5 runtime compatibility.

At Spring Boot level, it looks like there will be a consistent Servlet 6 baseline from version 3.2 onwards, including Jetty 12 in all stack variants.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: dependency-upgrade A dependency upgrade
Projects
None yet
Development

No branches or pull requests

4 participants