1 2 Previous Next 28 Replies Latest reply on Mar 2, 2006 3:10 PM by emsa

    Prevent @Factory method execution?

    lcoetzee

      Hi,

      I have a xhtml that gets loaded with data through an @Factory("load") method on a stateful bean (the xhtml references "load" which gets outjected by my bean) . This works well and as expected. "load" is event scoped, meaning that the method loading the data gets invoked every time I view the page. I build up and display several urls on this pages pointing to the xhtml (thus through the @Factory I load other elements to be displayed... a painful way of creating a page that can be bookmarked, but work very well ).

      However, I have a situation where I want to use a commandlink to execute a method in another stateful bean (and display another xhtml page). However, when I click the commandlink the original dataloader bean gets invoked because of the @Factory in stead of the action in the target bean (and then never executing the desired action).

      This is really quite baffling. Any suggestions would be appreciated.

      What I have tried is to inject a value (through @RequestParameter) into the "load" variable, thus theoretically preventing the @Factory from executing. Unfortunately the @Factory method still gets executed (even though I can see that the "load" variable has a value). I get the impression that Seam has already made the decision (evaluated the "load" variable) to execute the method before the RequestParam was injected.

      Is there a way to prevent the @Factory from being called ?

      What a mouthful. Sorry ;-)

      Louis

        • 1. Re: Prevent @Factory method execution?
          gavin.king

          Another user is complaining of this in another thread. I'm confused by it. Please show all code.

          (There is no way an @Factory method should be invoked before the action method, unless you have an @In on the factory component.)

          • 2. Re: Prevent @Factory method execution?
            gavin.king
            • 3. Re: Prevent @Factory method execution?
              lcoetzee

              I will try and get the appropriate parts...

              In the xhtml the bean is invoked based on allServicesToViewLoaded as called by :


              <ui:define name="leftNavigation" id="leftNavIns">
               <n:leftNavigation rendered="#{not empty allServicesToViewLoaded}"
               service="#{selectedServiceForView}"
               serviceTopics="#{orderedTopicsForView}"
               targetURL="#{facesContext.externalContext.requestContextPath}/public/content/view/viewContent.jsf"
               id="leftNavigationId" />
               </ui:define>
              
               <ui:define name="siteNavigation" id="siteNav">
               <n:siteNavigation rendered="#{not empty allServicesToViewLoaded}"
               services="#{allServicesForView}"
               targetURL="#{facesContext.externalContext.requestContextPath}/public/content/view/viewContent.jsf"
               id="siteNavigationId" />
               </ui:define>
              


              The link that I am trying to execute is:

              <h:commandLink action="#{contentManagementBean.editContent}"
               rendered="#{not empty selectedContentForView}" id="editContent" >
               <f:param name="preventAllServicesToViewLoaded" value="PreventLoading" />
              


              In my bean I have:

              //if we set this in the editContent and createContent links
               //the factory will hopefully not be executed as a value will be injected
               @RequestParameter(value="preventAllServicesToViewLoaded")
               @Out(required = false)
               private String allServicesToViewLoaded;
              
              @SuppressWarnings("unchecked")
               @IfNAPException(goToOutcome = "ViewContentHomePage")
               @Factory("allServicesToViewLoaded")
               @Begin(join = true)
               public String handleLoadAllServices() throws NAPException {
              
               logger.info("handleLoadAllServices has been called because of Factory");
               logger.info("But has value: " + allServicesToViewLoaded);
              .
              .
              


              When clicking the link, I get the following in my log file:

              19:08:39,791 INFO [ViewContentBean] handleLoadAllServices has been called because of Factory
              19:08:39,791 INFO [ViewContentBean] But has value: PreventLoading
              19:08:39,791 INFO [ViewContentBean] Planning to edit content
              
              


              Hope I got the important stuff.

              L



              • 4. Re: Prevent @Factory method execution?
                gavin.king

                Please put a breakpoint at org.jboss.seam.Component:1077 and show me the stack and try to figure out what causes the @Factory method to be called.

                • 5. Re: Prevent @Factory method execution?
                  lcoetzee

                  OK... will do first thing tomorrow (South African time)... already at home (need to eat and sleep at some point ;-)

                  L

                  • 6. Re: Prevent @Factory method execution?
                    lcoetzee

                    The stack:

                    Thread [http-0.0.0.0-8080-2] (Suspended (breakpoint at line 1077 in org.jboss.seam.Component))
                     org.jboss.seam.Component.getInstanceFromFactory(java.lang.String) line: 1077
                     org.jboss.seam.Component.getInstance(java.lang.String, boolean, java.lang.Object) line: 1041
                     org.jboss.seam.Component.getInstance(java.lang.String, boolean) line: 1027
                     org.jboss.seam.jsf.SeamVariableResolver.resolveVariable(javax.faces.context.FacesContext, java.lang.String) line: 43
                     com.sun.facelets.el.LegacyELContext$LegacyELResolver.getValue(javax.el.ELContext, java.lang.Object, java.lang.Object) line: 134
                     com.sun.el.parser.AstIdentifier.getValue(com.sun.el.lang.EvaluationContext) line: 44
                     com.sun.el.parser.AstEmpty.getValue(com.sun.el.lang.EvaluationContext) line: 28
                     com.sun.el.parser.AstNot.getValue(com.sun.el.lang.EvaluationContext) line: 25
                     com.sun.el.ValueExpressionImpl.getValue(javax.el.ELContext) line: 183
                     com.sun.facelets.el.TagValueExpression.getValue(javax.el.ELContext) line: 71
                     com.sun.el.parser.AstIdentifier.getValue(com.sun.el.lang.EvaluationContext) line: 40
                     com.sun.el.ValueExpressionImpl.getValue(javax.el.ELContext) line: 183
                     com.sun.facelets.el.TagValueExpression.getValue(javax.el.ELContext) line: 71
                     com.sun.facelets.el.LegacyValueBinding.getValue(javax.faces.context.FacesContext) line: 56
                     org.apache.myfaces.custom.datalist.HtmlDataList(javax.faces.component.UIComponentBase).isRendered() line: 822
                     com.sun.facelets.FaceletViewHandler.encodeRecursive(javax.faces.context.FacesContext, javax.faces.component.UIComponent) line: 543
                     com.sun.facelets.FaceletViewHandler.encodeRecursive(javax.faces.context.FacesContext, javax.faces.component.UIComponent) line: 551
                     com.sun.facelets.FaceletViewHandler.renderView(javax.faces.context.FacesContext, javax.faces.component.UIViewRoot) line: 457
                     org.apache.myfaces.lifecycle.LifecycleImpl.render(javax.faces.context.FacesContext) line: 352
                     javax.faces.webapp.FacesServlet.service(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 107
                     org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 252
                     org.apache.catalina.core.ApplicationFilterChain.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 173
                     org.apache.myfaces.component.html.util.ExtensionsFilter.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) line: 122
                     org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 202
                     org.apache.catalina.core.ApplicationFilterChain.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 173
                     org.jboss.seam.servlet.SeamRedirectFilter.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) line: 23
                     org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 202
                     org.apache.catalina.core.ApplicationFilterChain.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 173
                     org.jboss.seam.servlet.SeamExceptionFilter.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) line: 44
                     org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 202
                     org.apache.catalina.core.ApplicationFilterChain.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 173
                     org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) line: 96
                     org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 202
                     org.apache.catalina.core.ApplicationFilterChain.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) line: 173
                     org.apache.catalina.core.StandardWrapperValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) line: 213
                     org.apache.catalina.core.StandardContextValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) line: 178
                     org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) line: 54
                     org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) line: 174
                     org.apache.catalina.authenticator.FormAuthenticator(org.apache.catalina.authenticator.AuthenticatorBase).invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) line: 432
                     org.jboss.web.tomcat.security.JaccContextValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) line: 74
                     org.apache.catalina.core.StandardHostValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) line: 126
                     org.apache.catalina.valves.ErrorReportValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) line: 105
                     org.apache.catalina.core.StandardEngineValve.invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response) line: 107
                     org.apache.catalina.connector.CoyoteAdapter.service(org.apache.coyote.Request, org.apache.coyote.Response) line: 148
                     org.apache.coyote.http11.Http11Processor.process(java.io.InputStream, java.io.OutputStream) line: 868
                     org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(org.apache.tomcat.util.net.TcpConnection, java.lang.Object[]) line: 663
                     org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(java.net.Socket, org.apache.tomcat.util.net.TcpConnection, java.lang.Object[]) line: 527
                     org.apache.tomcat.util.net.MasterSlaveWorkerThread.run() line: 112
                     org.apache.tomcat.util.threads.ThreadWithAttributes(java.lang.Thread).run() line: 595
                    


                    I am trying to see what the value of my factory method is (and when it gets instantiated).. no luck as yet... but working on it. Let me know what else I can check.

                    L


                    • 7. Re: Prevent @Factory method execution?
                      lcoetzee

                      Hmmm.. stepping through the Component.java it seems as if

                      public static Object getInstanceFromFactory(String name)
                      


                      is done before

                       public void inject(Object bean/*, boolean isActionInvocation*/)
                      


                      so my RequestParameter is initiated too late.

                      L


                      • 8. Re: Prevent @Factory method execution?
                        gavin.king

                        The stack shows that this is happening during the render response phase. i thought you said you were invoking an action.


                        getInstanceFromFactory() would be called before inject(), since we would need the instance before we could start injecting into it...

                        • 9. Re: Prevent @Factory method execution?
                          gavin.king

                          Why don't you submit a very simply, stripped down test case to JIRA, so I can take a look.

                          • 10. Re: Prevent @Factory method execution?
                            lcoetzee

                            Gavin,

                            OK.. now I am completely stumped !!!! I duplicated the functionality in another test framework I have (without the bells and whistles)... and it works as expected !

                            Looking at the original application I can see no difference between the working and the broken application.

                            I will go into it a bit deeper and see what pops up before I submit something to jira (if it is still required that is !)

                            Thanks

                            Louis

                            • 11. Re: Prevent @Factory method execution?
                              emsa

                              Some more info, I'm not sure if all this has any relevance or not but here goes.

                              First this happens when I use a <h:commandLink> with a parameter, I haven't tested with a 'normal' post yet.

                              Seam is trying to find a value for A - A is Scoped as EVENT.

                              During the BEFORE RESTORE_VIEW phase the factory method for A is called, the stack from Component is:

                              20:55:41,885 ERROR [STDERR] at org.jboss.seam.util.Reflections.invoke(Reflections.java:13)
                              20:55:41,885 ERROR [STDERR] at org.jboss.seam.util.Reflections.invokeAndWrap(Reflections.java:32)
                              20:55:41,886 ERROR [STDERR] at org.jboss.seam.Component.callComponentMethod(Component.java:1119)
                              20:55:41,886 ERROR [STDERR] at org.jboss.seam.Component.getInstanceFromFactory(Component.java:1078)
                              20:55:41,886 ERROR [STDERR] at org.jboss.seam.Component.getInstance(Component.java:1041)
                              20:55:41,886 ERROR [STDERR] at org.jboss.seam.Component.getInstance(Component.java:1027)
                              20:55:41,886 ERROR [STDERR] at org.jboss.seam.jsf.SeamVariableResolver.resolveVariable(SeamVariableResolver.java:43)
                              20:55:41,886 ERROR [STDERR] at com.sun.facelets.el.LegacyELContext$LegacyELResolver.getValue(LegacyELContext.java:134)
                              


                              also all the @In properties are null during this factory invokation.

                              .. lots of phases happen ...

                              then during INVOKE_APPLICATION the correct action-method is called, with the correct vales injected, including the @RequestParameter.

                              My guess is that this is the same kind of error as the (in)famous duplicate id error. Facelets/JSF is trying to recreate the tree before invoking the application ... and needs a value that happens to have a factory method ... but this is just a guess at this point.

                              /Magnus

                              • 12. Re: Prevent @Factory method execution?
                                gavin.king

                                Yes, makes perfect sense. JSF needs to evaluate your rendered="#{...}" expressions during RESTORE_VIEW, so hence the factory method gets called.

                                • 13. Re: Prevent @Factory method execution?
                                  emsa

                                  Yeaj :-) getting somewhere - so is calling the factory here considered a bug? I guess that if there's no factory defined then the value will remain null even after RESTORE_VIEW so would the solution to ignore factory-methods during RESTORE_VIEW be alright?

                                  • 14. Re: Prevent @Factory method execution?
                                    gavin.king

                                    Well, it is not really a bug, no. AFAICT, The bug is in your logic:

                                    If I understand correctly, you are writing, essentially: #{foo==null}, for a variable foo with an @Factory method. By definition, variables with factory methods are never null - that is the whole idea.

                                    I suggest you rethink the way your rendered expressions work.

                                    1 2 Previous Next