In addition to downgrading the Servlet API to 5.0, we also need to cover the impact that this will have on testing. Framework's Servlet-related mocks require Servlet 6.0 and will fail due to the absence of ServletConnection when run against the Servlet 5.0 API. Similarly, Jetty requires Servlet 5.0 and will fail due to the absence of HttpSessionContext when run against the Servlet 6.0 API. This leaves us with two arrangements that will work:
- Tests use the Servlet 6.0 API and avoid starting Jetty by only using a mock web environment
- Tests use the Servlet 5.0 API and avoid using Framework's Servlet mocks by only using a full-blown web environment
If a mixture of web environments is required by an application's tests, it can be done but it may require some structural changes to separate the two web environments. With Gradle this could be done with different source sets or separate modules. With Maven, I believe separate modules will always be required.
Comment From: david-romero
Hi @wilkinsona,
I'm facing this issue in a real application, not only in tests. Do you know how to fix it?
Starters added: - spring-boot-starter-web - exclude - spring-boot-starter-tomcat - spring-boot-starter-jetty - spring-boot-starter-amqp - spring-boot-starter-data-redis - spring-boot-starter-actuator - spring-boot-starter-validation - spring-boot-starter-json - spring-boot-starter-webflux - spring-boot-starter-data-jpa
Version: 3.0.0-RC2
Error trace:
java.lang.ClassNotFoundException: jakarta.servlet.http.HttpSessionContext
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 41 common frames omitted
Wrapped by: java.lang.NoClassDefFoundError: jakarta/servlet/http/HttpSessionContext
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at org.eclipse.jetty.server.session.SessionHandler.<clinit>(SessionHandler.java:136)
at org.eclipse.jetty.servlet.ServletContextHandler.newSessionHandler(ServletContextHandler.java:339)
at org.eclipse.jetty.servlet.ServletContextHandler.getSessionHandler(ServletContextHandler.java:432)
at org.eclipse.jetty.servlet.ServletContextHandler.relinkHandlers(ServletContextHandler.java:257)
at org.eclipse.jetty.servlet.ServletContextHandler.<init>(ServletContextHandler.java:180)
at org.eclipse.jetty.webapp.WebAppContext.<init>(WebAppContext.java:301)
at org.eclipse.jetty.webapp.WebAppContext.<init>(WebAppContext.java:228)
at org.springframework.boot.web.embedded.jetty.JettyEmbeddedWebAppContext.<init>(JettyEmbeddedWebAppContext.java:28)
at org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory.getWebServer(JettyServletWebServerFactory.java:158)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:183)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:161)
... 21 common frames omitted
Wrapped by: org.springframework.context.ApplicationContextException: Unable to start web server
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:164)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:578)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291)
Comment From: wilkinsona
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0.0-RC2-Release-Notes#jetty
Comment From: larsgrefer
Would it be possible to let spring-boot-starter-jetty have different dependencies?
Currently, both the Maven pom and the Gradle module explicitly request Servlet 6:
<dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>compile</scope> </dependency>https://repo.spring.io/artifactory/milestone/org/springframework/boot/spring-boot-starter-jetty/3.0.0-RC2/spring-boot-starter-jetty-3.0.0-RC2.pom
{ "group": "jakarta.servlet", "module": "jakarta.servlet-api", "version": { "requires": "6.0.0" } },https://repo.spring.io/artifactory/milestone/org/springframework/boot/spring-boot-starter-jetty/3.0.0-RC2/spring-boot-starter-jetty-3.0.0-RC2.module
Comment From: wilkinsona
It's possible, although it would require some surgery to Spring Boot's build. For the vast majority of users it would have no benefit as Spring Boot's dependency management would upgrade the dependency to 6.0.0 again anyway. When we were in a similar situation with Jetty in Spring Boot 2.x (when Jetty did not support Servlet 4.0 and Tomcat and Undertow did), we used the current arrangement and it seemed to work well.
Comment From: Tristan971
For the runtime setup, this works easily enough indeed, but as you rightly point out in the first message this isn't nearly as easy to work with for the test side of things (at least right now), and splitting tests into different maven modules is a rather nuclear approach to the issue.
So, realistically, most affected users will have to just stall the upgrade till Jetty supports servlet-api 6. Which might be fine or not, depending on how long it will likely take to happen. Couldn't find a reference to the matter on their repo but I'm also not too familiar with how they manage their roadmap for the upcoming Jetty 12 (which I imagine is the one that will target servlet-api 6)
Comment From: Tristan971
Actually, scratch that, found someone asking the same question for the same reasons here https://www.eclipse.org/lists/jetty-users/msg10348.html
Quoting:
Date: Wed, 9 Nov 2022 13:59:43 -0600 Jetty 12 already has Alpha quality releases out that you can use to start experimenting with. We should be going to Betas (or Release candidates) in the next few weeks. Joakim Erdfelt / joakim@xxxxxxxxxxx
So hopefully not too long of a weird inter-version timeframe all-in-all (barring the usual delays one should expect with software development, ofc)
Comment From: wilkinsona
Unfortunately, as I understand it, there are some fairly significant breaking changes in Jetty 12. I believe @rstoyanchev saw quite a big impact on Spring Framework's WebSocket integration, for example. As such, Jetty 12 support may take some time to fully materialise.
Comment From: larsgrefer
It's possible, although it would require some surgery to Spring Boot's build. For the vast majority of users it would have no benefit as Spring Boot's dependency management would upgrade the dependency to 6.0.0 again anyway. When we were in a similar situation with Jetty in Spring Boot 2.x (when Jetty did not support Servlet 4.0 and Tomcat and Undertow did), we used the current arrangement and it seemed to work well.
Something like this in spring-boot-project/spring-boot-starters/spring-boot-starter-jetty/build.gradle should do the trick (at least for Gradle users):
api("jakarta.servlet:jakarta.servlet-api") {
version {
strictly "5.0.0"
because "Jetty 11 does not support Servlet 6 yet"
}
}
Comment From: wilkinsona
Unfortunately, it's not that simple. Internally, Boot's build is structured such our dependency management is enforced. This ensures that we know that we're compiling and testing against the versions in our dependency management. As I said, it would require some surgery to use a different version in spring-boot-starter-jetty. We don't believe it's worth it.
Comment From: mhalbritter
FTR, this is how you get a working setup with gradle:
ext['jakarta-servlet.version'] = '5.0.0'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation("org.springframework.boot:spring-boot-starter-jetty")
modules {
module("org.springframework.boot:spring-boot-starter-tomcat") {
replacedBy("org.springframework.boot:spring-boot-starter-jetty", "Use Jetty instead of Tomcat")
}
}
}
Comment From: lpandzic
Unfortunately, it's not that simple. Internally, Boot's build is structured such our dependency management is enforced. This ensures that we know that we're compiling and testing against the versions in our dependency management. As I said, it would require some surgery to use a different version in
spring-boot-starter-jetty. We don't believe it's worth it.
Ok, but for end users a fix would look like:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
?
We have a company wide BOM so my plan is to do something like this unless there's another concern not do so.
Comment From: wilkinsona
Yes, I believe that will work as your dependency management for jakarta.servlet-api is nearer to the root so it will take precedence over what's in the imported spring-boot-dependencies.
Comment From: Sineaggi
This leaves us with two arrangements that will work:
Tests use the Servlet 6.0 API and avoid starting Jetty by only using a mock web environment Tests use the Servlet 5.0 API and avoid using Framework's Servlet mocks by only using a full-blown web environment
The first option seems simple, that sounds like using @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) which is the default.
How would we go about using the second option which avoids using Framework's Servlet mocks?
EDIT: The second option would let you use WebEnvironment.RANDOM_PORT, DEFINED_PORT and NONE.
Comment From: crusi
Hi @wilkinsona,
I'm facing this issue in a real application, not only in tests. Do you know how to fix it?
Starters added:
spring-boot-starter-web
exclude
- spring-boot-starter-tomcat
- spring-boot-starter-jetty
- spring-boot-starter-amqp
- spring-boot-starter-data-redis
- spring-boot-starter-actuator
- spring-boot-starter-validation
- spring-boot-starter-json
- spring-boot-starter-webflux
- spring-boot-starter-data-jpa
Version: 3.0.0-RC2
Error trace:
java.lang.ClassNotFoundException: jakarta.servlet.http.HttpSessionContext at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ... 41 common frames omitted Wrapped by: java.lang.NoClassDefFoundError: jakarta/servlet/http/HttpSessionContext at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) at org.eclipse.jetty.server.session.SessionHandler.<clinit>(SessionHandler.java:136) at org.eclipse.jetty.servlet.ServletContextHandler.newSessionHandler(ServletContextHandler.java:339) at org.eclipse.jetty.servlet.ServletContextHandler.getSessionHandler(ServletContextHandler.java:432) at org.eclipse.jetty.servlet.ServletContextHandler.relinkHandlers(ServletContextHandler.java:257) at org.eclipse.jetty.servlet.ServletContextHandler.<init>(ServletContextHandler.java:180) at org.eclipse.jetty.webapp.WebAppContext.<init>(WebAppContext.java:301) at org.eclipse.jetty.webapp.WebAppContext.<init>(WebAppContext.java:228) at org.springframework.boot.web.embedded.jetty.JettyEmbeddedWebAppContext.<init>(JettyEmbeddedWebAppContext.java:28) at org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory.getWebServer(JettyServletWebServerFactory.java:158) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:183) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:161) ... 21 common frames omitted Wrapped by: org.springframework.context.ApplicationContextException: Unable to start web server at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:164) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:578) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291)
we are facing the same issue during startup but with 3.0.0 released version. Thought we can directly jump to Boot 3 with our new service but it looks like we have to wait...
Comment From: mhalbritter
There are workarounds for both Maven and Gradle:
Maven
<properties>
<jakarta-servlet.version>5.0.0</jakarta-servlet.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
Gradle
ext['jakarta-servlet.version'] = '5.0.0'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation("org.springframework.boot:spring-boot-starter-jetty")
modules {
module("org.springframework.boot:spring-boot-starter-tomcat") {
replacedBy("org.springframework.boot:spring-boot-starter-jetty", "Use Jetty instead of Tomcat")
}
}
}
Does that work for you?
Comment From: hborchardt
Hi, just wanted to report that for me, the gradle-based version adjustment you suggest did not work, it kept pulling version 6 in. Digging through the code a little, I also did not find how that mechanism would work, the only references I found were related to maven.
What worked for me was the following snippet, based on this link: https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/#managing-dependencies.gradle-bom-support.customizing
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'jakarta.servlet') {
details.useVersion '5.0.0'
}
}
}
Comment From: eocak
FTR, this is how you get a working setup with gradle:
``` ext['jakarta-servlet.version'] = '5.0.0'
dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation("org.springframework.boot:spring-boot-starter-jetty") modules { module("org.springframework.boot:spring-boot-starter-tomcat") { replacedBy("org.springframework.boot:spring-boot-starter-jetty", "Use Jetty instead of Tomcat") } } } ```
This seems to be working. Thanks.
Comment From: Tak1za
Found a temporary fix for the problem. Move back to Jakarta 6.0.0 and add the following dependency:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
With the latest version of jetty-server.
With this the service starts up and the unit tests with MockMvc works as expected.
Comment From: simenaj96
I tried the maven approach above, I tried adding the <jakarta-servlet.version>5.0.0</jakarta-servlet.version> in Maven properties, yet still no luck. Also tried the other approaches. But still getting that classes are not found.
Comment From: tasosz
I've had the same issue, and the previously suggested options were not working for everything. Either the service would start or all the tests (inc mockmvc) would succeed. But not everything. :-(
In the end, this setup has worked for all:
ext {
set("jakarta-servlet.version", '5.0.0')
}
plus:
testImplementation
'org.eclipse.jetty:jetty-server:11.0.14',
'jakarta.servlet:jakarta.servlet-api:6.0.0',
Comment From: nibexo
@tasosz @simenaj96 Did you try set only 'org.eclipse.jetty:jetty-server:11.0.14' in implementation section?
Comment From: Siedlerchr
I also tried the maven workarounds but still no success. I also tried to ugprade to jetty 12 beta maven plugin, but that didn't help. It's still the test that fail
Comment From: Siedlerchr
Update:
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
with
<properties>
<jetty.version>11.0.15</jetty.version>
<jakarta-servlet.version>5.0.0</jakarta-servlet.version>
</properties>
worked
Comment From: Nowheresly
In order to use jetty AND being able to run the unit test with spring boot 3.0.x, we use the following approach: * downgrade jakarta-servlet version to 5.0.0 as explained in the release notes
<properties>
<jakarta-servlet.version>5.0.0</jakarta-servlet.version>
</properties>
- copy and paste in the
src/test/javafolder the interfacejakarta.servlet.ServerConnection.java. It seems adding this interface in the test classpath is enough to fix one of the main issue to run unit tests. Source code for this interface can be found here.
Obviously, the second part is clearly a hack. I'm not sure to which extend we can trust the result of unit tests (but at least they can run)....
Comment From: mikebell90
@Nowheresly yours is a partial fix and works because the mockhttprequest (iirc) explicitly mocks this interface. However if you play with cookies, you'll get another error, since the Cookie class has been heavily modified.
Our "solution" is to package a local servlet-api with the cookie and servletconnection copied back.
Of course this will break should spring tests end up deliberately or accidentally referring to servlet 6 only other stuff.
https://github.com/opentable/servlet/compare/5.0.0-RELEASE...opentable:servlet:5.9.0 basically makes the idea concrete.
Another limitation besides the inherent fragility is of course you CANNOT open source any thing built with this, since of course the patched version doesn't exist in maven central.
I hasten to add this is a no good fragile solution. If Spring changes or another third party relies on Servlet 6 and uses it's methods, one will live to regret this solution
Comment From: fzyzcjy
Hi, is there any updates? Thanks!
Comment From: wilkinsona
@fzyzcjy No, I'm afraid not. We work in the open so any updates will appear in this issue. Anything that may be documented is already described in this issue.
Comment From: renannprado
Thanks @Tak1za.
In the end it looks like this for me with gradle.
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-jetty")
modules {
module("org.springframework.boot:spring-boot-starter-tomcat") {
replacedBy("org.springframework.boot:spring-boot-starter-jetty", "Use Jetty instead of Tomcat")
}
}
implementation("org.eclipse.jetty:jetty-server:11.0.15")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
Comment From: du-it
Unfortunately, no of the suggestions above worked for me at all. I tried with jetty-server 12.0.1, servlet-api 5.0.0/6.0.0, spring-boot-dependencies 3.1.3 in the dependency-management, ...I always get: org.eclipse.jetty.server.handler.HandlerWrapper
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory]: Factory method 'jettyServletWebServerFactory' threw exception with message: org/eclipse/jetty/server/handler/HandlerWrapper
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:171)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)
... 97 more
Caused by: java.lang.NoClassDefFoundError: org/eclipse/jetty/server/handler/HandlerWrapper
at org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedJetty.jettyServletWebServerFactory(ServletWebServerFactoryConfiguration.java:93)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:139)
... 98 more
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.server.handler.HandlerWrapper
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
Comment From: nibexo
@du-it
Did you try use version 11.0.14 instead 12.0.1?
Comment From: wilkinsona
@du-it As I already said on Stack Overflow Jetty 12 is not yet supported. #36073 will add Jetty 12 support and will hopefully be part of Spring Boot 3.2. In the meantime, as @nibexo suggests, you need to use Jetty 11.0.x.
Comment From: asciicode
Found a temporary fix for the problem. Move back to Jakarta 6.0.0 and add the following dependency:
```
``` org.eclipse.jetty jetty-server ${jetty.version} With the latest version of jetty-server.
With this the service starts up and the unit tests with MockMvc works as expected.
you save my day.
Comment From: mhalbritter
A part of this has been done while working on https://github.com/spring-projects/spring-boot/issues/37238.
Comment From: maddy65
I have a similar issue and I have used something like that
resolutionStrategy.eachDependency { details ->
if (details.requested.group == 'jakarta.servlet') {
// to support jetty on spring boot 3.1.4
details.useVersion '5.0.0'
}
}
After adding this in configuration of build.gradle my application is working fine but I am getting issue while running the testcase.
java.lang.NoClassDefFoundError: jakarta/servlet/ServletConnection
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:210)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:241)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$8(ClassBasedTestDescriptor.java:363)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:368)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$9(ClassBasedTestDescriptor.java:363)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:362)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:283)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:282)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:272)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:271)
at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:102)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:101)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Any workaround how to manage both application and testcases for the same.
Comment From: Spikhalskiy
I faced the same issue with java.lang.NoClassDefFoundError: jakarta/servlet/ServletConnection coming from the usage in org.springframework.mock.web.MockHttpServletRequest.
Environment: jetty 11 + jakarta.servlet-api 5 + Spring 6.1.
I was able to work around the problem by just adding ServletConnection to the project classpath (can be done by adding the source code of the class directly to the project).
Comment From: jo-elimu
I faced the same issue with
java.lang.NoClassDefFoundError: jakarta/servlet/ServletConnectioncoming from the usage inorg.springframework.mock.web.MockHttpServletRequest. Environment: jetty 11 + jakarta.servlet-api 5 + Spring 6.1. I was able to work around the problem by just adding ServletConnection to the project classpath (can be done by adding the source code of the class directly to the project).
@Spikhalskiy Thank you for sharing your work-around. I can confirm that it solved the problem.
Also, is it correct to assume that once we upgrade to Jetty 12 (Servlet 6), we can remove the source code (ServletConnection.java) and things should still work?
Comment From: Spikhalskiy
@jo-elimu Yeah, after upgrading to Jakarta Servlet API 6.0, you can remove this class because it's present in that version of servlet-api dependency.