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.
Comment From: iay
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.
Comment From: jhoeller
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.
Comment From: iay
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.
Comment From: anbusampath
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.
Comment From: jhoeller
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.