10 Replies Latest reply on Sep 3, 2007 2:01 PM by Jonas Buechel

    Multiple DataModels in an SFSB

    jk;l jkl; Expert

      I have multiple DataModels with corresponding DataModelSelections in an SFSB. The problem is that every time one is injected based on a selection, the other seems to get injected into its DataModelSelection as well (a default value of the first in the row of that other DataModel, because no row was actually selected for it).

      Has anybody else had this problem? I'm not doing caching or anything in my bean, so am wondering whether this might be a bug?

      In the code below, on one page I select a row in the table of "A" entities...however, not only is the DataModelSelection for A injected, but also for B! Totally unexpected... (The injected value for B is always the first element in its list.) The same thing happens in the opposite way when I am on the page for B.

      @DataModelSelection("a")
       @Out(required=false)
       private A a;
      
       @DataModelSelection("b")
       @Out(required=false)
       private B b;
      
       @DataModel
       @Factory
       @SuppressWarnings("unchecked")
       public List<A> getA() {
       ...
       }
      
       @DataModel
       @Factory
       @SuppressWarnings("unchecked")
       public List<B> getB() {
       ...
       }


        • 1. Re: Multiple DataModels in an SFSB
          None None Master

          I have had multiple DataModels in SFSBs and had no problems, but I have always used @DataModel on a variable, not on a method. Also I would think that @Factory and @DataModel should not be on the same thing.

          Try putting your @DataModels as variables, and leave your @Factorys on the appropriate methods.

          Just my guess.

          • 2. Re: Multiple DataModels in an SFSB
            jk;l jkl; Expert

             

            "SmokingAPipe" wrote:
            ... I have always used @DataModel on a variable, not on a method. Also I would think that @Factory and @DataModel should not be on the same thing.


            Could one of the developers of Seam comment on whether the above is correct? I'd think that whether I annotate a method or a variable as @DataModel, in either case it shouldn't affect when @DataModelSelection is populated.

            What might be causing the @DataModelSelection to be populated with the first row in its corresponding @DataModel when another @DataModel's element is selected?

            • 3. Re: Multiple DataModels in an SFSB
              Pete Muir Master

              @DataModel and @Factory shouldn't be on the same method.

              • 4. Re: Multiple DataModels in an SFSB
                jk;l jkl; Expert

                Ok, then in an SFSB how can you ensure that every time the property is accessed the factory is getting run again?

                The way I understand it is that the factory is only executed when the corresponding property is null. Therefore, the only time that would apply is the very first time that the factory method is run on the SFSB.

                I don't want to be dealing with stale data though! How should I solve this?

                • 5. Re: Multiple DataModels in an SFSB
                  Gavin King Master

                  @Factory(scope=EVENT|STATELESS)

                  • 6. Re: Multiple DataModels in an SFSB
                    Christian Bauer Master

                    Add a refreshMyList() method and let it listen to an event. Fire the event (from anywhere) when you need to refresh the data.

                    • 7. Re: Multiple DataModels in an SFSB
                      Fernando Montaño Expert

                       

                      "gavin.king@jboss.com" wrote:
                      @Factory(scope=EVENT|STATELESS)


                      Related to this I have some troubles, maybe you can help me.

                      I have this code:
                      @Statefull
                      @Name("userList")
                      @Scope(ScopeType.SESSION)
                      public class UserList {
                      
                      @DataModel
                      private List<User> users;
                      
                      @Factory("users")
                       public void findUsers() {
                       users = em.createQuery..........
                       }
                      
                      }
                      


                      The above code works fine, but the problem I have is that the user list is only fill up the first time.

                      Then I change the @Factory code (according your comment) as follows:

                      @Factory(value="users", scope=ScopeType.EVENT)
                       public void findUsers() {
                       users = em.createQuery..........
                       }
                      
                      


                      But, doing this change I always get this exception:

                      22:46:29,203 ERROR [D2DFaceletViewHandler] Problem in renderResponse: factory method with defined scope outjected a value:
                      users
                      java.lang.IllegalArgumentException: factory method with defined scope outjected a value: users
                       at org.jboss.seam.Component.handleFactoryMethodResult(Component.java:1745)
                       at org.jboss.seam.Component.getInstanceFromFactory(Component.java:1719)
                       at org.jboss.seam.Component.getInstance(Component.java:1655)
                       at org.jboss.seam.Component.getInstance(Component.java:1632)
                       at org.jboss.seam.jsf.SeamVariableResolver.resolveVariable(SeamVariableResolver.java:105)
                       at org.apache.myfaces.config.LastVariableResolverInChain.resolveVariable(LastVariableResolverInChain.java:42)
                       at com.sun.facelets.el.LegacyELContext$LegacyELResolver.getValue(LegacyELContext.java:134)
                       at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:44)
                       at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:183)
                       at com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:71)
                       at com.sun.facelets.el.LegacyValueBinding.getValue(LegacyValueBinding.java:56)
                       at javax.faces.component.UIData.getValue(UIData.java:1019)
                       at com.icesoft.faces.component.panelseries.UISeries.getDataModel(UISeries.java:304)
                       at com.icesoft.faces.component.panelseries.UISeries.processCurrentRowData(UISeries.java:132)
                       at com.icesoft.faces.component.panelseries.UISeries.setRowIndex(UISeries.java:124)
                       at javax.faces.component.html.HtmlDataTable.encodeBegin(HtmlDataTable.java:43)
                       at com.icesoft.faces.component.panelseries.UISeries.encodeBegin(UISeries.java:245)
                       at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:579)
                       at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:586)
                       at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:586)
                       at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:586)
                       at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:586)
                       at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:586)
                       at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:586)
                       at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:586)
                       at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:586)
                       at com.icesoft.faces.facelets.D2DFaceletViewHandler.renderResponse(D2DFaceletViewHandler.java:276)
                       at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:149)
                       at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:384)
                       at com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet.service(PersistentFacesServlet.java:406)
                       at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                       at org.jboss.seam.servlet.SeamExceptionFilter.doFilter(SeamExceptionFilter.java:85)
                       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.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
                       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
                       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
                       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:66
                      4)
                       at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
                       at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
                       at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
                       at java.lang.Thread.run(Thread.java:595)
                      
                      



                      I also tried using an Stateless component:

                      @Stateless
                      @Name("userList")
                      @Scope(ScopeType.STATELESS)
                      public class UserList {
                      
                      @DataModel
                      private List<User> users;
                      
                      @Factory(value="users", scope=ScopeType.STATELESS)
                       public void findUsers() {
                       users = em.createQuery..........
                       }
                      
                      }
                      


                      But trying that I get the same exception.

                      Is there something I'm doing wrong?

                      Is there some bug there?


                      I hope you can help me.

                      Thanks in advance.

                      • 8. Re: Multiple DataModels in an SFSB
                        Gavin King Master

                        void @Factory methods should not have a scope. The scope is defined on the attribute that does the outjection.

                        • 9. Re: Multiple DataModels in an SFSB
                          jk;l jkl; Expert

                          I'm getting a problem where the DataModelSelection that isn't being selected (because there's 2 in the SFSB) is still being outjected, albeit with all properties empty...I do a null check on whether a particular component is not empty in conversation scope for application functionality, so this is a problem. (By the way, is that not a good way of doing things?)

                          Where in my debugger should I put a breakpoint to see when a component gets outjected into any scope (in particular, the conversation scope)? I think it's a simple case of having a ${mycomponent.myproperty} somewhere in one of the pages, so the component is getting outjected...


                          A related question is if I put a ${mycomponent.myproperty} within Facelets template text in a page to output the value if that property exists (or remain empty otherwise), I get an empty mycomponent outjected (is that expected behavior)? I thought things only get outjected when you specify explicitly that you outject them (e.g. in an @Out of a session bean). But a simple property access...?

                          • 10. Re: Multiple DataModels in an SFSB
                            Jonas Buechel Novice

                             

                            "gavin.king@jboss.com" wrote:
                            void @Factory methods should not have a scope. The scope is defined on the attribute that does the outjection.

                            Hi, i'm struggling with a similar issue as fernando did:
                            Here some code snippets:

                            DataModel declaration:
                            @DataModel(scope=ScopeType.PAGE)
                             private Collection<Role> roleDataModel;
                            

                            Factory declaration:
                            @Factory("roleDataModel")
                             public void initializeModel() {
                             log.debug("initializeModel() called (but not used)");
                             if (organigramTreeModelSelection != null)
                             roleDataModel = ((OrganigramNode) organigramTreeModelSelection)
                             .getRoles();
                             else
                             roleDataModel = new ArrayList();
                            
                             }
                            

                            xhtml:
                            <rich:dataTable id="roleTableId" value="#{roleDataModel}"
                            ...
                            </rich:dataTable>


                            As Gavin wrote the scope has to be defined on the outjecting attribute. Considering @DataModel does only take PAGE or UNSPECIFIED scopes i run into a problem as the datatable (roleTableId) is updated through an ajax request.
                            As follows:
                            <rich:tree switchType="ajax" ajaxSubmitSelection="true" reRender="fwcToolbar, roleTableId" ....
                            


                            But in this case the PAGE scope i can't use, right?
                            Does anybody have any idea?

                            Help would be very appreciated as i've been fighting with this quite long..