简体   繁体   English

Websocket + Pretty Faces = AbstractMethodError

[英]Websocket + Pretty Faces = AbstractMethodError

I'm building a simple JSF 2.3 app in tomcat 8.5.我正在 tomcat 8.5 中构建一个简单的 JSF 2.3 应用程序。 I got the websocket working, and then I added Pretty Faces.我让 websocket 工作,然后我添加了 Pretty Faces。

If I use them separately, they both work.如果我单独使用它们,它们都可以工作。 I mean, if I remove Pretty Faces' dependencies from the pom, my websocket works.我的意思是,如果我从 pom 中删除 Pretty Faces 的依赖项,我的 websocket 就可以工作。 And if I keep the dependencies, and remove the <f:websocket> from my view, Pretty Faces work (redirects ok)!如果我保留依赖关系,并从我的视图中删除<f:websocket> ,Pretty Faces 工作(重定向正常)!

But, if I try to use Pretty Faces, while I have a <f:websocket> in a view, AbstractMethodError appears when I navigate to it.但是,如果我尝试使用 Pretty Faces,当我在视图中有一个<f:websocket>时,当我导航到它时会出现AbstractMethodError Literally, if I comment the tag, everything else works.从字面上看,如果我评论标签,其他一切都有效。

I use mojarra.我用莫哈拉。 In my pom, I'm using the dependecies from https://github.com/javaserverfaces/mojarra/blob/master/README.md , and the default ones for Pretty Faces.在我的 pom 中,我使用来自https://github.com/javaserverfaces/mojarra/blob/master/README.md的依赖,以及 Pretty Faces的默认依赖。

I'm guessing the problem is either that I have conflicting dependencies, from what I read in this BalusC answer , or that Pretty Faces and Websocket conflict somehow.我猜问题是我有冲突的依赖关系,从我在这个 BalusC 答案中读到的内容,或者 Pretty Faces 和 Websocket 以某种方式发生冲突。

Any help would be appreciated.任何帮助,将不胜感激。 Thanks in advance.提前致谢。

Here the dependencies这里的依赖

<!-- 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>

Here the exception这里例外

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)

Update:更新:

As per Lincoln's comment the new release PrettyFaces 3.4.3 supportes JSF 2.3.根据林肯的评论,新版本PrettyFaces 3.4.3支持 JSF 2.3。 Beside other changes it now makes the RewriteViewHandler extend ViewHandlerWrapper as suggested by BalusC.除了其他更改之外,它现在使RewriteViewHandler按照 BalusC 的建议扩展ViewHandlerWrapper


Background:背景:

It looks like PrettyFaces 3.4.2 is not fully compatible with JSF 2.3.看起来 PrettyFaces 3.4.2 与 JSF 2.3 不完全兼容。

The non abstract class org.ocpsoft.rewrite.faces.RewriteViewHandler.RewriteViewHandler extends javax.faces.application.ViewHandler but does not override the abstract method getWebsocketURL .非抽象 class org.ocpsoft.rewrite.faces.RewriteViewHandler.RewriteViewHandler扩展javax.faces.application.ViewHandler但不覆盖抽象方法getWebsocketURL

You can easily reproduce this with pretty faces and JSF 2.3 API on class path:您可以在 class 路径上使用漂亮的面孔和 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);
    }
}

Result:结果:

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)

The RewriteViewhandler is registered in the rewrite-integration-faces-3.4.2.Final.jar/META-INF/faces-config.xml : RewriteViewhandlerrewrite-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>

I'm not sure if there's chance to prevent this registration.我不确定是否有机会阻止此注册。 If so you could create a CustomRewriteViewHandler that extends RewriteViewHandler , overrides getWebsocketURL and delegates that call to super.parent :如果是这样,您可以创建一个扩展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);
    }
}

You'd then register this CustomRewriteViewHandler instead of the original one:然后,您将注册此 CustomRewriteViewHandler 而不是原来的:

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

As BalusC describes here you cannot block parts of faces-config.xml from the included jar .正如 BalusC在这里描述的那样,您不能从包含的jar中阻止faces-config.xml部分内容。 Instead you can set <faces-config... metadata-complete="true"> which results in none faces-config.xml nor annotations in any included jar s being processed so coming at the cost that you'd need to redefine all the 3d party stuff needed in your own faces.config.xml .相反,您可以设置<faces-config... metadata-complete="true">这会导致没有faces-config.xml或任何包含的jar中的注释正在处理,因此您需要重新定义所有您自己的faces.config.xml中需要的 3d 派对的东西。

As @Selaron detected, the problem was that PrettyFaces does not support JSF 2.3's Websocket, since the class RewriteViewHandler does not implement the method getWebsocketURL .正如@Selaron 检测到的,问题是 PrettyFaces 不支持 JSF 2.3 的 Websocket,因为getWebsocketURL RewriteViewHandler没有实现该方法。 Here's his solution to the problem.这是他解决问题的方法。

Once he pointed it out, I forked PrettyFaces ( ocpsoft/rewrite ) and discovered there was no support for JSF 2.3 at all.一旦他指出来,我就分叉了 PrettyFaces ( ocpsoft/rewrite ),发现根本不支持 JSF 2.3。 So I tried and upgrade to JSF 2.3, which seemed cleaner (at least to me) than @Selaron's answer.所以我尝试升级到 JSF 2.3,这似乎比@Selaron 的答案更干净(至少对我而言)。

Here's the commit of the thing working. 这是工作的提交 I won't get into the specifics of what I had to change (which are explained in the commit).我不会详细说明我必须更改的内容(在提交中进行了解释)。

One last thing.最后一件事。 As I mentioned in my question, the only two dependencies I used to include in my pom.xml for PrettyFaces are the default ones .正如我在问题中提到的,我曾经在我的pom.xml for PrettyFaces 中包含的唯一两个依赖项是默认依赖项。

But when I build the project in my local environment, I needed to add some more.但是当我在本地环境中构建项目时,我需要添加更多内容。

Here they are他们来了

<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>

Cloning/downloading from my branch of ocpsoft/rewrite, installing the project locally, and adding those dependencies into your pom.xml should allow you to make PrettyFaces + JSF 2.3's websocket to work.从我的 ocpsoft/rewrite 分支克隆/下载,在本地安装项目,并将这些依赖项添加到您的pom.xml应该允许您让 PrettyFaces + JSF 2.3 的 ZBF56D570E62CDB561 到 2.3 工作。

PS - I am reticent to mark any of the answers as accepted right now. PS - 我现在不愿将任何答案标记为已接受。 (I'll give a try to @Selaron's and decide then). (我会尝试@Selaron's 然后再决定)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM