2012-07-26 38 views
0

我在WebSphere Application Server 8上使用Apache MyFaces 2。 我想實現一個處理ViewExpiredException的自定義ExceptionHandler。JSF ViewExpiredExceptionHandler NullPointerException

我使用的代碼是BalusC posted。 工廠被稱爲在正確的時間,但我得到一個NullPointerException異常時handleNavigation這裏稱爲:

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

編輯: 首先/內容是目錄在我的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相同的NullPointerException()重定向。 但ExternalContext不爲null。我得到了RequestServletPath。

那麼我的代碼在這裏怎麼了?

最好的問候 - veote

回答

1

"/content/home?faces-redirect=true&expired=true"顯然不被視爲一個有效的導航情況。由於您的環境細節尚不清楚,因此不可能說出那裏有什麼問題。上下文路徑是否爲/content?如果是這樣,那麼它應該被省略。有沒有一個/home.xhtml文件?等等。

如果您仍然無法弄清楚,那麼它可能更容易,你似乎是一個重定向後,反正只是發送重定向。

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

請注意,如果URL無效,這仍然會導致404錯誤,但它可能更容易爲您找到。

+0

我試過使用這個,但仍然得到相同的異常。 (見我編輯的問題) – veote 2012-07-27 07:10:53

+0

你可能不可能獲得相同的NPE。或者你沒有注意到堆棧跟蹤? – BalusC 2012-07-27 11:39:24

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(我正在使用PrimeFaces 3.5和MyFaces)在這個錯誤的情況下與標準重定向有問題。解決方法是在該情況下

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一條代碼的幫助下,我能夠使用handlenavigation實現這一點。下面是我從JIRA問題添加了調用,它被在手柄()

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); 
     } 
    } 
} 

... 而在這之後,handlenavigation被在handle()方法中調用。

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

注意,在我的經驗到目前爲止,viewId必須是現有的頁面,比一個不同的你需要它重新定向。

好的事情是facesmessage我設置了viewexpiredexception消息現在顯示在新的頁面上,我以前有過各種麻煩,重定向。

相關問題