【问题标题】:Websocket + Pretty Faces = AbstractMethodErrorWebsocket + Pretty Faces = AbstractMethodError
【发布时间】:2020-03-02 10:43:12
【问题描述】:

我正在 tomcat 8.5 中构建一个简单的 JSF 2.3 应用程序。我让 websocket 正常工作,然后我添加了 Pretty Faces。

如果我单独使用它们,它们都可以工作。我的意思是,如果我从 pom 中删除 Pretty Faces 的依赖项,我的 websocket 就可以工作了。如果我保留依赖关系,并从我的视图中删除 <f:websocket>,Pretty Faces 工作(重定向正常)!

但是,如果我尝试使用 Pretty Faces,当我在视图中有 <f:websocket> 时,当我导航到它时会出现 AbstractMethodError。从字面上看,如果我评论标签,其他一切都可以。

我使用 mojarra。在我的 pom 中,我将 https://github.com/javaserverfaces/mojarra/blob/master/README.mdthe default ones 的依赖项用于 Pretty Faces。

我猜问题是我有冲突的依赖关系,从我在this BalusC answer 中读到的内容,或者 Pretty Faces 和 Websocket 以某种方式冲突。

任何帮助将不胜感激。提前致谢。

这里是依赖项

<!-- Java EE containers -->
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>8.0</version>
    <scope>provided</scope>
</dependency>

<!-- Servlet Containers -->
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.faces</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>org.jboss.weld.servlet</groupId>
    <artifactId>weld-servlet-shaded</artifactId>
    <version>3.0.0.Final</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
<dependency> <!-- Optional, only when <f:websocket> is used. -->
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.1</version>
</dependency>

<!-- Pretty Faces -->
<dependency>
    <groupId>org.ocpsoft.rewrite</groupId>
    <artifactId>rewrite-servlet</artifactId>
    <version>3.4.2.Final</version>
</dependency>
<dependency>
    <groupId>org.ocpsoft.rewrite</groupId>
    <artifactId>rewrite-config-prettyfaces</artifactId>
    <version>3.4.2.Final</version>
</dependency>

这里是例外

Nov 06, 2019 1:49:39 AM com.sun.faces.context.ExceptionHandlerImpl log
FATAL: JSF1073: java.lang.AbstractMethodError caught during processing of RENDER_RESPONSE 6 : UIComponent-ClientId=, Message=null
Nov 06, 2019 1:49:39 AM com.sun.faces.context.ExceptionHandlerImpl log
FATAL: No associated message
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:196)
    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:226)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:470)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:316)
    at org.ocpsoft.rewrite.servlet.impl.HttpRewriteResultHandler.handleResult(HttpRewriteResultHandler.java:42)
    at org.ocpsoft.rewrite.servlet.RewriteFilter.rewrite(RewriteFilter.java:297)
    at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:198)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:660)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

