The spring-boot-dependencies bom version 2.2.2.RELEASE manages both jersey and jetty versions. org.eclipse.jetty:jetty-util:9.4.24.v2191120 and org.glassfish.jersey.containers:jersey-container-jetty-http:2.29.1 are incompatible due to a change in jetty's api since version 9.4.22.v20191022. The incompatibility was fixed in jersey version 2.30 (see https://github.com/eclipse-ee4j/jersey/commit/1504174ace92ff8cbeb13f5b588edd598466e18b).

The resulting error

java.lang.IllegalAccessError: org.glassfish.jersey.jetty.JettyHttpContainerFactory$JettyConnectorThreadPool.newThread(Ljava/lang/Runnable;)Ljava/lang/Thread;

    at org.eclipse.jetty.util.thread.QueuedThreadPool.startThread(QueuedThreadPool.java:655)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.ensureThreads(QueuedThreadPool.java:642)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.doStart(QueuedThreadPool.java:182)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
    at org.eclipse.jetty.server.Server.start(Server.java:407)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:117)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:100)
    at org.eclipse.jetty.server.Server.doStart(Server.java:371)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72)
    at org.glassfish.jersey.test.jetty.JettyTestContainerFactory$JettyTestContainer.start(JettyTestContainerFactory.java:112)
    at org.glassfish.jersey.test.JerseyTest.setUp(JerseyTest.java:587)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)

Simple test case illustrating the problem. Make sure to add org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-jetty to the test runtime.

public class JerseyJettyIncompatibilityTest extends JerseyTest {

    @Override
    protected Application configure() {
        ResourceConfig resourceConfig = new ResourceConfig();
        resourceConfig.property("contextConfig", new AnnotationConfigApplicationContext());
        return resourceConfig;
    }

    @Test
    public void test() {}
}

Comment From: wilkinsona

Thanks for letting us know. Unfortunately, I don’t think there’s much we can do about this in 2.2.x.

We can’t stay on Jetty 9.4.21 as Boot’s Jetty users would miss out on important bug fixes. Equally, we can’t upgrade to Jersey 2.30 as not all of Boot’s Jersey users will want to pick up a new minor release of Jersey in a maintenance release of Boot.

Ideally, Jetty maintenance releases would not contain breaking API changes. I suspect this particular change can’t be made in a backwards compatible manner but you may want to raise an issue to see if it can or if it can be reverted.

Failing that, a Jersey 2.29.x that is Jetty 9.4.22+ compatible could be released. This would allow Jetty 9.4.x and Jersey 2.29.x to use the latest versions of both without having to move to a new minor. You may want to suggest this to the Jersey team.

In the meantime, you can override the managed version of Jersey to meet your needs.

Comment From: NielsDoucet

That makes sense. Thanks for the context and suggestions. I'll check in with the jetty and jersey teams for options.

Comment From: snicoll

Thank you for creating the issue @NielsDoucet!

Comment From: bsandiford

Just updated to Spring Boot 2.3.1.RELEASE - this issue appears to be resolved in that version at least. (Probably also in 2.3.0.RELEASE, but didn't test it there)