You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tomcat9升级至10时Jersey RequestContext单例范围异常求助

Tomcat 10升级后Jersey HK2 RequestContext单例范围异常解决

问题背景

将Web应用从Tomcat 9.0.78升级至10.0.14,已完成javax.servlet到jakarta.servlet命名空间迁移,同时升级了Hibernate。目前卡在启动阶段,Tomcat日志中出现异常:

java.lang.IllegalArgumentException: The implementation class org.glassfish.jersey.inject.hk2.RequestContext must be in the Singleton scope

已尝试操作

  • 移除Tomcat/lib下的jakarta.inject-2.6.1.jar和jakarta.inject-api-2.0.0.jar,但触发类未找到异常
  • 排查源码发现org.glassfish.jersey.inject.hk2.RequestContext未标注Jakarta单例注解

环境信息

依赖版本

  • 所有Jersey jar包版本为3.0.2,包含问题类的是jersey-hk2-3.0.2.jar
  • HK2依赖配置:
<h2k.version>3.0.2</h2k.version> 
<h2k.locator.version>3.0.1</h2k.locator.version>
<jakarta.inject.version>2.6.1</jakarta.inject.version>

<dependency>
    <groupId>org.glassfish.hk2</groupId>
    <artifactId>hk2-api</artifactId>
    <version>${h2k.version}</version>
</dependency>

<dependency>
    <groupId>org.glassfish.hk2</groupId>
    <artifactId>hk2-locator</artifactId>
    <version>${h2k.locator.version}</version>
</dependency>

<dependency>
    <groupId>org.glassfish.hk2</groupId>
    <artifactId>hk2-utils</artifactId>
    <version>${h2k.version}</version>
</dependency>

完整异常栈

023 12:14:49.238 SEVERE [main] org.apache.catalina.core.StandardContext.loadOnStartup Servlet [jersey-serlvet] in web application [/ngen] threw load() exception
        java.lang.IllegalArgumentException: The implementation class org.glassfish.jersey.inject.hk2.RequestContext must be in the Singleton scope
                at org.jvnet.hk2.internal.ServiceLocatorImpl.checkConfiguration(ServiceLocatorImpl.java:1700)
                at org.jvnet.hk2.internal.ServiceLocatorImpl.addConfiguration(ServiceLocatorImpl.java:2095)
                at org.jvnet.hk2.internal.DynamicConfigurationImpl.commit(DynamicConfigurationImpl.java:262)
                at org.glassfish.hk2.utilities.ServiceLocatorUtilities.bind(ServiceLocatorUtilities.java:166)
                at org.glassfish.jersey.inject.hk2.AbstractHk2InjectionManager.<init>(AbstractHk2InjectionManager.java:65)
                at org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager.<init>(ImmediateHk2InjectionManager.java:38)
                at org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory$Hk2InjectionManagerStrategy$1.createInjectionManager(Hk2InjectionManagerFactory.java:55)
                at org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory.create(Hk2InjectionManagerFactory.java:73)
                at org.glassfish.jersey.internal.inject.Injections.createInjectionManager(Injections.java:69)
                at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:259)
                at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311)
                at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154)
                at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:347)
                at jakarta.servlet.GenericServlet.init(GenericServlet.java:158)
                at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1165)
                at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1118)
                at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1011)
                at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4906)
                at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5213)
                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
                at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:726)
                at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:698)
                at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:747)
                at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1188)
                at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:2023)
                at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
                at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
                at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
                at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:123)
                at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:1098)
                at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:480)
                at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1708)
                at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:320)
                at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
                at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423)
                at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366)
                at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:946)
                at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:886)
                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
                at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396)
                at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386)
                at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
                at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
                at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
                at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:919)
                at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:263)
                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
                at org.apache.catalina.core.StandardService.startInternal(StandardService.java:432)
                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
                at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:927)
                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
                at org.apache.catalina.startup.Catalina.start(Catalina.java:795)
                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.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
                at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476)

解决方案尝试

1. 统一HK2版本

当前hk2-locator版本为3.0.1,其他HK2依赖为3.0.2,版本不一致会引发兼容性问题。修改配置统一版本:

<h2k.locator.version>3.0.2</h2k.locator.version>

重新打包部署后验证异常是否消失。

2. 排除冲突的Jakarta Inject依赖

Tomcat/lib下的jakarta.inject jar与项目依赖版本可能冲突。在项目HK2依赖中排除jakarta.inject-api,确保依赖版本统一:

<dependency>
    <groupId>org.glassfish.hk2</groupId>
    <artifactId>hk2-api</artifactId>
    <version>${h2k.version}</version>
    <exclusions>
        <exclusion>
            <groupId>jakarta.inject</groupId>
            <artifactId>jakarta.inject-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

同时清理Tomcat/lib下的冗余jakarta.inject jar,只保留与项目依赖匹配的2.6.1版本。

3. 升级Jersey版本

Jersey 3.0.2可能存在该已知问题,尝试升级到3.0.3或更高版本,后续版本大概率已修复该兼容性问题。

4. 手动绑定RequestContext为单例

若上述方法无效,自定义HK2绑定器强制注册RequestContext为单例:

import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.inject.hk2.RequestContext;
import jakarta.inject.Singleton;

public class CustomBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(RequestContext.class).to(RequestContext.class).in(Singleton.class);
    }
}

在Jersey应用类中注册该绑定器:

public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        register(new CustomBinder());
        // 其他资源/过滤器注册
    }
}

内容的提问来源于stack exchange,提问作者RichardFeynman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 20:14:58