自定义NavigationHandler无法强制转换为javax.faces.application.ConfigurableNavigationHandler

时间:2011-04-12 09:10:37

标签: java jsf jsf-2 primefaces

previous question之后,我有一个问题,如果我在faces-config.xml中注册RedirectNavigationHandler后使用来自primefaces的<p:button>,为什么会抛出此异常。 :

SEVERE: Error Rendering View[/TBrowse.xhtml]
java.lang.ClassCastException: my.package.RedirectNavigationHandler cannot be cast to javax.faces.application.ConfigurableNavigationHandler
        at org.primefaces.component.button.ButtonRenderer.findNavigationCase(ButtonRenderer.java:114)
        at org.primefaces.component.button.ButtonRenderer.buildOnclick(ButtonRenderer.java:90)
        at org.primefaces.component.button.ButtonRenderer.encodeMarkup(ButtonRenderer.java:56)
        at org.primefaces.component.button.ButtonRenderer.encodeEnd(ButtonRenderer.java:38)
        at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:883)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1659)
        at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
        at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:853)
        at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:304)
        at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185)
        at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:129)
        at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:853)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1652)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1655)
        at org.primefaces.component.tabview.TabViewRenderer.encodeContents(TabViewRenderer.java:177)
        at org.primefaces.component.tabview.TabViewRenderer.encodeMarkup(TabViewRenderer.java:120)
        at org.primefaces.component.tabview.TabViewRenderer.encodeEnd(TabViewRenderer.java:61)
        at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:883)
        at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:59)
        at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:43)
        at org.primefaces.component.panel.PanelRenderer.encodeContent(PanelRenderer.java:229)
        at org.primefaces.component.panel.PanelRenderer.encodeMarkup(PanelRenderer.java:152)
        at org.primefaces.component.panel.PanelRenderer.encodeEnd(PanelRenderer.java:75)
        at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:883)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1659)
        at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
        at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:853)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1652)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1655)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1655)
        at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:399)
        at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
        at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
        at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:541)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:383)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:288)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
unhandled exception : java.lang.ClassCastException: my.package.RedirectNavigationHandler cannot be cast to javax.faces.application.ConfigurableNavigationHandler
cause exception : java.lang.ClassCastException: my.package.RedirectNavigationHandler cannot be cast to javax.faces.application.ConfigurableNavigationHandler, cause exception is BE : false

使用<p:commandButton>很好,但<p:button>不是这样。

这是我的faces-config.xml摘录:

<application>
   ...
   <navigation-handler>id.co.sofcograha.RedirectNavigationHandler</navigation-handler>
   ...
</application>

代码:

import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;

public class RedirectNavigationHandler extends NavigationHandler {
    private NavigationHandler parent;

    public RedirectNavigationHandler(NavigationHandler parent) {
        this.parent = parent;
    }

    @Override
    public void handleNavigation(FacesContext context, String from, String outcome) {
        if (outcome != null && !outcome.trim().equals("") && !outcome.endsWith("?faces-redirect=true")) {
            System.out.println("adding faces redirect for " + outcome);
            outcome += "?faces-redirect=true";
        }

        parent.handleNavigation(context, from, outcome);        
    }
}

这是maven依赖项:

<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-api</artifactId>
    <version>2.0.4-b09</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-impl</artifactId>
    <version>2.0.4-b09</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.primefaces</groupId>
    <artifactId>primefaces</artifactId>
    <version>2.2.1</version>
</dependency>

关于此事的任何想法?

谢谢!

1 个答案:

答案 0 :(得分:4)

对于JSF 2.0,你显然应该扩展ConfigurableNavigationHandler

  

ConfigurableNavigationHandler扩展了NavigationHandler的合同,允许运行时检查构成导航规则库的NavigationCases。符合引入此类(或更高版本)的规范版本的实现必须使其NavigationHandler成为此类的扩展。

(强调我的)这是NavigationHandler javadoc中没有提到/警告的方式,所以我在前一个问题中完全忽略了这一点。

以下是你如何做到的:

package com.example;

import java.util.Map;
import java.util.Set;

import javax.faces.application.ConfigurableNavigationHandler;
import javax.faces.application.NavigationCase;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;

public class RedirectNavigationHandler extends ConfigurableNavigationHandler {

    private NavigationHandler parent;

    public RedirectNavigationHandler(NavigationHandler parent) {
        this.parent = parent;
    }

    @Override
    public void handleNavigation(FacesContext context, String from, String outcome) {
        if (!outcome.endsWith("?faces-redirect=true")) {
            outcome += "?faces-redirect=true";
        }

        parent.handleNavigation(context, from, outcome);        
    }

    @Override
    public NavigationCase getNavigationCase(FacesContext context, String fromAction, String outcome) {
        if (parent instanceof ConfigurableNavigationHandler) {
            return ((ConfigurableNavigationHandler) parent).getNavigationCase(context, fromAction, outcome);
        } else {
            return null;
        }
    }

    @Override
    public Map<String, Set<NavigationCase>> getNavigationCases() {
        if (parent instanceof ConfigurableNavigationHandler) {
            return ((ConfigurableNavigationHandler) parent).getNavigationCases();
        } else {
            return null;
        }
    }

}
相关问题