12 Replies Latest reply on Feb 27, 2009 8:23 PM by andygibson.contact.andygibson.net

    More than one @Factory in a controller

    tony.herstell1

      can you have more than one @Factory in a controller?



      I ma having to call the second factory from the first one as a workaround.


          /* (non-Javadoc)
           * @see nz.co.selwynequestriancentre.action.eventsManagement.EventsManagementController#findEvents()
           */
          @Factory("availableEvents")
           @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
           @Override
           public void findEvents()
           {
               if (eventList == null) {
                    eventList = (List<Event>)em.createQuery("from Event e order by e.entriesCloseDate asc").getResultList();
               }
               findUsers();
           }
           
           /* (non-Javadoc)
            * @see nz.co.selwynequestriancentre.action.eventsManagement.EventsManagementController#findUsers()
            */
           @Factory("availableUsers")
           @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
           @Override
           public void findUsers()
           {
                if (availableUsers.isEmpty()) {
                     List<User> allAvailableUsers = (List<User>)em.createQuery("from User u order by u.surname asc").getResultList();
                     }
                }
           }
      


        • 1. Re: More than one @Factory in a controller
          tony.herstell1

          @DataModel(value="availableEvents")
               private List<Event> eventList;
          
           @Out(value="availableUsers",required=true)
              private List<User> availableUsers = new ArrayList<User>();
          


          • 2. Re: More than one @Factory in a controller
            tony.herstell1

            List<User> availableUsers = (List<User>)em.createQuery("from User u order by u.surname asc").getResultList();



            This should have read this...



            Anyone???

            • 3. Re: More than one @Factory in a controller
              clerum

              Tony,


              Did you ever find anything on this? I'm running into the same thing.

              • 4. Re: More than one @Factory in a controller
                tony.herstell1

                Sorry I didn't.


                The initial workaround for calling the second (and third one!) one from the first one is still in place in my code.


                You might raise a JIRA unless someone knows of the proper way to do this?

                • 5. Re: More than one @Factory in a controller
                  norman

                  I'm sorry.  I must be dense, but I don't understand what the problem is.  I've never seen any issues with multiple named factories on one component. 

                  • 6. Re: More than one @Factory in a controller
                    tony.herstell1

                    @SuppressWarnings("serial")
                    @Stateful
                    @Conversational
                    @Scope(value=ScopeType.CONVERSATION)
                    @Name("eventsController")
                    public class EventsControllerImpl implements EventsController, Serializable {
                    
                    SNIP
                    
                         @DataModel(value="availableEvents")
                         private List<Event> eventList;
                         
                         @DataModel(value="allEventsClasses")
                         private List<ClassEntity> allEventsClasses;
                         
                         @DataModel(value="eventsPrizePics")
                         private List<Image> eventsPrizePics;
                         
                         @DataModel(value="eventsWinnerPics")
                         private List<Image> eventsWinnerPics;
                         
                         @DataModel(value="classEntityPrizePics")
                         private List<Image> classEntityPrizePics;
                         
                         @DataModel(value="classEntityWinnerPics")
                         private List<Image> classEntityWinnerPics;
                         
                    SNIP
                    
                    
                        @Out(value="availableUsers",required=true)
                        private List<User> availableUsers = new ArrayList<User>();
                        
                        @Out(value="allAvailableTests",required=true)
                        private List<Test> allAvailableTests = new ArrayList<Test>();
                        
                    SNIP
                    
                    
                        /* (non-Javadoc)
                         * @see nz.co.selwynequestriancentre.action.eventsManagement.EventsManagementController#findEvents()
                         */
                        @Factory("availableEvents")
                         @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
                         @Override
                         public void findEvents()
                         {
                             if (eventList == null) {
                                  eventList = (List<Event>)entityManager.createQuery("from Event e order by e.entriesCloseDate asc").getResultList();
                             }
                             findUsers();
                             findTests();
                         }
                         
                         /* (non-Javadoc)
                          * @see nz.co.selwynequestriancentre.action.eventsManagement.EventsManagementController#findUsers()
                          */
                         @Factory("availableUsers")
                         @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
                         @Override
                         public void findUsers()
                         {
                              if (availableUsers.isEmpty()) {
                                   availableUsers = (List<User>)entityManager.createQuery("from User u order by u.surname asc").getResultList();
                              }
                         }
                         
                         @Factory("allAvailableTests")
                         @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
                         @Override
                         public void findTests()
                         {
                              if (allAvailableTests.isEmpty()) {
                                   allAvailableTests = (List<Test>)entityManager.createQuery("from Test t order by t.description asc").getResultList();
                              }
                         }
                              
                         /* (non-Javadoc)
                          * @see nz.co.selwynequestriancentre.action.eventsManagement.EventsManagementController#enter()
                          */
                         @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
                         @Override
                         @Begin
                         public String enter() {
                              log.info(">enter");
                              this.event = null;
                              this.mode = Mode.READ;
                              // Used for editor component.
                              configurations.add(new SelectItem(CONFIGS_PACKAGE + "simple", "Simple"));
                              configurations.add(new SelectItem(CONFIGS_PACKAGE + "advanced", "Advanced"));
                              log.info("<enter");
                              return "eventSelection";
                         }




                    The above code shows me having to call the other factories (BOTH OF THEM) as Factory didn't work too well.


                    I have 100 hours work to do today so will try seeing if it got fixed with latest release sometime!


                    :)

                    • 7. Re: More than one @Factory in a controller
                      clerum

                      I ran into the same thing.


                      The first factory is created and works fine and the second one just returns null when it gets called from the datatable.


                      I did the same as Tony and did a work around by calling the factory method from the first since they both need to be called anyway....but that doesn't seem like the right way.

                      • 8. Re: More than one @Factory in a controller
                        clerum

                        I see the issue on 2.1.1GA just to be clear.

                        • 9. Re: More than one @Factory in a controller
                          tony.herstell1

                          Note that in my code the second and third factories are not exposed as DataModels. No idea whether its relevant.

                          • 10. Re: More than one @Factory in a controller
                            norman

                            @Factory is trigger lazy initialization from outside the component.  If you just want to make sure those values are set when the component is first accessed, maybe you should do the initialization in the @Create method?

                            • 11. Re: More than one @Factory in a controller
                              buckmin.erdem.agaoglu.gmail.com

                              I ran into same problem a while back which i overcame by initing manually just like everyone did. and i agree it's not an elegant solution.
                              Although what Norman proposed seems to be the best way, i managed another solution. IMHO if we need that list as both java.util.List and DataModel at different times, we should have both of them in context.


                              @In(create=true) @DataModel("abstractTextFieldDM")
                              List<AbstractTextField> abstractTextFieldList;
                              
                              @DataModelSelection("abstractTextFieldDM")
                              AbstractTextField selectedAbstractTextField;
                              
                              ...
                              
                              @Factory("abstractTextFieldDM")
                              public void initAbstractTextFieldDM(){
                                   // we dont need to do anything, var is already injected
                              }
                              
                              @Factory("abstractTextFieldList")
                              public List<AbstractTextField> getAbstractTextFieldList(){
                                   abstractTextFieldList = abstractTemplate.getAbstractTextFieldList(); // or em.createQuery
                                   return abstractTextFieldList;
                              }
                              


                              Important thing here is that we have to define List factory with a return type. since a void factory does not return anyting, injection fails with a NPE, not a RequiredException (This may be a bug).


                              This worked better for me as i often need to access the actual list but since context var is a ListDataModel i have to go through getWrappedData(). But i dont know about performance implications whatsoever. so it'll be good to have an expert opinion on this approach.

                              • 12. Re: More than one @Factory in a controller
                                andygibson.contact.andygibson.net

                                Could it be that the problem lies in the fact that you are outjecting the values when you call the first factory method and since the values exist, the factories are not being called.


                                For example, you request the El Expression for one of the values and it calls the first factory and the outjection takes place and outjects value 'abc'. When the EL resolver goes looking for 'abc' it finds the value that was outjected and thus never calls the factory.  If this is the case, your fix works because you are initializing those values before they are outjected.


                                Cheers,


                                Andy