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

    Prevent @Factory method execution?

    Louis Coetzee Apprentice

      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 Master

          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.)

          • 3. Re: Prevent @Factory method execution?
            Louis Coetzee Apprentice

            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 Master

              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?
                Louis Coetzee Apprentice

                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?
                  Louis Coetzee Apprentice

                  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?
                    Louis Coetzee Apprentice

                    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 Master

                      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 Master

                        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?
                          Louis Coetzee Apprentice

                          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?
                            Magnus Sandberg Novice

                            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 Master

                              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?
                                Magnus Sandberg Novice

                                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 Master

                                  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