4 Replies Latest reply on Jun 23, 2006 5:24 AM by Carsten Hoehne

    SFSB are evil? (The eternal Update problem)

    Markus Dahm Novice

      Hi,

      I seem to have a general problem with refreshing views from the database
      when using SFSB like in the examples.
      Remember the messages list example, I've got except pretty much the
      same code, except there is a link on the page where you can edit the specified row entry.

      @Stateful
      @Scope(ScopeType.SESSION)
      @Name("listVertraege")
      @Interceptors(SeamInterceptor.class)
      public class ListVertragActionBean implements Serializable, ListVertragAction {
       private static final Category _logger = Logger.getInstance(ListVertragActionBean.class);
       private static final long serialVersionUID = 1L;
      
       @DataModel(value = "vertraege")
       private List<Vertrag> _vertraege;
      
       @Out(required = false, value = "vertrag")
       @DataModelSelection
       private Vertrag _vertrag;
      
       @SuppressWarnings("unused")
       @Out(value = "vertragReadOnly", required = false)
       private Boolean _vertragReadOnly;
      
       @PersistenceContext(type = EXTENDED)
       private EntityManager _em;
      
       @SuppressWarnings("unchecked")
       @Factory("vertraege")
       public void findVertraege() {
       _vertraege = _em.createQuery("from Vertrag v order by v.vertragsBeginn").getResultList();
       }
      
       public String select() {
       return "selected";
       }
      
       public String delete() {
       _vertrag.removeAllVertragspartner();
       _vertrag.removeAllPatient();
       _vertraege.remove(_vertrag); // Auch aus dem Datenmodell entfernen
       _em.remove(_vertrag);
       _vertrag = null;
       return "deleted";
       }
      
       public String edit() {
       return rereadAndEdit(false);
       }
      
       public String end() {
       return rereadAndEdit(true);
       }
      
       private String rereadAndEdit(boolean readonly) {
       _vertragReadOnly = readonly;
       // May be modified meanwhile
       _em.refresh(_vertrag);
      
       return "editVertrag";
       }
      
       @Remove
       @Destroy
       public void destroy() {
       }
      }
      


      Now the problem is that the data model isn't updated when I've modified
      the data somewhere else (The changes are in the database).
      I checked it, and the find() method is not called when I revisit the page.
      How can I enforce that the list is reread?

      This is a general problem I have with SFSB, the caching ignores
      database changes or worse overrides them. I had the suspect that
      this could be someting with the way I implemented the equals()
      method for the Vertrag class, but after modification it still didn't work

      By the way setting scope=PAGE in the @DataModel didn't work. The data
      may be reloaded every time, but the @DataSelection _vertrag field isn't
      set anymore (always null) and the select(), end() and edit() methods are not called.

      Any help will be appreciated...

      Cheers
      Markus


        • 1. Re: SFSB are evil? (The eternal Update problem)
          fhh Expert

          Well, this is how stateful session beans are supposed to work. They save their state and that includes your List _vertraege.

          So the question is what you really want to do. If you want to keep in sync with the database at any cost, you could user a stateless session bean. But doing so will cost performance since the db is re-read for every request. (I'm not sure how much is cached by hibernate. You may run into problems with hibernate cache)

          If you don't have a lot of use (and not too man vertraege in the db) the performance loss should be negligible.

          The "Big" solution would be to use JBoss' entity cache or implement your own caching strategy. But this will only work as expected iff your webapp is the ONLY application modifying the data in the db.

          Refards

          Felix

          • 2. Re: SFSB are evil? (The eternal Update problem)
            Carsten Hoehne Master

            Hello,
            Your problem looks very common for me.

            I checked it, and the find() method is not called when I revisit the page.

            That is correct. The find() method is only called when vertraege is null.
            That is the meaning of a factory method.
            How can I enforce that the list is reread?

            Easy answer. You have to set vertraege to null.
            But to implement it is sometimes not so easy. Look at the hotelbooking example for a hint.

            • 3. Re: SFSB are evil? (The eternal Update problem)
              Markus Dahm Novice

              Hi,

              thanks for the reply...


              How can I enforce that the list is reread?



              Easy answer. You have to set vertraege to null.
              But to implement it is sometimes not so easy. Look at the hotelbooking example for a hint.


              It's not that easy indeed, because I alread tried to set this field to null
              in the edit() action. However this caused an immediate reload from
              the database thus loading again the old data. The the page flow then went
              to the edit page. But when I got back to the listing page I still was stuck
              with the old data.
              I also tried to export the list using @Out so I could clear it elsewhere.
              The @DataModel docs says somewhere that List.equals() is used to
              determine when to reload the data. However it's not that specific when
              this actually occurs.

              Funnily, I have implemented very similar code elsewhere but have no
              clue what could be wrong here.

              BTW: Could you please be more specific where to look a the hotel booking
              example. It's a rather big one :-)

              Cheers
              Markus

              • 4. Re: SFSB are evil? (The eternal Update problem)
                Carsten Hoehne Master

                 

                BTW: Could you please be more specific where to look a the hotel booking
                example.

                I meant the booking example for hibernate and tomcat. There exists in class HotelBookingAction this method:
                @End
                 public String clear()
                 {
                 hotels = null;
                 hotel = null;
                 booking = null;
                 return "main";
                 }

                But the original example is refactored so this method does not exists anymore.

                Try to ask you the question: Is there a way to avoid the @factory for the datamodel?
                Perhaps the answer to this question will lead you to a better implementation.
                Funnily, I have implemented very similar code elsewhere but have no
                clue what could be wrong here.


                Same here...