13 Replies Latest reply on Mar 14, 2007 12:30 PM by Leo Baschy

    since today (JBSEAM-954?) I get NPE in setEntityManagerFlush

    Leo Baschy Novice

      Calls to changeFlushMode that get passed a null flushMode from a null actualFlushMode?

      I haven't changed anything that seems related, but upgrade to a build we make from CVS.

      In class ManagedPersistenceContect method setEntityManagerFlushMode() throws a NullPointerException.

      I dont think you need to know it is in a

      @Name("authenticator")
      public class Authenticator {
      
       @In
       EntityManager entityManager;
      
      ...


      You probably want the stack trace

      13:47:20,593 ERROR [SeamPhaseListener] uncaught exception
      java.lang.NullPointerException
       at org.jboss.seam.core.ManagedPersistenceContext.setEntityManagerFlushMode(ManagedPersistenceContext.java:228)
       at org.jboss.seam.core.ManagedPersistenceContext.changeFlushMode(ManagedPersistenceContext.java:222)
       at org.jboss.seam.core.PersistenceContexts.changeFlushMode(PersistenceContexts.java:67)
       at org.jboss.seam.core.PersistenceContexts.afterRender(PersistenceContexts.java:81)
       at org.jboss.seam.jsf.AbstractSeamPhaseListener.afterRender(AbstractSeamPhaseListener.java:233)
       at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:116)
       at org.apache.myfaces.lifecycle.PhaseListenerManager.informPhaseListenersAfter(PhaseListenerManager.java:89)
       at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:391)
       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:138)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:63)
       at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
       at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
       at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:57)
       at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
       at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:79)
       at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
       at org.jboss.seam.web.SeamFilter.doFilter(SeamFilter.java:84)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.ajax4jsf.framework.ajax.xmlfilter.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:67)
       at org.ajax4jsf.framework.ajax.xmlfilter.BaseFilter.doFilter(BaseFilter.java:223)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
       at org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
       at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
       at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
       at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
       at java.lang.Thread.run(Thread.java:595)


      The real reason seems to be that the in PersistenceContexts there are calls to methods changeFlushMode that get passed a null flushMode from a null actualFlushMode.

      Oddly in the debugger I see calls to afterRender before beforeRender, but don't take my word for it.

      I might have mistinterpreted what I saw in debugger, because it didn't link up all symbols right this time.

      I need a quick workaround or I'll get fried here for running Seam from CVS :(

      Can I in PersistenceContexts make that

      private FlushModeType flushMode = FlushModeType.AUTO;
       private FlushModeType actualFlushMode = FlushModeType.AUTO;


      ?

        • 1. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
          Gavin King Master

          I would love to know how you managed to produce this. I dont understand how PersistenceContexts.afterRender() could get called w/o an earlier call to beforeRender().

          Perhaps if an exception occurred?

          • 2. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
            Leo Baschy Novice

            Importantly to my well being in put in that

            private FlushModeType actualFlushMode = FlushModeType.AUTO;


            and now I'm running without crashes.

            When I'm out of trouble for the afternoon I'll look again.

            One hint how I got there might be: Page action returns outcome, navigation rule makes it redirect to another page. Not sure about details though.

            And it happens during a login redirection that I've been mentioning I'm working on. Not sure though whether that makes/made any difference.

            • 3. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
              Leo Baschy Novice

              I know I've suggested the exact wording, but my consciousness will bug me if I don't mention the following. If the fix instead of

              private FlushModeType actualFlushMode = FlushModeType.AUTO;


              would write to the same effect

              private FlushModeType actualFlushMode = flushMode;


              then it would be more stable in case someone two years from now changes the default flush mode or even just tries understanding the logic.

              • 4. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                Leo Baschy Novice

                Trying to answer Gavin's question how I get this.

                To be clear, the NPE is gone with actualFlushMode not being null any more.

                For completeness of record let's mention I'm now running the 2nd patch of JBSEAM-1009 on a build we did from a CVS pull on Friday.

                When starting up the server and having a breakpoint both in PersistenceContexts afterRender() and beforeRender(), then when for the first time trying to log in, resulting in a redirect to a login page, I get the first break in afterRender(), not in beforeRender():

                Thread [http-0.0.0.0-8080-1] (Suspended (breakpoint at line 87 in PersistenceContexts))
                 PersistenceContexts.afterRender() line: 87
                 TransactionalSeamPhaseListener(AbstractSeamPhaseListener).afterRender(FacesContext) line: 233
                 TransactionalSeamPhaseListener(SeamPhaseListener).afterPhase(PhaseEvent) line: 116
                 PhaseListenerManager.informPhaseListenersAfter(PhaseId) line: 89
                 LifecycleImpl.render(FacesContext) line: 391
                 FacesServlet.service(ServletRequest, ServletResponse) line: 138
                 ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 252
                 ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 173
                 SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 63
                 RedirectFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 45
                 SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 49
                 ExceptionFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 57
                 SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 49
                 MultipartFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 79
                 SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 49
                 SeamFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 84
                 ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 202
                 ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 173
                 TidyXMLFilter(BaseXMLFilter).doXmlFilter(FilterChain, HttpServletRequest, HttpServletResponse) line: 67
                 Filter(BaseFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 223
                 ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 202
                 ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 173
                 ReplyHeaderFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 96
                 ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 202
                 ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 173
                 StandardWrapperValve.invoke(Request, Response) line: 213
                 StandardContextValve.invoke(Request, Response) line: 178
                 SecurityAssociationValve.invoke(Request, Response) line: 175
                 NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 432
                 JaccContextValve.invoke(Request, Response) line: 74
                 StandardHostValve.invoke(Request, Response) line: 126
                 ErrorReportValve.invoke(Request, Response) line: 105
                 CachedConnectionValve.invoke(Request, Response) line: 156
                 StandardEngineValve.invoke(Request, Response) line: 107
                 CoyoteAdapter.service(Request, Response) line: 148
                 Http11Processor.process(InputStream, OutputStream) line: 869
                 Http11Protocol$JmxHttp11ConnectionHandler(Http11BaseProtocol$Http11ConnectionHandler).processConnection(TcpConnection, Object[]) line: 664
                 PoolTcpEndpoint.processSocket(Socket, TcpConnection, Object[]) line: 527
                 MasterSlaveWorkerThread.run() line: 112
                 ThreadWithAttributes(Thread).run() line: 595


                The FacesContext on the stack in its external context shows we're still at the original page, the one that requires the login.

                My best guess is that maybe because in Pages method enterPage() if there is a redirectToLoginView() then the page.enter() isn't called.

                Whether there is a significant difference in that behavior with or without JBSEAM-1009 I can't grasp for sure, but it seems even without 1009 there will be a call to redirectToLoginView() without calling page.enter().

                So the answer would be you can get there with a redirectToLoginView().

                Does that answer the question? If still needed, I can offer my Eclipse to debug with simple remote login to a URL in the browser, Windows and Mac.

                • 5. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                  Gavin King Master

                  No it does not answer the question. No way should JSF ever call afterPhase() without a prior beforePhase(). And there is no other exit point (apart from exceptions) from beforeRender().

                  • 6. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                    Leo Baschy Novice

                    Not 100% confirmed, but I think I got a reproducible case:

                    Don't have a login-required for a page, but for the page have a s:hasRole or s:hasPermission that consequentially throws a different exception than what you probably have been expecting.

                    Meanwhile though ... I'm having a heck of a time getting the patch right for JBSEAM-1009. Because the DTD says <!ATTLIST page login-required (true|false) "false"> we're getting from dom4j element.attribute().getValue() or element.attributeValue() a "false" even if the attribute isn't there.

                    Any way to tell (the dom4j way) whether attribute login-required has been set explicitely?

                    I've been a JDOM user for years, without DTDs. Wrote XML parser before that, not a dummy. But this automatic fixing up things curtesy of DTD is a bit unnerving.

                    • 7. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                      Gavin King Master

                      So change the DTD to use IMPLIED instead of "false".

                      • 8. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                        Leo Baschy Novice

                         

                        <!ATTLIST page login-required (true|false) #IMPLIED>
                        instead of "false" fixes the problem "on my machine".

                        The bigger problem though would be people who don't change the DTD e.g. from 1.2 to either 1.2.1 or 1.3 and still get the "false" instead of recognizing it isn't defined. So a login-required that isn't defined acts like a login-required="false", which trying to implement JBSEAM-1009 is bad.

                        One answer would be "well, then let's forget about JBSEAM-1009". Not a good answer.

                        Meanwhile I might have a better patch for 1009 working also for overriding <restrict ...> specific over less specific wildcard (need to test), and am using a nicer pages element attribute name for the on/off flag for this feature

                        weaker-explicit-security="true"


                        Any guidance, e.g. whether instead of login-required we now should use require-login to ensure #IMPLIED. Should we replace it, or have both in the code? Doesn't sound good.

                        I hope Seam isn't too old yet to allow change for the better.

                        Sure, one could say "have to switch to new DTD anyway to comply for weaker-explicit-security", but the problem are older whatever.page.xml files.

                        Then, we could keep the DTD's ID of the pages.xml and compare all page.xml and throw an exception if on is a different version. That would be dom4j DocumentType method getPublicID? Or getSystemID?

                        I want to get this to work in a way that works for everyone.

                        • 9. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                          Gavin King Master

                          You've totally lost me now.

                          That change to the DTD is not a breaking change and, following the policy we have used for Hibernate for years, non-breaking DTD changes do not require an increment of the version number.

                          • 10. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                            Leo Baschy Novice

                            JBSEAM-1009 is about (if switched on) explicitly setting login-required (and restrict) per page or per wildcard in a way that allows a specific page to be less restricted than a * site wide wildcard. For each (login-required and restrict) it picks the most specific page where it is defined and only evaluates that one, ignores less specific wildcards. Why needed, I'll explain if asked.

                            In that context it is unsecure if a missing login-required is interpreted as login-required="false".

                            By conicidence, that's what caused the interaction with 954, the mysterious afterRender beforeRender. The problem with afterRender beforeRender could occur any time there is no login-required but a restrict, but my work on 1009 made it happen sooner on my system.

                            The reasonable workaround I've code today in the mornig and will submit as patch for 1009 hopefully later today is that I now force all DTD public IDs for pages.xml and all whatever.page.xml to be the same, so if someone consciously switches to the new DTD in pages.xml with #IMPLIED then he won't be able to "forget" an old DTD in any whatever.page.xml. Because that old DTD would cause an undesired login-required="false".

                            I'll be happy to explain it again, but maybe we should have that conversation after I've submitted that 3rd version patch to 1009. I assume you want me to run it for some time here before submitting it :)

                            • 11. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                              Gavin King Master

                              Sorry, I won't be accepting any patch that is implemented as you just described.

                              A missing login-required should be interpreted as null, and delegate to the more general widcard.

                              I certainly won't be forcing any kind of DTD update on users, or (worse) accepting any switch that turns this functionality "on". If it doesn't just work, and fit transparently into the current DTD and current behavior, I won't accept the patch.

                              • 12. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                                Leo Baschy Novice

                                Exactly, I agree with

                                A missing login-required should be interpreted as null, and delegate to the more general widcard.


                                And that's where dom4j and the existing DTD are messing with us. Because there isn't a way to tell the login-required isn't there. Dom4j insists on saying it is false, per existing DTD, even if it isn't there.

                                Now people who don't want to use the new functionality can keep using the old DTD.

                                The "forcing" is meant to make sure one site uses the same DTD for all page.xml, because otherwise a single page could have an older DTD, which could be easy to overlook, e.g. copy and paste from an example.

                                The overlooked DTD would make that page less secure, no login-required, a bad oops.

                                The "forcing" is in a well isolated piece of the patch (yet to submit 3rd version) so it can/could be removed/not incorporated by itself.

                                I think it is figured out relatively nicely, so if it doesn't come across clearly I'll be happy to answer questions.

                                • 13. Re: since today (JBSEAM-954?) I get NPE in setEntityManagerF
                                  Leo Baschy Novice

                                  It also works fine (I think to remember) without DTD listed in any page.xml, because then dom4j doesn't say it is false when in fact it isn't there.

                                  One could say that's a bad library, that returns different results for an attribute value whether the DTD is mentioned in the XML or not. Though it is open for discussion what one expects. I think at least it should be optional to get the result one wants if one cares to code it so, and it seems dom4j doesn't let us do that here.