【问题标题】:JSF ViewExpiredExceptionHandler NullPointerExceptionJSF ViewExpiredExceptionHandler NullPointerException
【发布时间】:2012-07-24 19:39:44
【问题描述】:

我在 WebSphere Application Server 8 上使用 Apache MyFaces 2。 我想实现一个处理 ViewExpiredException 的自定义 ExceptionHandler。

我使用 BalusC posted 的代码。 工厂在正确的时间被调用,但是在这里调用 handleNavigation 时我得到了 NullPointerException:

public class ViewExpiredExceptionHandler extends ExceptionHandlerWrapper {

    private ExceptionHandler wrapped;

    public ViewExpiredExceptionHandler(ExceptionHandler wrapped) {
        this.wrapped = wrapped;
    }


    @Override
    public void handle() throws FacesException {
        FacesContext facesContext = FacesContext.getCurrentInstance();

        for (Iterator<ExceptionQueuedEvent> iter = getUnhandledExceptionQueuedEvents()
                .iterator(); iter.hasNext();) {
            Throwable exception = iter.next().getContext().getException();

            if (exception instanceof ViewExpiredException) {
                facesContext
                        .getApplication()
                        .getNavigationHandler()
                        .handleNavigation(facesContext, null,
                                "/content/home?faces-redirect=true&expired=true");
                facesContext.renderResponse();
                iter.remove();
            }
        }

        getWrapped().handle();
    }

    @Override
    public ExceptionHandler getWrapped() {
        return wrapped;
    }

}

例外是:

com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0068E: An exception was thrown by one of the service methods of the servlet [Faces Servlet] in application [My_App]. Exception created : [java.lang.NullPointerException
    at org.apache.myfaces.application.NavigationHandlerImpl.getNavigationCase(NavigationHandlerImpl.java:203)
    at org.apache.myfaces.application.NavigationHandlerImpl.handleNavigation(NavigationHandlerImpl.java:77)
    at myapp.ViewExpiredExceptionHandler.handle(ViewExpiredExceptionHandler.java:33)
    at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:191)
    at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1147)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:722)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:449)
    at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.invokeTarget(WebAppFilterChain.java:125)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:92)
    at myapp.auth.RequestFilter.doFilter(RequestFilter.java:35)
    at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:192)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:89)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:919)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1016)
    at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:87)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:886)
    at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1655)
    at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:195)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:452)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:511)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:305)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:276)
    at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
    at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
    at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
    at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
    at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
    at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
    at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
    at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
    at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1650)
]

编辑: 首先 /content 是我的 WebContent 中的一个目录。它不是上下文路径。 我更改了我的代码并使用了这样的外部重定向:

if (exception instanceof ViewExpiredException) {
        String loc = facesContext.getExternalContext()
            .getRequestServletPath();
        try {
            facesContext.getExternalContext().redirect(loc);
            //facesContext.getExternalContext().redirect("/content/home.xhtml");
            //facesContext.getExternalContext().redirect("/");
        } catch (IOException e) {
            e.printStackTrace();
        }
}

但仍然在 facesContext.getExternalContext().redirect 上得到相同的 NullPointerException。 但是 ExternalContext 不为空。我得到了 RequestServletPath。

那么我的代码有什么问题?

最好的问候 - 投票

【问题讨论】:

    标签: java exception jsf-2 session-timeout


    【解决方案1】:

    我收到了一组类似的错误。按照上面的方法,我的手柄导航

    nav.handleNavigation(fc, null, "/error");
    

    返回一个像上面一样的 NPE(甚至相同的行号)。

    如果我修改为只进行重定向,我会得到:

    java.lang.NullPointerException
    at org.apache.myfaces.context.servlet.PartialViewContextImpl.getPartialResponseWriter(PartialViewContextImpl.java:303)
    at org.primefaces.context.PrimePartialViewContext.getPartialResponseWriter(PrimePartialViewContext.java:45)
    at org.apache.myfaces.context.servlet.ServletExternalContextImpl.redirect(ServletExternalContextImpl.java:452)
    at my.package.CustomExceptionHandler.handle(CustomExceptionHandler.java:134)
    at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:191)
    at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1235)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:758)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:441)
    

    在这两种情况下,我认为原因是 getViewRoot() 为 null,这显然不是 'getNavigationCase' 或 getPartialResponseWriter 所期望的。

    我能够使用此博客文章 (http://ovaraksin.blogspot.com/2010/10/jsf-ajax-redirect-after-session-timeout.html) 中的示例进行修复。似乎 Mojarra 和 PrimeFaces(我正在使用带有 MyFaces 的 PrimeFaces 3.5)在出现此错误的情况下存在标准重定向问题。解决方法是

    facescontext.getResponseWriter() == null && facescontext.getRenderKit() == null
    

    而且是部分请求和ajax请求,然后使用RenderKit创建ResponseWriter并设置在facescontext上。

    externalContext.redirect() 然后工作。

    编辑:更具体地说,在博客文章中,SecurityPhaseListener 有一个 doRedirect(FacesContext fc, String redirectPage) 方法,其中包括一个名为:

     // fix for renderer kit (Mojarra's and PrimeFaces's ajax redirect)
    

    我将该部分提升为我从 if (exception instanceof ViewExpiredException) 块调用的重定向响应方法

    编辑 好的,最终解决方案。在http://jira.icesoft.org/browse/ICE-4251 的一小段代码的帮助下,我能够使用句柄导航来实现这一点。这是我从 JIRA 问题中添加的调用,它在 handle() 中执行

    checkViewRoot(facesContext,"/error.jsf");
    

    ... 这是方法

        public static void checkViewRoot( FacesContext ctx, String viewId) {
        if (ctx.getViewRoot() == null) {
            UIViewRoot viewRoot = ctx.getApplication().getViewHandler().createView(ctx, viewId);
            if (viewRoot != null) {
                ctx.setViewRoot(viewRoot);
            }
        }
    }
    

    ... 然后在handle()方法中调用handlenavigation。

        facesContext
                .getApplication()
                .getNavigationHandler()
                .handleNavigation(facesContext, null,
                        (redirectPage != null ? redirectPage : ""));
        facesContext.renderResponse();
    

    请注意,根据我目前的经验,viewId 必须是现有页面,并且与您需要重定向到的页面不同。

    好消息是我使用viewexpiredexception 设置的facesmessage 消息现在显示在新页面上,我之前在重定向时遇到了各种问题。

    【讨论】:

      【解决方案2】:

      "/content/home?faces-redirect=true&amp;expired=true" 显然未被识别为有效的导航案例。由于您的环境的详细信息尚不清楚,因此无法判断其中有什么问题。 /content 是否是上下文路径?如果是这样,那么它应该被省略。真的有/home.xhtml 文件吗?等等。

      如果您仍然无法弄清楚,那么发送重定向可能更容易,因为您似乎在重定向之后。

      externalContext.redirect("/content/home.xhtml?expired=true");
      

      请注意,如果 URL 无效,这仍会导致 404,但可能更容易为您找出。

      【讨论】:

      • 我尝试使用它,但仍然得到相同的异常。 (见我编辑的问题)
      • 您不可能获得相同的 NPE。或者你根本没有注意堆栈跟踪?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-28
      • 1970-01-01
      • 2020-08-31
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多