14 Replies Latest reply on Jun 11, 2010 1:23 AM by nickarls

    CDI timeout results in an NPE

    bleathem

      Is there a way (in JSF 2) to catch a Conversation timeout and redirect a user to a new page? I'm getting nasty NullPointerExceptions when the conversation times out.


      I could redirect the user on all NPE's, but that seems like too big a net.

        • 1. Re: CDI timeout results in an NPE
          pmuir

          Nothing specific. But this sounds like a bug in Weld (bad exception).


          Could you post the stack trace and how to reproduce?

          • 2. Re: CDI timeout results in an NPE
            bleathem

            Ok, here's some code showing the behavior (anywhere I can upload a maven project?)


            2 Classes:



            1. Model.java - a single Integer value property.

            2. WebBean.java - a conversation scoped managed bean, with a Model property.



            2 JSF pages:



            1. index.xhtml - initialize the Model property of WebBean, and go to add.xhtml

            2. add.xhtml - click the increment button to increment the value property of Model



            Run the app, initialize the value property of Model, then click the increment button.  All is well so long as you click the increment button before the conversation timeout.  If the conversation time's out first, you get an NPE because the new instance of WebBean does not have a valid Model property.


            A contrived example, but it demonstrates the problem.


            Classes and xhtml files:


            Model.java:


            package example;
            
            public class Model {
                private Integer value;
            
                public Integer getValue() {
                    return value;
                }
            
                public void setValue(Integer value) {
                    this.value = value;
                }
            
            }
            



            WebBean.java


            package example;
            
            import java.io.Serializable;
            import javax.enterprise.context.Conversation;
            import javax.enterprise.context.ConversationScoped;
            import javax.inject.Inject;
            import javax.inject.Named;
            
            @Named
            @ConversationScoped
            public class WebBean implements Serializable {
                private static final long serialVersionUID = 1L;
            
                private Model model;
                private Integer startValue;
                @Inject
                private Conversation conversation;
            
                public Model getModel() {
                    return model;
                }
            
                public void setModel(Model model) {
                    this.model = model;
                }
            
                public Integer getStartValue() {
                    return startValue;
                }
            
                public void setStartValue(Integer startValue) {
                    this.startValue = startValue;
                }
            
                public String initialize() {
                    model = new Model();
                    model.setValue(startValue);
                    if (conversation.isTransient()) {
                        conversation.begin();
                        conversation.setTimeout(3000);
                    }
                    return "add";
                }
            
                public void increment() {
                    model.setValue(model.getValue() + 1);
                }
            
            }
            



            index.xhtml


            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml"
                  xmlns:f="http://java.sun.com/jsf/core"
                  xmlns:h="http://java.sun.com/jsf/html"
                  lang="en" xml:lang="en">
                <f:view>
                    <h:head>
                        <title>Test</title>
                    </h:head>
            
                    <h:body>
                        <h:form>
                            <h:inputText value="#{webBean.startValue}"/>
                            <br />
                            <h:commandButton value="Initialize" action="#{webBean.initialize}" />
                        </h:form>
                    </h:body>
                </f:view>
            </html>
            



            add.xhtml


            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml"
                  xmlns:f="http://java.sun.com/jsf/core"
                  xmlns:h="http://java.sun.com/jsf/html"
                  lang="en" xml:lang="en">
                <f:view>
                    <h:head>
                        <title>Test</title>
                    </h:head>
            
                    <h:body>
                        <h:form>
                            <h:outputText value="#{webBean.model.value}"/>
                            <br />
                            <h:commandButton value="Increment" action="#{webBean.increment}" />
                        </h:form>
                    </h:body>
                </f:view>
            </html>
            

            • 3. Re: CDI timeout results in an NPE
              bleathem

              I can think of two workarounds, both are kind of ugly:



              1. Have an actionListener on the increment button that throws an AbortProcessingException if #{webBean.model} is null, and re-routes to the index page using the NavigationHandler




              1. Similar to 1), but do this in a PhaseListener.  Advantage of catching the error condition in an earlier phase, but invades the whole app.



              I never used Seam 2, but I was under the impression you could specify a page to navigate to when a conversation times out.  Something like that is what I am looking for with Weld/CDI - or maybe Seam 3?


              Thanks,
              Brian Leathem

              • 4. Re: CDI timeout results in an NPE
                pmuir

                Can you post the stack trace of the NPE?

                • 5. Re: CDI timeout results in an NPE
                  hirowla.ian.rowlands.three.com.au

                  One way I do this is to write my own JSF ExceptionHandler. There is an article from a Sun guy (forgotten his name) on how to do this - basically it involves writing an extension of ExceptionHandlerWrapper, and getting the ExceptionHandlerFactory to create your exception handler rather than it's own. Actually you write your own factory, and register that as the exception factory to use. Anyway, I copied it from this article!


                  Once you have that, you can catch all errors - particularly ContextException and ViewExpiredException. I redirect those exceptions back to the main page - they usually happen when there is a session timeout, or when a wrong (or timed out) conversation is restored. Other exceptions you can redirect to a custom error page if you like.


                  Regards,


                  Ian

                  • 6. Re: CDI timeout results in an NPE
                    bleathem

                    Sorry Pete, I forgot you asked for the stacktrace:




                    WARNING: WELD-000301 Could not restore long-running conversation 2 because id not known
                    SEVERE: java.lang.NullPointerException
                    javax.faces.el.EvaluationException: java.lang.NullPointerException
                            at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
                            at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
                            at javax.faces.component.UICommand.broadcast(UICommand.java:315)
                            at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:775)
                            at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1267)
                            at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)
                            at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
                            at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
                            at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
                            at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
                            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
                            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
                            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
                            at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
                            at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
                            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
                            at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
                            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:233)
                            at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
                            at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
                            at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
                            at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
                            at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
                            at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
                            at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
                            at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
                            at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
                            at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
                            at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
                            at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
                            at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
                            at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
                            at java.lang.Thread.run(Thread.java:637)
                    Caused by: java.lang.NullPointerException
                            at example.WebBean.increment(WebBean.java:55)
                            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                            at java.lang.reflect.Method.invoke(Method.java:597)
                            at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:113)
                            at example.WebBean_$$_javassist_104.increment(WebBean_$$_javassist_104.java)
                            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                            at java.lang.reflect.Method.invoke(Method.java:597)
                            at com.sun.el.parser.AstValue.invoke(AstValue.java:234)
                            at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
                            at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43)
                            at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:72)
                            at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:98)
                            at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
                            ... 32 more
                    
                    WARNING: #{webBean.increment}: java.lang.NullPointerException
                    javax.faces.FacesException: #{webBean.increment}: java.lang.NullPointerException
                            at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
                            at javax.faces.component.UICommand.broadcast(UICommand.java:315)
                            at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:775)
                            at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1267)
                            at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)
                            at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
                            at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
                            at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
                            at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
                            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
                            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
                            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
                            at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
                            at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
                            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
                            at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
                            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:233)
                            at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
                            at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
                            at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
                            at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
                            at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
                            at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
                            at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
                            at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
                            at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
                            at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
                            at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
                            at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
                            at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
                            at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
                            at java.lang.Thread.run(Thread.java:637)
                    Caused by: javax.faces.el.EvaluationException: java.lang.NullPointerException
                            at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
                            at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
                            ... 31 more
                    Caused by: java.lang.NullPointerException
                            at example.WebBean.increment(WebBean.java:55)
                            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                            at java.lang.reflect.Method.invoke(Method.java:597)
                            at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:113)
                            at example.WebBean_$$_javassist_104.increment(WebBean_$$_javassist_104.java)
                            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                            at java.lang.reflect.Method.invoke(Method.java:597)
                            at com.sun.el.parser.AstValue.invoke(AstValue.java:234)
                            at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
                            at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43)
                            at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:72)
                            at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:98)
                            at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
                            ... 32 more
                    
                    WARNING: StandardWrapperValve[FacesServlet]: PWC1406: Servlet.service() for servlet FacesServlet threw exception
                    javax.faces.el.EvaluationException: java.lang.NullPointerException
                            at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
                            at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
                            at javax.faces.component.UICommand.broadcast(UICommand.java:315)
                            at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:775)
                            at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1267)
                            at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)
                            at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
                            at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
                            at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
                            at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
                            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
                            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
                            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
                            at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
                            at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
                            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
                            at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
                            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:233)
                            at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
                            at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
                            at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
                            at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
                            at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
                            at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
                            at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
                            at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
                            at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
                            at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
                            at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
                            at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
                            at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
                            at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
                            at java.lang.Thread.run(Thread.java:637)
                    Caused by: java.lang.NullPointerException
                            at example.WebBean.increment(WebBean.java:55)
                            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                            at java.lang.reflect.Method.invoke(Method.java:597)
                            at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:113)
                            at example.WebBean_$$_javassist_104.increment(WebBean_$$_javassist_104.java)
                            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                            at java.lang.reflect.Method.invoke(Method.java:597)
                            at com.sun.el.parser.AstValue.invoke(AstValue.java:234)
                            at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
                            at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43)
                            at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:72)
                            at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:98)
                            at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
                            ... 32 more
                    
                    
                    



                    • 7. Re: CDI timeout results in an NPE
                      bleathem

                      Thanks Ian, I like your approach.  The problem is that the only exception I can target with my custom ExceptionHandler is an NPE.  This is a little too broad a net to trap like this.


                      I suppose I could throw a custom exception in the getter of my model, and use the ExceptionHandler sensibly redirect the user when I catch that custom exception.  Still seems kind of gross, Weld throwing some kind of a CoversationExpired exception would be much easier to work with.


                      Brian

                      • 8. Re: CDI timeout results in an NPE
                        hirowla.ian.rowlands.three.com.au

                        Probably a null exception in Weld is not a good thing, and hence you should raise an issue for it (like you have).


                        My approach works when you get a ConversationExpired exception, so when you start getting that you'll be fine.


                        One catch with my approach - maybe somebody could suggest how to do this? If I get an exception when constructing a @ConversationScoped bean (in particular, in the @PostConstruct method) I get a Weld conversation error. My exception handler catches the original exception, but cannot catch the Weld conversation error and hence I cannot redirect it. Any ideas on how to deal with that? Should Weld be throwing this exception at this point?


                        Ian


                        • 9. Re: CDI timeout results in an NPE
                          nickarls

                          Yes please file a JIRA, the sooner you do the sooner we can fix it in trunk because I don't think there ever will be a good workaround for a NPE at that level...

                          • 10. Re: CDI timeout results in an NPE
                            bleathem
                            • 11. Re: CDI timeout results in an NPE
                              nickarls

                              Brian Leathem wrote on Jun 08, 2010 09:54:


                              Here's the jira issue:
                              https://jira.jboss.org/browse/WELD-550 Link


                              Thanks for the report. Could you check out trunk because I couldn't reproduce it with that, it throws an NonExistentConversationException without traces of NPE:s. There were changes to the conversation management since 1.0.0, though.

                              • 12. Re: CDI timeout results in an NPE
                                bleathem

                                Thanks, I'll give it a shot as soon as I figure out how to replace the weld implementation in my glassfish install.

                                • 13. Re: CDI timeout results in an NPE
                                  bleathem

                                  For anyone who's following along, here's a link describing how to build weld, and integrate it into glassfish (involves building glassfish too).


                                  http://wiki.glassfish.java.net/Wiki.jsp? page=V3Jsr299JavaContextsAndDependencyInjectionIntegration

                                  • 14. Re: CDI timeout results in an NPE
                                    nickarls

                                    I heard this guy tried that with a clean local repository.