12 Replies Latest reply on May 3, 2012 8:10 AM by healeyb

    Inconsistent ApplicationScoped bean value

    jn.colin

      Hello,

       

      Here's my problem.

       

      I have defined an ApplicationScoped managed bean, which contains some Lists of values

      @ManagedBean

      @ApplicationScoped

      public class GlobalData implements Serializable {

       

      I have two other beans, defined as:

       

      @ManagedBean

      @ViewScoped

      public class AdminEventsBean implements Serializable {

        @ManagedProperty(value = "#{globalData}")

                private GlobalData globalData = null;

       

      and

       

      @ManagedBean

      @ViewScoped

      public class RegistrationBean implements Serializable {

        @ManagedProperty(value = "#{globalData}")

                private GlobalData globalData = null;

       

      When I call a reload method from the first one on the ApplicationScoped one, I can see that the list gets reloaded properly.

      However, when I access the list from the second on on the ApplicationScoped one, I can't see the updated list, it always contains the first set of values.

       

      Did I miss something or is there something wrong?

       

      Thanks for your help

       

      Jean-Noël

        • 1. Re: Inconsistent ApplicationScoped bean value
          healeyb

          Looks ok except for initialising globalData to null in the view scoped beans, can you try without this? Also

          check that you have the correct javax.faces.bean... imports for the @...Scoped annotations and not CDI

          variants.

           

          Regards,

          Brendan.

          • 2. Re: Inconsistent ApplicationScoped bean value
            jn.colin

            I just try without setting globalData to null, and the problem is still the same.

             

            Something to add though (not related to the test you asked for):

             

            If, in the setter for globalData defined in RegistrationBean, I add a call to the reload function:

             

                      public void setGlobalData(GlobalData globalData) {

                                this.globalData = globalData;

                                globalData.reloadEvents();

                      }

             

            then I get the proper list.

             

            So it's really like if both ViewScoped bean had their own version of the ApplicationScoped bean, which seems against the design, doesn't it? :-)

            • 3. Re: Inconsistent ApplicationScoped bean value
              healeyb

              That's got to be what's happening, 2 app scoped beans !! Can you put some logging in a no-arg constructor and an

              @PostConstruct method and print out this.toString() - also in the getGlobalData() method.

              • 4. Re: Inconsistent ApplicationScoped bean value
                jn.colin

                I hope I understood your suggestion correctly.

                 

                In each of the 3 beans, i added the following method:

                  @PostConstruct

                          public void postConstructMethod() {

                                    System.out

                                                        .println("RegistrationBean PostConstruct: " + globalData.toString());

                          }

                 

                (of course, in globalData, it outputs this.toString())

                 

                When looking at the logs, here's what i get:

                 

                ws-92-166:logs jnc$ grep PostConstruct catalina.out

                GlobalData PostConstruct: be.erigo.fclusers.GlobalData@2af7b740

                RegistrationBean PostConstruct: be.erigo.fclusers.GlobalData@2af7b740

                AdminEventsBean PostConstruct: be.erigo.fclusers.GlobalData@2af7b740

                RegistrationBean PostConstruct: be.erigo.fclusers.GlobalData@2af7b740

                 

                so it looks consistent, doesn't it?

                 

                I've also added a printout in each constructor, and here again, output seems ok:

                 

                ws-92-166:logs jnc$ grep Building catalina.out

                Building RegistrationBean

                Building GlobalData

                Building AdminEventsBean

                Building RegistrationBean

                 

                But still, the lists are not consistent in the two ViewScoped beans, even though I can see the reload taking place in the ApplicationScoped bean.

                 

                Thanks for your help

                • 5. Re: Inconsistent ApplicationScoped bean value
                  healeyb

                  what is globalData.toString() when you access the data in the view scoped beans? if the data is different, it has to

                  be a different hash code, unless the data is being changed between accesses. There is an outstanding issue related

                  to this:

                   

                  http://java.net/jira/browse/JAVASERVERFACES-1705

                   

                  What JSF version are you using? A real long shot but perhaps try @ManagedBean(eager = true) on the app scoped

                  bean, no real reason but can't think of anything else!

                  • 6. Re: Inconsistent ApplicationScoped bean value
                    jn.colin

                    Hello again,

                     

                    To be a bit more concrete: the AdminEventsBean allows to create new data and push it to the database (using hibernate); to avoid going to the DB to query the data, since it's rather static, it also calls a reload function on the GlobalData bean, that reloads the data from the db; then, the RegistrationBean calls the getEventItems, which is defined as:

                              private List<SelectItem> eventItems = new ArrayList<SelectItem>();

                     

                    and accessible through getter only.

                     

                     

                    I tried adding more printouts, and I get surprising results. In the ApplicationScoped bean (GlobalData), in the getter for the inconsistent field, I've added a print of the content of the list:

                     

                     

                              public List<SelectItem> getEventItems() {

                     

                                        System.out

                                                            .println("GlobalData.getEventItems: " + this.toString() + "#" + eventItems.toString());

                      return eventItems;

                              }

                     

                    When I check the logs, I find the following:

                     

                    ws-92-166:logs jnc$ grep GlobalData.getEventItems catalina.out
                    GlobalData.getEventItems: be.erigo.fclusers.GlobalData@3addc3fe#[javax.faces.model.SelectItem@356e76e3, javax.faces.model.SelectItem@673f4c7c, javax.faces.model.SelectItem@6cb695d8, javax.faces.model.SelectItem@4727cfaa, javax.faces.model.SelectItem@6b2c665]
                    GlobalData.getEventItems: be.erigo.fclusers.GlobalData@3addc3fe#[javax.faces.model.SelectItem@356e76e3, javax.faces.model.SelectItem@673f4c7c, javax.2.1.7faces.model.SelectItem@6cb695d8, javax.faces.model.SelectItem@4727cfaa, javax.faces.model.SelectItem@6b2c665]
                    GlobalData.getEventItems: be.erigo.fclusers.GlobalData@4ffecba5#[javax.faces.model.SelectItem@60ebe6aa, javax.faces.model.SelectItem@1f74d49c, javax.faces.model.SelectItem@2f325de6, javax.faces.model.SelectItem@13b2bf3f, javax.faces.model.SelectItem@3c29cb33, javax.faces.model.SelectItem@5bdba020]
                    GlobalData.getEventItems: be.erigo.fclusers.GlobalData@3addc3fe#[javax.faces.model.SelectItem@356e76e3, javax.faces.model.SelectItem@673f4c7c, javax.faces.model.SelectItem@6cb695d8, javax.faces.model.SelectItem@4727cfaa, javax.faces.model.SelectItem@6b2c665]
                    GlobalData.getEventItems: be.erigo.fclusers.GlobalData@3addc3fe#[javax.faces.model.SelectItem@356e76e3, javax.faces.model.SelectItem@673f4c7c, javax.faces.model.SelectItem@6cb695d8, javax.faces.model.SelectItem@4727cfaa, javax.faces.model.SelectItem@6b2c665]
                    GlobalData.getEventItems: be.erigo.fclusers.GlobalData@3addc3fe#[javax.faces.model.SelectItem@356e76e3, javax.faces.model.SelectItem@673f4c7c, javax.faces.model.SelectItem@6cb695d8, javax.faces.model.SelectItem@4727cfaa, javax.faces.model.SelectItem@6b2c665]

                     

                     

                    All lists are the same, except the 3d one, which is the one obtained after calling the reload function on globalData from one of the ViewScoped beans. So it shows that after the call to reload, the list is properly updated (it contains the additional element), but as soon as I move to another page which calls the getEventItems (through the JSF lifecycle), it returns to the old version.

                     

                    I'm using JSF 2.1.7

                     

                    I tried the eager=true option but it didn't help

                     

                    Thanks for your help

                    • 7. Re: Inconsistent ApplicationScoped bean value
                      healeyb

                      >GlobalData@4ffecba5

                       

                      this is the problem, in the third list globalData is a seperate chunk of VM entirely. There's just got to be

                      something different about the environment this is running in, and how it accesses globalData, compared

                      to when you have GlobalData@3addc3fe.


                      • 8. Re: Inconsistent ApplicationScoped bean value
                        jn.colin

                        I do understand that that's the problem, but what can cause this? The constructor of GlobalData is called only once, I verified this. So how can I have two instances of an ApplicationScoped bean?

                         

                        I made another test: in the AdminEventsBean, which calls the reload function on GLobalData, here's the trace:

                         

                        Building AdminEventsBean

                        AdminEventsBean Setting globalData to be.erigo.fclusers.GlobalData@13603408

                        AdminEventsBean PostConstruct: be.erigo.fclusers.GlobalData@13603408

                        AdminEventsBean Reloading be.erigo.fclusers.GlobalData@6c910628

                        AdminEventsBean Reloaded 5

                         

                        the first message comes from the constructor

                        the second one comes from the setter of the managed-property. Is it normal that it comes before the PostConstruct?

                        the third one is from the PostConstruct

                        the fourth one is called from the Action method, described in the xhtml as:

                          <h:commandButton action="#{adminEventsBean.addAction}" value="Add"

                          rendered="#{!adminEventsBean.updateMode}" />

                         

                        it clearly references a different instance of GlobalData, which has never been instantiated (at least if I trust the printout added to the constructor)

                         

                        So what's happening here?

                         

                        Thanks a lot


                        • 9. Re: Inconsistent ApplicationScoped bean value
                          healeyb

                          Hang on, I may have got it. Just remembered from "Core JSF" that the @ManagedProperty must have a public

                          setter method, so does the bean that generated this output (AdminEventsBean Reloading be.erigo.fclusers.GlobalData@6c910628)

                          have a setGlobalData() method?

                           

                          Regards,

                          Brendan.

                          • 10. Re: Inconsistent ApplicationScoped bean value
                            jn.colin

                            Unfortunately, yes, all beans have public setters and getters for the @ManagedProperty.

                            I did another test, and found something else which is very strange: in the addAction action which is used from the AdminEventsBean (viewscoped) to store new items in the DB and then invoke the reload function on globalData, I added the following printouts:

                             

                                                System.out

                                                                    .println("AdminEventsBean addAction " + globalData.toString());

                                                FacesContext context = FacesContext.getCurrentInstance();

                                                GlobalData bean = (GlobalData) context.getApplication().evaluateExpressionGet(context, "#{globalData}", GlobalData.class);

                                                System.out

                                                .println("AdminEventsBean addAction bis " + bean.toString());

                             

                             

                            Looking at the trace, I can see that the two globalData are not the same; the first one (GlobalData@38493622) is incorrect, and it's the one that will be used to reload, hence my problem. The same applies to the other viewscoped bean

                             

                            Building AdminEventsBean

                            AdminEventsBean Setting globalData to be.erigo.fclusers.GlobalData@3303dccc

                            AdminEventsBean PostConstruct: be.erigo.fclusers.GlobalData@3303dccc

                            AdminEventsBean addAction be.erigo.fclusers.GlobalData@38493622

                            AdminEventsBean addAction bis be.erigo.fclusers.GlobalData@3303dccc

                            AdminEventsBean Reloading be.erigo.fclusers.GlobalData@38493622

                            AdminEventsBean Reloaded 6

                             

                            again, many thanks for your help

                            • 11. Re: Inconsistent ApplicationScoped bean value
                              jn.colin

                              Brendan, I found it!!

                               

                              In my web.xml, I had:

                               

                                <context-param>

                                                  <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>

                                                  <param-name>javax.faces.STATE_SAVING_METHOD</param-name>

                                <param-value>client</param-value>

                                </context-param>

                               

                              Changing it to:

                               

                                <context-param>

                                                  <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>

                                                  <param-name>javax.faces.STATE_SAVING_METHOD</param-name>

                                <param-value>server</param-value>

                                </context-param>

                               

                              did the trick. Not sure why, though...

                               

                              Thanks a lot for your help


                              • 12. Re: Inconsistent ApplicationScoped bean value
                                healeyb

                                Great you got it fixed, I've added this to my list of "things to watch out for".