9 Replies Latest reply on Aug 9, 2010 12:23 PM by rcorak

    rich:dataTable out of sync with Bean when other user updates DB

    rcorak

      We have a web application using JBoss/Seams, Hibernate & Richfaces with Java.  We had a user who was reporting a problem where they click a commandBtn in a row but a different row's data was being processed.  They said the problem was random with no real pattern.  It turned out that what was happening was that another user (User2) was updating a record on a different screen (changed the record's status).  The new status of the record would cause the record to now be part of the resulting query in the first user's screen next time they refreshed the screen.  However, the first user has not yet updated the screen but there is now a shift in the selection (for example, she clicks on row 6 now but it processes row 5).  I am guessing that the problem is that the backing bean is being updated when the database is updated but the screen does not yet know about the new record.

       

      Some code snippets:

       

      <rich:dataTable var="mb" value=

      "#{dbUtils.diagnosedByReceivedDate}">

       

       

       

         <rich:column>

       

       

            <f:facet name="header">

                #{messages.id}

       

            </f:facet>

       

            ...

      </rich:dataTable>

       

      @Name

       

       

      ("dbUtils")

      @AutoCreate

      public

       

       

      class

      DBUtils {

       

           ...

       

       

      public List<Bottle> getDiagnosedByReceivedDate() {

       

       

        List<Bottle> results =

            this.entityManager.createQuery(

       

          "from Bottle mb where "

          +

           " mb.Status = :diagnosed and "

          +

           " mb.bottle.received >= :startReceivedDate and "

          +

           " mb.bottle.received <= :endReceivedDate and "

          +

           " mb.bottle.sample.rootLevel = :rootLevel ")

          .setParameter(

          "diagnosed",

       

          this.getDiagnosedBottleStatus())

          .setParameter(

          "startReceivedDate",

       

          this.userSession.getSelectStartReceivedDate())

          .setParameter(

          "endReceivedDate",

       

          this.userSession.getSelectEndReceivedDate())

          .setParameter(

          "rootLevel",

       

          this.userSession.getSelectRootLevel())

          .getResultList();

       

          // etc

          Collections.sort(results,

           this.userSession

          .getMecoilBottleComparator());

       

       

          return results;

       

          }

       

       

      }

       

      I tried to resolve this by modifying the scope of the dbUtil class to conversation, page, etc but it had no effect.

       

      I am stuck...

       

      Any help would be greatly appreciated.

       

      Regards,

       

      -Rob

        • 1. Re: rich:dataTable out of sync with Bean when other user updates DB
          ilya_shaikovsky

          what you using as a parameter for getting the selected record?

          1 of 1 people found this helpful
          • 2. Re: rich:dataTable out of sync with Bean when other user updates DB
            rcorak

            Sorry Ilya, I left that part out by accident (it was late last night).

             

            Below is the HTML code  that calls the Java method:

             

             

            <h:commandButton id="storeBottle"

             

            value="#{messages.DiagnosisStore}"

             

            styleClass="StoreBottleAction Action"

             

            action="#{BottleHome.store(mb)}"

             

            />

             

            Below is the corresponding section of generated HTML code on the client side for one of the rows:

             

            <div id="j_id91:j_id115:0:j_id165"><input id="j_id91:j_id115:0:storeMecoilBottle" type="submit" name="j_id91:j_id115:0:storeBottle" value="Send To Admin" class="StoreBottleAction Action" />

             

            When the user clicks the button on the screen, the submit is executed using the id from the original request (does not include the new record).  When the submit executes, does JBoss first resync some internal structure on the server so that the ids are no longer in sync?

             

            Could you outline the specific steps of the process (who gets the submit request, how is it passed to the Java code, when is mb actually resolved?

             

            How do you manage this type of situation from happening OR is there a different design approach that is needed to fix this problem.  I would imagine that this type of problem would occur all the time when you have multiple users updating data that are accessible from multiple screens.

             

            Can you manage this using the @scope for the dbUtil class definition?

             

            Regards,

             

            -Rob

            • 3. Re: rich:dataTable out of sync with Bean when other user updates DB
              rcorak

              After spending more time staring at the client side HTML, i saw that the only difference in the submit caall for the 3 rows of data that I had was an incrementing position (see bolded value below) which seems to be the index of the data row.  That would certainly make sense as to why it would grab the wrong data row back at the server if the data model in the Java bean gets updated dynamically.

               

              td id="j_id91:j_id115:0:j_id162"><input type="submit" name="j_id91:j_id115:0:j_id164" value="Preview" />
              td id="j_id91:j_id115:1:j_id162"><input type="submit" name="j_id91:j_id115:1:j_id164" value="Preview" />
              td id="j_id91:j_id115:2:j_id162"><input type="submit" name="j_id91:j_id115:2:j_id164" value="Preview" />

               

              If there is a data model on the server, isn't it scoped to just your session?  If its just your session, can you prevent it from automatically updating when the backend database is updated?

               

              Can someone break down how he above Submit is processed on the server side to actually make the call on the Java method with the appropriate instance of the object?

               

              Regards,

               

              -Rob

              • 4. Re: rich:dataTable out of sync with Bean when other user updates DB
                germanescobar

                Try the following:

                 

                @Name("dbUtils")
                @AutoCreate
                @Scope(PAGE)
                public class DbUtils {
                
                  private List<Bottle> bottles;
                
                  public List<Bottle> getDiagnosedByReceivedDate() {
                     if (bottles == null) {
                       // load the bottles from the database
                     }
                
                     return bottles;
                  }  
                
                }
                

                 

                Notice that the scope of the bean is Page.

                 

                Hope it helps!

                1 of 1 people found this helpful
                • 5. Re: rich:dataTable out of sync with Bean when other user updates DB
                  nbelaevski

                  Rob,

                   

                  There are standard data models in JSF. They are sequence-based, so that row index is extracted from clientId and that's how data is processed on the server. RichFaces offers extended version of data model (ExtendedDataModel class) that allows to use arbitrary objects as item keys (e.g. entity PK). Examples of ExtendedDataModel usage are available at livedemo.

                   

                  As a variant, you can implement persistent processing of data by storing row index <-> entity relationship information (or row index <-> PK) in the view scope (e.g. via a4j:keepAlive) and use it in your custom model.

                  • 6. Re: rich:dataTable out of sync with Bean when other user updates DB
                    rcorak

                    Thanks Mark,

                     

                    I tried this and am still having th eproblem.  I am going to create a new class like dbUtils but just have the one method call in it and see if I have any more luck (there are lot sof other calls in this class with a variety of definitions).  When I set the dbUtils to PAGE scope, I was getting other errors that three was a NULL pointer because I think that there are other references to this class.

                     

                    I am still trying to understand the flow of control from the point where the submit is done that passes in the ids and the "index" of the row.  When JBoss/Seams receive the submit, what actually happens?  IDoes it go against the database directly?  Is there a cached data model on the server that it hits that has already been updated by the other user's update on the other browser?  If so, how do you detach the list so it doesn't update?  I read something about using "evict" to detach from the Entity Manager.  Do I need to do something with this?

                     

                    Regards,

                     

                    -Rob

                    • 7. Re: rich:dataTable out of sync with Bean when other user updates DB
                      rcorak

                      Thank you Nick for your input.

                       

                      I am wondering if the whole approach for this particular instance is wrong in terms of using the Entity Manager, rich:dataTable, etc.

                       

                      All I want to be able to do is display the list to the user and when they seletc a commandButton, it calls a Java method passing in a value.  The value will never change on the client side and there is no need for the client to stay in synch with the backend database.

                       

                      Regards,

                       

                      -Rob

                      • 8. Re: rich:dataTable out of sync with Bean when other user updates DB
                        germanescobar

                        Rob,

                         

                        The problem is that when the submit button is pressed, Seam will call again the getDiagnosedByReceivedDate() method. It must return the same data that was retrieved in the first place or the DataModel will be messed up. That's why it is so important that the bean has the Page scope. Otherwise, the data is going to be fetched again from the database and if it changed, the index of the selected row will not match the one from the model.

                         

                        German.

                        • 9. Re: rich:dataTable out of sync with Bean when other user updates DB
                          rcorak

                          Thanks German,

                           

                          Using the PAGE scope and the private list variable fixed the problem.  I did have to create a separate dbUtils class because there were other methods in the original one that got messed up when I changed the scope to PAGE.

                           

                          I didn't realize that when the Submit call was made that it actually hit the same method again that fetched the result in the first place.

                           

                          Stepping back, I wish that I could just have the unique id for the sample stored directly in the generated HTML page so there is no need to have to recall the method in the first place.  The value associated with each row does not change.

                           

                          Is there an alternate implementation  for all of this that would build the list on screen and have it totally detached from the backend JAVA?  The current generated HTML code fom Seam/Richfaces creates the Submit with the index into the list.  How could I have it so that it generated a straight call to the method with the mb.name value already in the submit (without having to go back to the original method and grab the list variable to index into)?

                           

                          Thanks for all your assistence.

                           

                          Regards,

                           

                          -Rob