10 Replies Latest reply on Nov 12, 2008 10:46 AM by etirk

    Identity creates multiple instances of authenticator component

    etirk

      The authentication class, Authenticator, has a session-scoped component injected, created by jsf.
      The component however, seems to be created in two different scopes/domains, or in two different versions.
      The first component used from jsf does not hold the same values as the one injected into the Authenticator class used by Identity.
      Example follows.



      components.xml:
           <security:identity authenticate-method="#{authenticator.authenticate}"
                remember-me="true" />
      
      
      @Stateful
      @Scope(ScopeType.SESSION)
      @Name("extendedAuthenticator")
      public class ExtendedAuthenticatorAction implements ExtendedAuthenticator {
           private boolean value;
      
           public boolean isValue() {
                return value;
           }
      
           public void setValue(boolean value) {
                this.value = value;
           }
           
           public boolean authenticate() {
                ...
           }
      }
      
      
      @Name("authenticator")
      public class Authenticator {
      
           @In(scope = ScopeType.SESSION)
           @Out(scope = ScopeType.SESSION)
           private ExtendedAuthenticator extendedAuthenticator;
      
           public boolean authenticate() {
                if(extendedAuthenticator != null) {
                     if(this.extendedAuthenticator.isValue()) // evaluates to false
                          this.extendedAuthenticator.authenticate(); // call made to other instance than set from jsf
                }
           }
      }
      
      @Name("loginHandler")
      public class Authenticator {
      
           @In
           private Identity identity;
           
           public boolean login() {
                this.identity.tryLogin();
           }
      }
      
      xhtml:
      #{extendedAuthenticator.setValue(true)} -- create the component
      #{loginHandler.login()} -- triggers login through a handling bean, and extendedAuthenticator.isValue() will evaluate to false.
      




      It seems though as seam creates a duplicate version of the ExtendedAuthenticator somehow. This happens only when two different users tries to access the page.
      As long as one browser is accessing the page this is not the case. Am I missing something obvious or might this be a bug?


      /K

        • 1. Re: Identity creates multiple instances of authenticator component
          shane.bryzak

          How is the authenticator component created by JSF?  Also, your code seems very obfuscated, is there a reason for all the extra complexity?  Why can't all your logic go in the authenticator component?  Also, the outjection of ExtendedAuthenticator is unnecessary.


          To the case in point, I can't see how two different users, with two different sessions can cause the issue you're seeing.  If you can put together a deployable test case with steps to easily reproduce the issue, then please raise it in JIRA and we'll take a look.

          • 2. Re: Identity creates multiple instances of authenticator component
            etirk

            All code from the extendedAuthenticator has now moved into Authenticator.
            All beans using the old one is now directly injected with Authenticator. The xhtml is now calling the setValue on authenticator. This did
            however not seem to help one bit. The method and instance of authenticator that is called from xhtml is not the same as used by the loginHandler-component. All components that use the Authenticator component has been equipped with:


            @In(create = true)
            @Out(scope = ScopeType.SESSION)
            


            What would be nicer to do though is to only use


            @In(scope = ScopeType.SESSION


            And somehow get a guarantee that seam creates the Authenticator-component before any other component will use it. Autocreate did not solve this problem.
            Seam trunk from 13:30 today is used.


            /K

            • 3. Re: Identity creates multiple instances of authenticator component
              etirk

              After one day of restructuring and bugsearching the solution is a really ugly one.
              It seems that JSF/Richfaces will fail to permanentely set the value in a backing bean in our application.
              This behaviour has been registered before, aprox a week back, for a random data holding java bean.
              A richfaces


              rendered="#{bean.isValue()}"



              refused to evaluate to true, though the value was set.
              Printing the value using a


              #{bean.isValue()}



              on the same page seemed to force the value to be fetched correctly, and the value evaluated to true, thus making the rendered-clause work properly.
              The same printing of a value through JSTL solved the problem this time around as well.
              By printing the value that gets set through the xhtml-page forces the value to be correctly set in the session-scoped Authenticator bean.
              If printing of the value is omitted, the authenticator that receives the setValue() operation is not the same that is used in all the subsequent calls.
              What can produce this behaviour? Is it JSF or Richfaces? JSTL? Seam?
              It seems that Seam creates a temporary component that is used when setting the value, but when JSTL prints the value, it forces the same companent instance to remain in session.
              If the value is not printed (evaluated through JSTL), the instance of the component gets thrown out and a new one is created.
              The problem is very hard to reproduce and I hope you guys could take a moment to ponder upon this problem.


              /K

              • 4. Re: Identity creates multiple instances of authenticator component
                etirk

                Correction again.
                The jstl-evaluation seems to be as random as the next one...it solved the problem, and then it stopped working after a restart of the application, not the entire server.
                What's missing...really? There is bearly any code left at this point that could be the source of the problem.
                The only odd thing that can be seen in the log is the failure to find a classloader during the call of a method on a component that has
                nothing to do with the current case.


                2008-11-10 17:55:21,971 DEBUG [org.jboss.seam.persistence.HibernatePersistenceProvider] no Hibernate Search, sorry :-(
                java.lang.ClassNotFoundException: No ClassLoaders found for: org.hibernate.search.Version
                     at org.jboss.mx.loading.LoadMgr3.beginLoadTask(LoadMgr3.java:306)
                     at org.jboss.mx.loading.RepositoryClassLoader.loadClassImpl(RepositoryClassLoader.java:521)
                     at org.jboss.mx.loading.RepositoryClassLoader.loadClass(RepositoryClassLoader.java:415)
                     at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
                     at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
                     at java.lang.Class.forName0(Native Method)
                     at java.lang.Class.forName(Class.java:164)
                     at org.jboss.seam.persistence.HibernatePersistenceProvider.<clinit>(HibernatePersistenceProvider.java:59)
                     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
                     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
                     at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
                     at java.lang.Class.newInstance0(Class.java:350)
                     at java.lang.Class.newInstance(Class.java:303)
                     at org.jboss.seam.Component.instantiateJavaBean(Component.java:1404)
                     at org.jboss.seam.Component.instantiate(Component.java:1325)
                     at org.jboss.seam.Component.newInstance(Component.java:2083)
                     at org.jboss.seam.Component.getInstance(Component.java:1987)
                     at org.jboss.seam.Component.getInstance(Component.java:1966)
                     at org.jboss.seam.Component.getInstance(Component.java:1960)
                     at org.jboss.seam.Component.getInstance(Component.java:1933)
                     at org.jboss.seam.Component.getInstance(Component.java:1928)
                     at org.jboss.seam.persistence.PersistenceProvider.instance(PersistenceProvider.java:126)
                     at org.jboss.seam.persistence.EntityManagerProxyInterceptor.proxyPersistenceContexts(EntityManagerProxyInterceptor.java:56)
                     at org.jboss.seam.persistence.EntityManagerProxyInterceptor.postConstruct(EntityManagerProxyInterceptor.java:43)
                     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:585)
                     at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
                     at org.jboss.seam.intercept.Interceptor.postConstruct(Interceptor.java:193)
                     at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:74)
                     at org.jboss.seam.persistence.HibernateSessionProxyInterceptor.postConstruct(HibernateSessionProxyInterceptor.java:46)
                     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:585)
                     at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
                     at org.jboss.seam.intercept.Interceptor.postConstruct(Interceptor.java:193)
                     at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:74)
                     at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
                     at org.jboss.seam.intercept.RootInterceptor.invokeAndHandle(RootInterceptor.java:84)
                     at org.jboss.seam.intercept.SessionBeanInterceptor.postConstruct(SessionBeanInterceptor.java:114)
                     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:585)
                     at org.jboss.ejb3.interceptor.LifecycleInvocationContextImpl.proceed(LifecycleInvocationContextImpl.java:131)
                     at org.jboss.ejb3.interceptor.LifecycleInterceptorHandler.postConstruct(LifecycleInterceptorHandler.java:109)
                     at org.jboss.ejb3.EJBContainer.invokePostConstruct(EJBContainer.java:623)
                     at org.jboss.ejb3.AbstractPool.create(AbstractPool.java:131)
                     at org.jboss.ejb3.InfinitePool.get(InfinitePool.java:49)
                     at org.jboss.ejb3.ThreadlocalPool.create(ThreadlocalPool.java:50)
                     at org.jboss.ejb3.ThreadlocalPool.get(ThreadlocalPool.java:90)
                     at org.jboss.ejb3.cache.simple.SimpleStatefulCache.create(SimpleStatefulCache.java:315)
                     at org.jboss.ejb3.stateful.StatefulLocalProxyFactory.createProxy(StatefulLocalProxyFactory.java:146)
                     at org.jboss.ejb3.JndiProxyFactory.getObjectInstance(JndiProxyFactory.java:53)
                     at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304)
                     at org.jnp.interfaces.NamingContext.getObjectInstance(NamingContext.java:1273)
                     at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1290)
                     at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:763)
                     at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:627)
                     at javax.naming.InitialContext.lookup(InitialContext.java:351)
                     at org.jboss.seam.Component.instantiateSessionBean(Component.java:1366)
                     at org.jboss.seam.Component.instantiate(Component.java:1330)
                     at org.jboss.seam.Component.newInstance(Component.java:2083)
                     at org.jboss.seam.Component.getInstance(Component.java:1987)
                     at org.jboss.seam.Component.getInstance(Component.java:1949)
                     at org.jboss.seam.Component.getInstance(Component.java:1943)
                     at org.jboss.seam.Component.getInstanceInAllNamespaces(Component.java:2310)
                     at org.jboss.seam.Component.getValueToInject(Component.java:2262)
                     at org.jboss.seam.Component.injectAttributes(Component.java:1702)
                     at org.jboss.seam.Component.inject(Component.java:1520)
                     at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:61)
                     at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                     at org.jboss.seam.bpm.BusinessProcessInterceptor.aroundInvoke(BusinessProcessInterceptor.java:51)
                     at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                     at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
                     at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                     at org.jboss.seam.persistence.EntityManagerProxyInterceptor.aroundInvoke(EntityManagerProxyInterceptor.java:29)
                     at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                     at org.jboss.seam.persistence.HibernateSessionProxyInterceptor.aroundInvoke(HibernateSessionProxyInterceptor.java:31)
                     at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                     at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
                     at org.jboss.seam.intercept.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:50)
                     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:585)
                     at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:118)
                     at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.ejb3.entity.ExtendedPersistenceContextPropagationInterceptor.invoke(ExtendedPersistenceContextPropagationInterceptor.java:57)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:126)
                     at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:195)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:95)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.ejb3.stateful.StatefulInstanceInterceptor.invoke(StatefulInstanceInterceptor.java:83)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
                     at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
                     at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
                     at org.jboss.ejb3.stateful.StatefulContainer.localInvoke(StatefulContainer.java:206)
                     at org.jboss.ejb3.stateful.StatefulLocalProxy.invoke(StatefulLocalProxy.java:119)
                        ...
                



                Where to look for a solution?


                /K

                • 5. Re: Identity creates multiple instances of authenticator component
                  etirk

                  And again, changing the xhtml-file and doing a new explode of the xhtml-files seems to trigger a new render for the view/xhtml/jsf-tree. This in turn gives back the functionality, and the backend components work as they should.
                  The problem is definetaly somewhere between jsf/richfaces and seam, which then could be anywhere really...:P


                  /K

                  • 6. Re: Identity creates multiple instances of authenticator component
                    shane.bryzak

                    Have you changed the scope of your authenticator component to make it session scope?

                    • 7. Re: Identity creates multiple instances of authenticator component
                      etirk

                      Yes. The new code have only the authenticator component, in session scope.
                      But the whole matter has really nothing to do with the authenticator or Identity. This behaviour seem to affect all back-end components that gets called from this page. The actual calls are made from the template.xhtml, the standard page decorator.
                      It would seem that seam creates a temporary component, and throws it out if the component is not used in succequent rendering when returning to the same view. That is, when jstl evaluates the set value the component remains. If not, seam creates a new component when it is needed by another back-end component. Thus creating it directly from a view, through a commandLink or jstl-evaluation, will not make it permanent back-end.
                      This is a very real bug, and we have all witnessed it here in our office. How to replicate this I just cannot figure out and for now
                      the solution was to move the described functionality into a pageflow.


                      /K

                      • 8. Re: Identity creates multiple instances of authenticator component
                        etirk

                        Correction again. Adding pageflow seems to be working, after the second access and forth. Thus, first access to the bean will not make it stick. The following actions setting and reading the bean works. There must be someone else that has encountered this problem?


                        /K

                        • 9. Re: Identity creates multiple instances of authenticator component
                          etirk

                          Seam kills and starts a new session. It's as simple as that. Can't believe I did not see this immediatly!
                          The question remains, why does this happen?
                          Logging the session id for all the calls made to the authenticator component shows that the session id is different for the requests.
                          This explains the odd and irregular behaviour exactly.
                          There is however no code or configuration set to kill the session run. Only place this occurs in the logout action, wich is never run.
                          I will continue the investigation to find out what triggers this. So far the log has revealed nothing.


                          /K

                          • 10. Re: Identity creates multiple instances of authenticator component
                            etirk

                            The following can be seen happening at the exact point when the value of the backing bean is set. Right after the call is made to the setValue method seam logs that it is starting up session, ruleBasedPermissionResolver and identity once more. More information will follow...


                            10:39:10,605 INFO  [STDOUT] Before phase event id: RENDER_RESPONSE 6
                            10:39:11,154 INFO  [STDOUT] After phase event id: RENDER_RESPONSE 6
                            10:39:11,281 INFO  [STDOUT] TestFilter: Session id = 6088B25CE636B6D24ED27D7A8D650B4A
                            10:39:11,330 INFO  [STDOUT] TestFilter: Session id = 6088B25CE636B6D24ED27D7A8D650B4A
                            10:39:11,332 INFO  [STDOUT] TestFilter: Session id = 6088B25CE636B6D24ED27D7A8D650B4A
                            10:39:11,334 INFO  [STDOUT] TestFilter: Session id = 6088B25CE636B6D24ED27D7A8D650B4A
                            10:39:11,334 INFO  [STDOUT] TestFilter: Session id = 6088B25CE636B6D24ED27D7A8D650B4A
                            10:39:11,934 WARN  [DTDEntityResolver] unable to locate [http://jboss.com/products/seam/pages-2.1.dtd] on classpath
                            10:39:11,936 WARN  [DTDEntityResolver] unable to locate [http://jboss.com/products/seam/pages-2.1.dtd] on classpath
                            10:39:11,937 WARN  [DTDEntityResolver] unable to locate [http://jboss.com/products/seam/pages-2.1.dtd] on classpath
                            10:39:11,937 WARN  [DTDEntityResolver] unable to locate [http://jboss.com/products/seam/pages-2.1.dtd] on classpath
                            10:39:11,941 WARN  [DTDEntityResolver] unable to locate [http://jboss.com/products/seam/pages-2.1.dtd] on classpath
                            10:39:21,694 INFO  [Contexts] starting up: org.jboss.seam.web.session
                            10:39:21,694 INFO  [Contexts] starting up: org.jboss.seam.security.ruleBasedPermissionResolver
                            10:39:21,694 INFO  [Contexts] starting up: org.jboss.seam.security.identity
                            10:39:21,694 INFO  [STDOUT] TestFilter: Session id = C2C1765F9D62E02117907E1CF271FD43
                            10:39:22,022 WARN  [DTDEntityResolver] unable to locate [http://jboss.com/products/seam/pages-2.1.dtd] on classpath
                            10:39:22,443 INFO  [STDOUT] Before phase event id: RESTORE_VIEW 1
                            10:39:22,444 INFO  [STDOUT] After phase event id: RESTORE_VIEW 1



                            /K