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

Tomcat8.5渲染JSF2.3 f:websocket组件遇AbstractMethodError求助

解决Tomcat 8.5上JSF 2.3 <f:websocket>的AbstractMethodError问题

我来帮你排查这个问题——从错误堆栈和你的配置来看,核心是版本兼容性导致的,具体来说是OCPSoft Rewrite的旧版本不支持JSF 2.3新增的WebSocket相关方法,再加上JSF初始版本的潜在bug,一起引发了AbstractMethodError。

先梳理下你的当前配置和报错信息,再给出具体的修复步骤:


你的当前配置

Maven依赖

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.faces</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <version>2.0</version>
</dependency>
<dependency>
    <groupId>org.jboss.weld.servlet</groupId>
    <artifactId>weld-servlet-shaded</artifactId>
    <version>3.0.3.Final</version>
</dependency>
<dependency>
    <groupId>org.primefaces</groupId>
    <artifactId>primefaces</artifactId>
    <version>6.2</version>
</dependency>

测试页面(test.xhtml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
    <h:form>
        <h:outputText value="#{pisSocketView.count}" styleClass="display" />
        <p:commandButton value="Click" actionListener="#{pisSocketView.increment}" />
        <f:websocket channel="counter" onmessage="handleMessage" />
    </h:form>
    <script type="text/javascript">
        function handleMessage(message, channel, event) {
            $('.display').text(message);
        }
    </script>
</h:body>
</html>

错误堆栈

java.lang.AbstractMethodError
    at javax.faces.application.ViewHandlerWrapper.getWebsocketURL(ViewHandlerWrapper.java:328)
    at javax.faces.application.ViewHandlerWrapper.getWebsocketURL(ViewHandlerWrapper.java:328)
    at com.sun.faces.push.WebsocketChannelManager.register(WebsocketChannelManager.java:151)
    at com.sun.faces.push.WebsocketChannelManager.register(WebsocketChannelManager.java:142)
    at com.sun.faces.push.WebsocketChannelManager$Proxy$_$$_WeldClientProxy.register(Unknown Source)
    at com.sun.faces.renderkit.html_basic.WebsocketRenderer.encodeEnd(WebsocketRenderer.java:115)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:949)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1912)
    at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:918)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1905)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:491)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:194)
    at org.ocpsoft.rewrite.faces.RewriteViewHandler.renderView(RewriteViewHandler.java:186)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:151)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:151)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:126)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:223)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:671)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:205)
    at org.apache.catalina.c...

问题根源与修复步骤

1. 核心原因:Rewrite版本不兼容JSF 2.3

从错误堆栈里的org.ocpsoft.rewrite.faces.RewriteViewHandler可以看出,你使用的Rewrite版本太旧了——JSF 2.3新增了ViewHandler.getWebsocketURL()方法,但旧版本的Rewrite的RewriteViewHandler作为ViewHandlerWrapper的子类,没有实现这个新方法,导致调用时直接抛出AbstractMethodError。

2. 具体修复操作

(1)升级OCPSoft Rewrite到兼容版本

Rewrite从3.4.1.Final开始正式支持JSF 2.3,你需要在pom.xml中添加/更新Rewrite的依赖:

<dependency>
    <groupId>org.ocpsoft.rewrite</groupId>
    <artifactId>rewrite-servlet</artifactId>
    <version>3.4.1.Final</version>
</dependency>
<dependency>
    <groupId>org.ocpsoft.rewrite</groupId>
    <artifactId>rewrite-config-faces</artifactId>
    <version>3.4.1.Final</version>
</dependency>

如果你的项目之前已经引入了Rewrite,直接修改版本号即可。

(2)升级JSF到稳定版

你当前用的JSF 2.3.0是第一个正式版,存在一些已知的兼容性问题,建议升级到最新的2.3.x稳定版(比如2.3.14):

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.faces</artifactId>
    <version>2.3.14</version>
</dependency>

(3)确认CDI配置完整

JSF 2.3的WebSocket功能依赖CDI,确保你的项目WEB-INF/beans.xml存在且配置正确(CDI 2.0版本):

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       version="2.0"
       bean-discovery-mode="all"/>

这个文件是CDI启用的必要条件,缺失或配置错误会导致WebSocket无法正常工作。

(4)验证Tomcat WebSocket支持

Tomcat 8.5默认已经启用WebSocket支持,错误日志中也出现了WsFilter,这部分无需额外配置,只要确保没有在项目中禁用该Filter即可。


验证修复

完成上述修改后,重新构建并部署项目,访问test.xhtml页面:

  • 页面应该能正常加载,不会再抛出AbstractMethodError
  • 点击"Click"按钮后,数值应该能通过WebSocket实时更新到页面上

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:04:48