10 Replies Latest reply on Mar 3, 2006 8:10 PM by gavin.king

    @Factory (+@Begin) method called repeatedly on every request

    landels

      Hi,

      We are using a @Factory method to initialize and @Begin conversation. So far so good, the corresponding variable gets initialized and the conversation gets started.
      The strange thing is that the corresponding member that gets initialized by the @Factory method is later not found in the conversational context, correspondingly the Factory gets called again.

      We did step through the stuff and it seams that old conversation id is not found, a new one is generated, correspondingly a new instance of the backing SFSB... One can also see the different SFSBs getting destroyed on undeploy.

      Any ideas? The source is trivial

       @org.jboss.seam.annotations.datamodel.DataModel
       private List<Transaction> transactionList;
      ...
       @org.jboss.seam.annotations.Factory("transactionList")
       @org.jboss.seam.annotations.Begin
       public String initialize() {
       log.info("initialize");
       // fetch some data from the DB and set it to this.transactionList
       intFilter();
       return "transactionlist";
       }
      
      


      In another conversation we have the variant w/ a @In/@Out variable w/ the same effect.

      We are using latest CVS version.

      Related topics (http://www.jboss.com/index.html?module=bb&op=viewtopic&t=73310,
      http://www.jboss.com/index.html?module=bb&op=viewtopic&t=72267,
      http://www.jboss.com/index.html?module=bb&op=viewtopic&t=73702)

      cu & thanks,

        • 1. Re: @Factory (+@Begin) method called repeatedly on every req
          gavin.king

          Are you sure the conversation did not time out?

          • 2. Re: @Factory (+@Begin) method called repeatedly on every req
            landels

            Hi Gavin,

            No don't think so, the timeout was set pretty high. I did set it even higher today:

            <context-param>
             <param-name>org.jboss.seam.core.manager.conversationTimeout</param-name>
             <param-value>3600000</param-value>
            </context-param>
            


            but with no effect. Plus - if the conversation gets timed out the SFSB should be destroyed, right? And the brakepoint in the @Destroy method gets never called before undeploy.

            cu,

            • 3. Re: @Factory (+@Begin) method called repeatedly on every req
              landels

              Ok I do not know if this is relevant but on the second request (after the @Factory and @Begin method is called on the the first request) in org.jboss.seam.core.Manager::restore() the storedConversationId is null and a new id gets generated (Id.nextId()). In difference on the next request the id is restored properly.

              cu,

              • 4. Re: @Factory (+@Begin) method called repeatedly on every req
                landels

                Hmmm,
                could it be that JspStateManagerImpl.saveSerializedView only does save changes done to the FacesContext when it is called for the first time?

                ...
                if (serializedView == null)
                 {
                 // first call to saveSerializedView --> create SerializedView
                 Object treeStruct = getTreeStructureToSave(facesContext);
                 Object compStates = getComponentStateToSave(facesContext);
                 serializedView = new StateManager.SerializedView(treeStruct, compStates);
                 externalContext.getRequestMap().put(SERIALIZED_VIEW_REQUEST_ATTR,
                 serializedView);
                 }
                ...
                

                well it gets called twice from StateManagerInterceptor.saveSerializedView the second time after the @Factory/@Begin call w/ the updated FacesContext and this code segment gets skipped...

                cu,


                • 5. Re: @Factory (+@Begin) method called repeatedly on every req
                  landels

                  Ok the last was a dead-end, so I am where I was before... the @Factory method beeing called twice.

                  Any hints are welcome! Wrong configuration?

                  Thanks,

                  • 6. Re: @Factory (+@Begin) method called repeatedly on every req
                    gavin.king

                    Is the second request a GET request or a JSF postback?

                    • 7. Re: @Factory (+@Begin) method called repeatedly on every req
                      landels

                      Hi Gavin,

                      Just re-checked this again w/ Seam beta 2...

                      The second request is a JSF Postback triggered by an <h:commandButton> inside a <h:form>. Funny enough <h:commandLink>s on the same page work properly... Are these both handled differently?!

                      We also put the conversation id on the form and one can clearly see that after pushing the <h:commandButton> it is another conversation...

                      cu,

                      • 8. Re: @Factory (+@Begin) method called repeatedly on every req
                        gavin.king

                        Make sure you don't have more than one f:view, and that the h:commandButtons are all inside the f:view.

                        It would help if you actually show the JSF pages.

                        • 9. Re: @Factory (+@Begin) method called repeatedly on every req
                          landels

                          Hi

                          it seams to be the case... the f:view was in the template, we moved it here for the test's sake.

                          The "View Transactions" button is the one doing the problem. On the GET request (when the page is loaded for the first time) a @Factory and @Begin initialize() is called to initialize the transactionList DataModel.

                          When the "View Transactions" is pushed the list of transactions should be filtered accordingly the restriction given in the input field "transactionCode". This happens (the filter method is called and the transactionList is updated ), but first the initialize method is called one more time.

                          After this it works ok - pushing the "View Transactions" button only updates the model, the factory method is not called again, i.e. the conversational context is estimated.

                          <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                          
                          <ui:composition template="template.xhtml" xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" >
                          
                           <!-- content -->
                           <ui:define name="caption">
                           Next generation PMX - Prototype: Transaction view
                           </ui:define>
                           <ui:define name="content">
                          <f:view>
                          
                           <b> conversationId="#{conversation.id}"</b>
                           <h:form>
                           <h:outputLabel for="transactionCode">Transaction code:</h:outputLabel>
                           <h:inputText id="transactionCode" value="#{transactionView.txidentifier}" />
                          
                           <h:commandButton id="viewTransactions" type="submit" value="View transactions" action="#{transactionView.viewTransactions}" class="button"/>
                           <h:commandButton id="newTransaction" type="submit" value="Create new transaction" action="#{transactionView.gotoNewTransaction}" class="button"/>
                           </h:form>
                           <h:outputText value="No transactions found" rendered="#{transactionList == null or empty transactionList}" />
                           <div class="section">
                           <h:dataTable class="datatable" value="#{transactionList}" var="trans" rendered="#{transactionList != null and not empty transactionList}">
                           <h:column>
                           <f:facet name="header">Transaction code</f:facet>
                           #{trans.identifier}
                           </h:column>
                           <h:column>
                           <f:facet name="header">Description</f:facet>
                           #{trans.description}
                           </h:column>
                           <h:column>
                           <f:facet name="header">Type</f:facet>
                           #{trans.transactionType}
                           </h:column>
                           <h:column>
                           <f:facet name="header">Status</f:facet>
                           <h:outputText value="New" rendered="#{trans.materialLot==null}"/>
                           <h:outputText value="Processed" rendered="#{trans.materialLot!=null}"/>
                           </h:column>
                           <h:column>
                           <f:facet name="header">Supplier</f:facet>
                           #{trans.materialDefinition.supplier}
                           </h:column>
                           <h:column>
                           <f:facet name="header">Material</f:facet>
                           #{trans.materialDefinition.identifier}
                           </h:column>
                           <h:column>
                           </h:column>
                           <h:column>
                           <f:facet name="header">Quantity</f:facet>
                           #{trans.orderedQuantity.value}
                           #{trans.orderedQuantity.unit}
                           </h:column>
                           <h:column>
                           <f:facet name="header">Edit</f:facet>
                           <h:commandLink action="#{transactionView.gotoEditTransaction}" rendered="#{trans.materialLot==null}">Edit</h:commandLink>
                           </h:column>
                           <h:column>
                           <f:facet name="header">Process</f:facet>
                           <h:commandLink action="#{transactionView.gotoProcessTransaction}" rendered="#{trans.materialLot==null}">Process</h:commandLink>
                           </h:column>
                           <h:column>
                           <f:facet name="header">View</f:facet>
                           <h:commandLink action="#{transactionView.viewTxDetails}" rendered="#{trans.materialLot!=null}">View</h:commandLink>
                           </h:column>
                           </h:dataTable>
                           <h:messages globalOnly="true" />
                           </div>
                          </f:view>
                           </ui:define>
                          </ui:composition>
                          


                          Regards,


                          • 10. Re: @Factory (+@Begin) method called repeatedly on every req
                            gavin.king

                            So this was a pure-JSF problem then ;)