8 Replies Latest reply on Oct 26, 2007 9:36 AM by dmitriy.lapko

    Let's use component scope before lookupInStatefulContexts

    dmitriy.lapko

      One of the key methods of Seam in class Component is:

      public static Object getInstance(String name, boolean create)
       {
       Object result = Contexts.lookupInStatefulContexts(name);
       result = getInstance(name, create, result);
       return result;
       }
      


      Method lookupInStatefulContexts checks all possible scopes for an instance of a requested component. But as for me, usually a scope for a component is defined and I don't understand, why can't we use this information before scanning of all contexts.

      If I marked my component by annotation @Scope, and defined its scope to Session, wouldn't it be faster not to check method, event, page and conversation scopes before getting it from session? Searching in method, event and page contexts is fast, just hashmap searching, but for conversation scope it is much longer and depends on component realization.

      Why do I ask - because in my application there are more session scoped components then conversation scoped. And for them method ServerConversationContext.isPerNestedConversation is called anyway and it takes more then 1% of CPU time in all application, because it iterates among all methods in component trying to find annotation PerNestedConversation (I profiled it with JProfiler).

      So, it just a question for discussion - what is a key reason not to use

      Component component = Component.forName(name);
      component.getScope();


      in method Contexts.lookupInStatefulContexts and search only in this scope or untill this scope?


        • 1. Re: Let's use component scope before lookupInStatefulContext
          shane.bryzak

          Seems reasonable. Could you open a JIRA request for this?

          • 2. Re: Let's use component scope before lookupInStatefulContext
            dmitriy.lapko
            • 3. Re: Let's use component scope before lookupInStatefulContext
              pmuir

              I'm concerned about this as it drastically changes the behaviour of @In - currently if you have a component called user, in the session scope, and outject a variable called user into a the event scope, you would get the variable NOT the component injected. With this proposed change you would get the component injected.

              This would alter the behaviour described in a number places here

              http://docs.jboss.org/seam/2.0.0.CR3/reference/en/html/concepts.html

              Or i have I misunderstood what you want to do?

              • 4. Re: Let's use component scope before lookupInStatefulContext
                dmitriy.lapko

                Yes, I thought about this - that such feature can influence outjection. But if I'm sure, that I wouldn't in any place outject any property with name, equal to my component name, I could just specify it in @Name annotation, like:

                @Name(value = "loginBean", limitSearchByGivenScope="true")

                So in method lookupInStatefulContext we can check if there is a component with such name and it is marked with a propery 'limitSearchByGivenScope', then it should search only in given scope.

                If I suppose, that I would use this possibility to overwrite component by outjected object, I would't use this option.

                Really, I spent last 2 days JProfiling my application and see method getInstance in my hotspots. Too much of calls to method BaseContext.get and ServerConversationContext.isPerNestedConversation...

                • 5. Re: Let's use component scope before lookupInStatefulContext
                  pmuir

                  Ok, I see the problem, but I don't think this is the solution (as it is basically alters the entire way Seam works).

                  perNestedConversation: what version of Seam? As we removed the annotation scan for perNestedConversation for CR3 at least.

                  • 6. Re: Let's use component scope before lookupInStatefulContext
                    pmuir

                    So, you can skip the lookupInStatefullContexts if you use Component.getInstance("foo", SESSION);

                    You can use this in your app using @In(scope=SESSION) Foo foo;

                    However you still have to do a lookupInStatefulContexts when injecting objects into JSF.

                    You should raise JIRA issues if you spot Seam internally not explicitly scoping getInstance() inside instance methods.

                    • 7. Re: Let's use component scope before lookupInStatefulContext
                      dmitriy.lapko

                      Ok, thank you for answer about fixing perNestedConversation, I used previous CR and didn't had this update. Now I updated seam and it works better, thank you again :)

                      But...

                      I made a little experiment concerning lookupInStatefulContexts.

                      1 code:

                      <ui:repeat value="#{itemResultList.resultList}" var="#{item}">
                       <tr>
                       <td class="itemListCenter">
                       #{itemBrowseList.getItemQuantity(item)}
                       </td>
                       </tr>
                      </ui:repeat>
                      


                      2 code:
                      <ui:repeat value="#{itemResultList.resultList}" var="#{item}">
                       <tr>
                       <td class="itemListCenter">
                       #{baseComponent.itemBrowseList.getItemQuantity(item)}
                       </td>
                       </tr>
                      </ui:repeat>
                      


                      The only difference is that in second example itemBrowseList is returned by EVENT scoped component with method:

                      public ItemBrowseListComp getItemBrowseList() {
                       return (ItemBrowseListComp) Component.getInstance("itemBrowseList", ScopeType.SESSION);
                       }
                      


                      itemBrowseList is in SESSION scope.

                      I measure time for RENDER_RESPONSE phase. Page contains a lot of other code, by the way.

                      I use last sources of Seam from CVS.

                      Result list contains 100 elements.

                      So,

                      for code 1: approx. 540ms (#{itemBrowseList.getItemQuantity(item)})
                      for code 2: approx. 310ms (#{baseComponent.itemBrowseList.getItemQuantity(item)})

                      So, difference - (540-310)/100 alsmost 2ms for each EL!

                      I'll raise a JIRE issue for this. And until it will be implemented, I will use this ugly code for my system...



                      • 8. Re: Let's use component scope before lookupInStatefulContext
                        dmitriy.lapko

                        Or, better, to use something like this:

                        in BaseComponent:

                        @Factory(value="itemBrowseListEvent", scope=ScopeType.EVENT)
                        public ItemBrowseListComp getItemBrowseList() {
                         return (ItemBrowseListComp) Component.getInstance("itemBrowseList", ScopeType.SESSION);
                        }
                        


                        and on pages:

                        #{itemBrowseListEvent.getItemQuantity(item)}