DynaView causes NPE in PrimeExceptionHandler

Splash Forums PrettyFaces Users DynaView causes NPE in PrimeExceptionHandler

Tagged: 

This topic contains 7 replies, has 2 voices, and was last updated by  Christian Kaltepoth 1 year, 7 months ago.

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #26654

    delomer
    Participant

    Hello,

    I don’t now if this is a Primefaces (5.1) or PrettyFaces (3.3.3) bug, but if we use both together the PrimeExceptionHandler throws a NullPointerException because FacesContext is null!

    The NPE only occurs if we use DynaViews like this:

    
    <url-mapping id="view-2-mapping">
        <pattern value="/view/2" />
        <view-id value="#{dispatcher.getViewPath}" />
    </url-mapping>
    

    And the dispatcher bean:

    @RequestScoped
    @Named
    public class Dispatcher {
      public String getViewPath() {
        return "/faces/view2.xhtml";
      }
    }

    The PrimeExceptionHandler is called 3 times per request:
    1. in restore-view-phase
    2. in render-response-phase
    3. and again in restore-view-phase but now the FacesContext is null!

    If i change the mapping like this, the PrimeExceptionHandler is only called twice and FacesContext is never null:

      <url-mapping id="view-1-mapping">
        <pattern value="/view/1" />
        <view-id value="/faces/view1.xhtml" />
      </url-mapping>

    Thanks for your help!

    #26655

    Why is the PrimefacesExceptionHandler? Looks like the NPE is just hiding the real issue.

    #26657

    delomer
    Participant

    I agree, but the question is why is the FacesContext null at this point, and why it doesn’t happen without DynaView?

    #26659

    That’s a good question. How does Primefaces obtain the FacesContext?

    Could you please post the full stacktrace of the NPE.

    #26661

    delomer
    Participant

    The stacktrace looks like this:

    2014-12-19 12:17:26,253 ERROR (http-/0.0.0.0:8080-1) [UID=,REQ=#] [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/sample-web-jsf].[default]] JBWEB000236: Servlet.service() for servlet default threw exception: java.lang.NullPointerException
    	at org.primefaces.application.exceptionhandler.PrimeExceptionHandler.handle(PrimeExceptionHandler.java:70)
    	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119)
    	at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116)
    	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    	at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:145)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:832)
    	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:620)
    	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:553)
    	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:482)
    	at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:119)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149)
    	at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:336)
    	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
    	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653)
    	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:920)
    	at java.lang.Thread.run(Thread.java:724)
    

    The attached project contains two mappings:
    http://localhost:8080/sample/view/1 => works fine
    http://localhost:8080/sample/view/2 => works, but causes a NPE in server.log!

    Attachments:
    1. sample-web-jsf.zip
    #26664

    I’ve no idea what is causing this. The stacktrace clearly shows, that the PrimeExceptionHandler is invoked during the JSF lifecycle. So I see no reason why FacesContext.getCurrentInstance() could return null. Which application server are you deploying to. Perhaps some JSF implementation specific bug?

    However, as you may or may not know, PrettyFaces is now part of the Rewrite framework. I strongly recommend to migrate your app to Rewrite. This is very easy if you use the PrettyFaces Compatibility Module as described here:

    http://ocpsoft.org/rewrite/docs/migration/prettyfaces3

    With Rewrite you can do such things as determining to which URL you want to forward very easily. See the examples here:

    http://ocpsoft.org/rewrite/examples/

    #26665

    delomer
    Participant

    OK thank you Christian, i will try to migrate to Rewrite.
    But i can’t find any exmaples that show how to determine the view-id at runtime with Rewrite?

    How do I make this pretty-faces configuration with Rewrite?

    <url-mapping id="view-2-mapping">
        <pattern value="/view/2" />
        <view-id value="#{dispatcher.getViewPath}" />
    </url-mapping>
    #26669

    Basically, the inbound part of a rule that forwards an incoming request to some internal URL, looks like this:

    .addRule()
    .when(Direction.isInbound().and(Path.matches("/view/2")))
    .perform(Forward.to("/faces/view.xhtml"))
    

    You can now just created your own HttpOperation which does some calculation upfront to determine which view to forward to. This could look like this:

    .addRule()
    .when(Direction.isInbound().and(Path.matches("/view/2")))
    .perform(new HttpOperation() {
       @Override
       public void performHttp(HttpServletRewrite event, EvaluationContext context)
       {
          
          String viewId = ....;
          
          Forward.to(viewId).perform(event, context);
          
       }
    })
    

    I hope this helps.

Viewing 8 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic.

Comments are closed.