10 Replies Latest reply on Feb 12, 2007 12:23 PM by Gavin King

    DataModel

    jk;l jkl; Expert

      I'm removing an entity from a DataModel, so I do an em.remove(selectedEntity), where selectedEntity is the value of the DataModelSelection.

      There's a problem: the entity gets removed and the page gets refreshed with the correct FacesMessage. However, the entity still shows up in the dataTable. Only when I do another refresh of the page does it get removed.

      What are possible reasons for this? I'm not using browser caching... I'm using an SFSB:

      @DataModelSelection("data")
       @Out(required=false)
       private Entity selectedEntity;
      
       @DataModel
       private List<Entity> data;
      
       @Factory("data")
       public void initData() {
       // init the data...
       }




        • 1. Re: DataModel
          Tony Herstell Master

          I had a similar problem.

          My "Find" Session Sateful bean had a liost of users.

          My Controller Stateful conversational fiddled with the store of users.

          When my Controller update the database; this was "behind" the back of the "Find" bean; so it didnt get reflected to the "find" beans "em" cache.

          My solution is below (Gavin may have a better way to do it; but this works for me)

          (need to inject the "Find" bean into the crud Controller bean naturally)

           @End
           @TransactionAttribute(TransactionAttributeType.REQUIRED)
           public String update() {
           log.info("> update");
           user.setPassword(encryptionController.encrypt(user.getPassword()));
           em.merge(user);
           em.flush();
           facesMessages.addFromResourceBundle("user_update_successful");
          
           /*
           * We need to update this user in the list of users in the session scoped FindUserController
           */
           if (findUserController != null) {
           log.info("User sent to database => " + user);
           findUserController.updateUserInExistingList(user);
           }
          
           log.info("< update");
           return "findUser";
           }
          


           public void updateUserInExistingList(User updatedUser) {
           log.info("> updateUserInExistingList");
           List<User> usersList = new ArrayList<User>();
           for (User eachUser : users) {
           if (updatedUser.getId() != eachUser.getId()) {
           usersList.add(eachUser);
           } else {
           em.refresh(eachUser); // Force the update of the user in the em cache.
           log.info("User from the DBase (refreshed) => " + eachUser);
           usersList.add(eachUser);
           }
           }
           users = usersList.toArray(new User[0]);
           applyCurrentQuery();
           log.info("< updateUserInExistingList");
           }
          


          • 2. Re: DataModel
            Tony Herstell Master

            Naturally I had to do similar thing for the Create and Delete too.

            /*
            * Used by external rountines to update the session users list object.
            */
            public void addUserToExistingList(User user);

            public void updateUserInExistingList(User user);

            public void deleteUserFromExistingList(User user);

            • 3. Re: DataModel
              Tony Herstell Master

              Only a guess, but if you are in the same bean you might try an em.flush?

              • 4. Re: DataModel
                jk;l jkl; Expert

                em.flush() doesn't work. It still gives the same problem.

                What could be causing another refresh to be necessary? After the redirect in pages.xml, shouldn't that take care of the refresh?

                • 5. Re: DataModel
                  Gavin King Master

                  What scope is the DataModel. If it is conversation scope, nothing you do to the database is going to be reflected until you update the DataModel itself!

                  • 6. Re: DataModel
                    jk;l jkl; Expert

                    It's only specified as @DataModel right now. If I try putting an @DataModel(scope=ScopeType.something), it gives an error saying it can only be ScopeType.UNSPECIFIED or ScopeType.PAGE.

                    ScopeType.UNSPECIFIED gives identical behavior to having just @DataModel (with no scope), and ScopeType.PAGE gives some very weird behavior. Should it be ScopeType.PAGE or something else?

                    Completely confused...

                    • 7. Re: DataModel
                      Gavin King Master

                      What I'm trying to tell you is that you have to update the DataModel when you change the data.

                      Just like the booking demo does.

                      • 8. Re: DataModel
                        jk;l jkl; Expert

                        That makes sense (and works). Thanks.


                        I have two DataModelSelections for two DataModels on the same SFSB. When I select one table, the DataModelSelection for that gets properly injected, but the other gets injected with null values (and an id of 0).

                        Why is something (albeit a null value) getting injected into the DataModelSelection that I didn't select? This is causing problems when I do a #{empty selectedEntity} to check whether the OTHER entity (the one I didn't select) has been injected.

                        It returns FALSE because it has been injected when it shouldn't have been!

                        Why is a "null entity" getting injected into DataModelSelection? Is this expected behavior? If not, what might be causing it?

                        • 9. Re: DataModel
                          jk;l jkl; Expert

                           

                          What I'm trying to tell you is that you have to update the DataModel when you change the data.


                          That works (i.e. calling the factory method to update the DataModel) when the Factory method grabs results from the database. But I have a Factory that grabs results from another entity that has just been updated.

                          My DataModel is a collection of entities from another entity. e.g. myA.getCollectionOfBs(). My remove method from the DataModel does the following:

                          em.remove(b);
                          // em.flush();
                          runFactory();


                          runFactory() simply does a myA.getCollectionOfBs(), which returns the same set of entities (not removing the entity I just got rid of). I tried doing a flush where I've commented it out above, but that didn't help.

                          What can I do to get these changes reflected? (Short of just doing a query...shouldn't I be able to get them straight from the entities?)

                          • 10. Re: DataModel
                            Gavin King Master

                            You are supposed to remove an entity instance from in-memory associations before deleting it.