【问题讨论】:

    标签: java jsf java-websocket prettyfaces jsf-2.3


    【解决方案1】:

    更新:

    根据林肯的评论,新版本 PrettyFaces 3.4.3 支持 JSF 2.3。除了其他更改之外,它现在按照 BalusC 的建议进行 RewriteViewHandler extend ViewHandlerWrapper


    背景:

    PrettyFaces 3.4.2 似乎与 JSF 2.3 不完全兼容。

    非抽象类org.ocpsoft.rewrite.faces.RewriteViewHandler.RewriteViewHandler扩展javax.faces.application.ViewHandler,但不覆盖抽象方法getWebsocketURL

    您可以使用漂亮的面孔和类路径上的 JSF 2.3 API 轻松重现此内容:

    package my.pkg;
    
    import org.ocpsoft.rewrite.faces.RewriteViewHandler;
    
    public class PrettyFacesTest {
        public static void main(String[] args) {
            new RewriteViewHandler(null).getWebsocketURL(null, null);
        }
    }
    

    结果:

    Exception in thread "main" java.lang.AbstractMethodError: org.ocpsoft.rewrite.faces.RewriteViewHandler.getWebsocketURL(Ljavax/faces/context/FacesContext;Ljava/lang/String;)Ljava/lang/String;
        at my.pkg.PrettyFacesTest.main(PrettyFacesTest.java:7)
    

    RewriteViewhandler 注册在rewrite-integration-faces-3.4.2.Final.jar/META-INF/faces-config.xml

    <application>
        <navigation-handler>org.ocpsoft.rewrite.faces.RewriteNavigationHandler</navigation-handler>
        <view-handler>org.ocpsoft.rewrite.faces.RewriteViewHandler</view-handler>
    </application>
    

    我不确定是否有机会阻止此注册。如果是这样,您可以创建一个扩展 RewriteViewHandlerCustomRewriteViewHandler,覆盖 getWebsocketURL 并将调用委托给 super.parent

    import javax.faces.application.ViewHandler;
    import javax.faces.context.FacesContext;
    
    import org.ocpsoft.rewrite.faces.RewriteViewHandler;
    
    public class CustomRewriteViewHandler extends RewriteViewHandler {
        public CustomRewriteViewHandler(ViewHandler viewHandler) {
            super(viewHandler);
        }
    
        @Override
        public String getWebsocketURL(FacesContext context, String channel) {
            return super.parent.getWebsocketURL(context, channel);
        }
    }
    

    然后您将注册这个 CustomRewriteViewHandler 而不是原来的:

    <application>
        <view-handler>my.pkg.CustomRewriteViewHandler</view-handler>
    </application>
    

    正如 BalusC 描述的here,您不能从包含的jar 中阻止faces-config.xml部分。 相反,您可以设置&lt;faces-config ... metadata-complete="true"&gt;,这会导致没有faces-config.xml 或任何包含的jars 中的注释被处理,因此您需要重新定义您自己的faces.config.xml 中所需的所有3d 派对内容。

    【讨论】:

    • 啊,是的,你是对的!谢谢你。我从 github 下载了源代码,看起来模块 rewrite-integration-faces 使用的是 jsf getWebsocketURL 方法甚至在 ViewHandler 中都不存在。我在那里升级了 jsf,并覆盖了它,但无法在 Eclipse 中构建整个东西。如果我得到它会稍后发布。
    • 获取和修改源代码也是一种解决方法,是的。请注意,您必须确保所有构建环境都获取修改后的 jar。
    • PrettyFaces 的正确解决方案是从 ViewHandlerWrapper 扩展而不是 ViewHandler
    • 大家好,感谢您解决这个问题。您能否尝试升级到 Rewrite/PrettyFaces 3.4.3.Final 并让我知道它是否可以解决您的问题?我已经合并了对 JSF 2.3 / EE7 / EE8 API 的基本支持。很快就会发布到 Maven Central。 (可能需要一个通宵的周期,但通常会在几个小时内同步。)
    • @Lincoln 顺便说一句。是 onzinsky 分叉并提交了更改。我只分析并提出了解决方法。
    【解决方案2】:

    @Selaron 检测到,问题在于 PrettyFaces 不支持 JSF 2.3 的 Websocket,因为类 RewriteViewHandler 没有实现方法 getWebsocketURLHere's his solution 解决问题。

    他指出后,我派生了 PrettyFaces (ocpsoft/rewrite),发现根本不支持 JSF 2.3。所以我尝试升级到 JSF 2.3,这似乎比@Selaron 的答案更干净(至少对我来说)。

    Here's the commit 工作的东西。我不会详细说明我必须更改的内容(在提交中进行了解释)。

    最后一件事。正如我在问题中提到的,我曾经在 PrettyFaces 的 pom.xml 中包含的唯一两个依赖项是 the default ones

    但是当我在本地环境中构建项目时,我需要添加更多内容。

    他们来了

    <dependency>
        <groupId>org.ocpsoft.rewrite</groupId>
        <artifactId>rewrite-impl-servlet</artifactId>
        <version>3.4.3-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.ocpsoft.rewrite</groupId>
        <artifactId>rewrite-config-prettyfaces</artifactId>
        <version>3.4.3-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.ocpsoft.rewrite</groupId>
        <artifactId>rewrite-api-servlet</artifactId>
        <version>3.4.3-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.ocpsoft.rewrite</groupId>
        <artifactId>rewrite-annotations-impl</artifactId>
        <version>3.4.3-SNAPSHOT</version>
    </dependency>
    

    从我的 ocpsoft/rewrite 分支克隆/下载,在本地安装项目,并将这些依赖项添加到您的 pom.xml 中应该可以让 PrettyFaces + JSF 2.3 的 websocket 工作。

    PS - 我现在不愿将任何答案标记为已接受。 (我会尝试@Selaron's 然后再决定)。

    【讨论】:

    • 正确的解决方案是让RewriteViewHandler从ViewHandlerWrapper扩展而不是ViewHandler。实际上,所有试图包装名为“Foo”的现有 JSF 工件的 JSF 库都必须从“FooWrapper”而不是从 Foo 扩展(注意“Wrapper”后缀,这是强制性的,它们都依次实现 FacesWrapper)。这将确保当您升级到下一个 JSF API 版本(恰好向 Foo 添加了新方法)时,您不需要在非包装类中手动添加另一组缺失的方法。相反,JSF API 会将这些方法添加到 FooWrapper 类中!
    • 感谢@BalusC。我阅读了您对@Selaron 的回答的第一条评论,并且已经尝试过了,但我得到了Unable to create a new instance of 'org.ocpsoft.rewrite.faces.RewriteViewHandler'。我稍后会尝试解决它。​​
    • 嗨@onzinsky,由于林肯的评论,我更新了我的答案。 PrettyFaces 3.4.3 升级为支持 JSF 2.3,因此应该可以解决您的问题。
    猜你喜欢
    • 2011-10-24
    • 2013-04-24
    • 2013-08-14
    • 2020-12-04
    • 2014-05-10
    • 1970-01-01
    • 2012-12-28
    • 2016-12-03
    • 2020-09-29
    相关资源
    最近更新 更多