You need to enable JavaScript to run this app. Quarkus 1.10.5整合Atmosphere报JSR356配置异常,寻求WebSocket开启方案
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus 1.10.5整合Atmosphere报JSR356配置异常,寻求WebSocket开启方案

问题根因定位

你遇到的 ServerContainer is null 异常,本质是两套初始化机制的时序冲突导致的,和之前配置的 Servlet 异步支持没有直接关联:

  • Quarkus 1.10.5.Final 版本的 quarkus-undertow-websockets 扩展存在初始化时序差:该扩展会在所有 Servlet 上下文初始化流程走完之后,才完成 WebSocket 引擎的部署,把 ServerContainer 实例绑定到 ServletContext 属性上。而 Atmosphere 的 JSR356AsyncSupport 是跟着 Vaadin Servlet 的初始化流程触发加载的,这个阶段上下文里还没有写入对应的属性,自然取到 null。
  • Quarkus 原生的 WebSocket 扩展默认不会把 ServerContainer 暴露到全局 ServletContext 域,只有当应用显式注册了 @ServerEndpoint 标注的 JSR-356 端点时,才会做属性绑定,单靠引入依赖是不会自动完成绑定的。
    这种 null 值会直接触发 Atmosphere 的自动降级逻辑,切到不支持 WebSocket 的 Servlet30CometSupport 实现,和你之前加的 Servlet 异步支持配置没有关联,自然无法解决问题。
分步解决操作
  • 第一步:对齐依赖版本
    确保引入的 websocket 依赖和 Quarkus 核心版本完全匹配,不要跨版本混用 Undertow 相关的扩展,避免内核API不兼容:
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-undertow-websockets</artifactId>
      <version>1.10.5.Final</version>
    </dependency>
    
  • 第二步:手动补全 ServletContext 的 ServerContainer 绑定
    编写一个实现 io.quarkus.undertow.ServletDeploymentListener 的 CDI Bean,在 Undertow 完成部署的阶段,把容器已经初始化好的 ServerContainer 显式写入到 ServletContext 属性中,匹配 Atmosphere 取数的key:
    @Singleton
    public class WebSocketContextBinder implements ServletDeploymentListener {
        @Inject
        ServerContainer injectedContainer;
    
        @Override
        public void deploymentInitialized(ServletDeploymentContext deployContext) {
            ServletContext ctx = deployContext.servletContext();
            // 严格按照 Atmosphere 读取的key写入属性
            ctx.setAttribute(ServerContainer.class.getName(), injectedContainer);
        }
    }
    
    这个操作直接绕开了扩展的初始化时序问题,不需要修改 Atmosphere 的源码逻辑。
  • 第三步:修正 Servlet 注册规则
    删掉之前手动通过 ServletBuildItem 重复注册 QuarkusVaadinServlet 的代码,重复手动注册会打乱 Quarkus Vaadin 扩展自带的 Servlet 优先级逻辑,进一步加剧初始化时序的混乱。只需要在 application.properties 里配置异步支持即可,不需要硬编码 Servlet 构造逻辑:
    # 为 Vaadin Servlet 开启异步支持
    quarkus.undertow.servlet."vaadin-servlet".async-supported=true
    
  • 第四步:关闭 Atmosphere 的自动降级逻辑
    因为 Atmosphere 的降级判断是在属性为空时立刻触发,哪怕后续我们补全了上下文属性,也不会重新加载 JSR356 的实现。需要通过初始化参数强制 Atmosphere 固定使用 JSR356 作为底层实现:
    # 强制指定 Atmosphere 异步实现类
    quarkus.vaadin.servlet.init-params.org.atmosphere.cpr.asyncSupport=org.atmosphere.container.JSR356AsyncSupport
    
避坑注意事项
  • 不要在 Quarkus 1.10.5.Final 版本下升级 Atmosphere 到 2.4.30 以上的版本,高版本 Atmosphere 对新 Undertow 的适配逻辑和该老版本的 Servlet 容器实现不兼容,会触发类加载、端点映射的连锁异常。
  • 不要尝试通过 web.xml 配置 JSR-356 的 WebSocket 端点,Quarkus 1.10 版本的 Undertow 适配层不支持解析 web.xml 中的 WebSocket 配置项,配置完全不生效。
  • 完成上述配置后,不需要额外给 WebSocket 路径加 Undertow 的路由规则,Atmosphere 会自动接管自己的端点映射流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.07 10:15:05