10 Replies Latest reply on Oct 29, 2008 12:45 PM by bartdp

    Using Factory annotation

    bartdp

      Hi all,


      I'm filling my selectbox with values from the db. Therefor I'm using the @Factory annotation in my bean.
      I have 1 problem with this solution. This selectbox is placed in my header template, so every time I do an action, this is rendered again. Is there a better solution for this?


      Thx, Bart

        • 1. Re: Using Factory annotation
          joaobmonteiro

          Hi Bart,


          Have you tried to use @Factory with a scope definition ? Something like this:


          @Factory(scope=ScopeType.SESSION)
          



          Of course you have to select the correct scope according to your application.

          • 2. Re: Using Factory annotation
            bartdp

            I can't set the scope according the seam documentation. The scope should not be used when the factory method is void.

            • 3. Re: Using Factory annotation
              joaobmonteiro

              That's right, I forgot that.


              When I need to use any collection through my entire application, I usually put everything I need in a Seam component with Session/Application scope so I can retrive those values once from db.


              Everything that is commom for the entire application and that is not modified frequently, I put in that component for easy access.


              I hope it can now help :)

              • 4. Re: Using Factory annotation
                nimo22

                Hey Joao, do you use the


                @Startup-Annotation or @Factory or @Create ?


                Should we use the @Startup-Annotation for stuff like that?


                • 5. Re: Using Factory annotation
                  bartdp

                  I allready use the @Factory annotation to get the data. I know how to use the annotations.
                  I'm searching for the right solution. So the dropdown is filled with the data I need, but the problem is that this dropdown is put into the header template and this template will always rendered by every action.

                  • 6. Re: Using Factory annotation
                    joaobmonteiro

                    Hi Nimo,


                    The annotation you need may vary according to your application design. I suggest to put in global managed beans only collections that span the entire application. A typical usage is a list with countries, cities and so on.


                    @Startup is good for retrive some resources you need right after inicialization. I usually use this for schedulers and batch jobs. I don't use many @Factory for no specific reason.


                    @Create I always use to initialize my managed beans correctly but for using the suggestion I gave you don't need anything.


                    You could do some lazy initialization as described in http://www.seamframework.org/Documentation/WhyDoesJSFCallMyGetterHundredsOfTimes in an ordinary managed bean with higher scope (Session or Application for example).


                    If you use @Create to initialize all collections you could do more work than you really need. In the end, your global managed bean is simply a POJO with lazy inicialization.


                    I am not an expert to say that it is a good solution but I am using this approach successfully.

                    • 7. Re: Using Factory annotation
                      admin.admin.email.tld

                      Marks a method as a factory method for a context variable. A factory method is called whenever no value is bound to the named context variable, and is expected to initialize the value of the context variable. There are two kinds of factory methods. Factory methods with void return type are responsible for outjecting a value to the context variable. Factory methods which return a value do not need to explicitly ouject the value, since Seam will bind the returned value to the specified scope. This annotation supports use of the Seam factory component pattern.

                      http://docs.jboss.org/seam/2.0.1.CR1/api/org/jboss/seam/annotations/Factory.html


                      so you can outject the variable to Session scope and thus the @Factory method will only exec once per session (as long as it doesn't get nulled out elsewhere in the code).


                      example:


                      @Factory(value="fooString", scope=ScopeType.SESSION)
                      public String getFoo()
                      {
                          return "foo";
                      }



                      @Out(required=false, scope=ScopeType.SESSION)
                      private List fooList;
                      
                      @Factory("fooList")
                      public void getFoo()
                      {
                          fooList = new ArrayList<String>();
                          fooList.add("bar");
                      }



                      • 8. Re: Using Factory annotation
                        utdrew

                        There are two problems you might be trying to solve here


                        1) Factory method gets called for every action.  In this case change the scope as people have suggested.
                        2) Since the list is static you would prefer that it not get rendered every time.  In this case you would probably want to look into the s:cache tag.


                        Drew

                        • 9. Re: Using Factory annotation
                          bartdp

                          I am using the session scope. Maybe it is better that I post some code.
                          So in my bean:


                               @Out(required = false, scope = ScopeType.SESSION)
                               private List<SelectItem> productsDropdown;
                          
                               @Factory(value="productsDropdown")
                               public void getProductsDropdown() {
                                    log.info("* getProductsDropdown *");
                                  ...set the productsDropdown
                          


                          In the header.xhtml (I'm using ICEFaces):


                               <ice:panelGroup>
                                    <ice:selectOneMenu value="#{user.product.name}" partialSubmit="true">
                                         <f:selectItems value="#{productsDropdown}"/>
                                    </ice:selectOneMenu>
                               </ice:panelGroup>
                          


                          By every action, I see the getProductsDropdown as log information.


                          What is wrong with my code?




                           

                          • 10. Re: Using Factory annotation
                            bartdp

                            Ok, I founded myself. Fasten your seatbelts.



                            In have also a scope annotation on class level:


                            @Scope(ScopeType.CONVERSATION)
                            public class ...
                            



                            Pfff, I'm still sweating...
                            So keep in mind the scope annotations.