9 Replies Latest reply on Oct 4, 2006 3:16 PM by Gavin King

    Stale Data until redeploy

    Samuel Mendenhall Apprentice

      I posted in the EJB 3.0 forum without much success, so I am hoping this forum can help me, as the users are more active.

      I am having a horrible time with stale data. In my seam app, I create jobs then list the jobs, and I can click on a job to edit it. However, when I edit a job, the changes absolutely refuse to show up in the listing of jobs, the listing of jobs only shows the state of when I initially created a job, and NO changes.

      This is really driving me mad and I am not sure how to fix it.

      I am using MySQL InnoDB, and everything shows up as correct in the database. All the data is current and right, however in my view, all the data is old. Is there some cache I need to disable, or someway to can ensure the data for listing my jobs is not stale.

      I've tried several things like giving the Query hints and disabling 2nd level cache in the persistence.xml, but nothing works.


      @Name("viewJobs")
      @Stateful
      @Scope(ScopeType.SESSION)
      public class ViewJobsBean implements ViewJobs {
      
       @Logger
       private Log log;
      
       @DataModel
       private List<Job> jobs;
      
       @DataModelSelection
       private Job job;
      
       @PersistenceContext(type=EXTENDED)
       private EntityManager em;
      
       public String view() {
       Map parameters = new HashMap();
       StringBuffer queryString = new StringBuffer();
      
       queryString.append("from Job");
      
       Query query = em.createQuery(queryString.toString());
      // query.setHint("org.hibernate.cacheable", new Boolean(false));
      // query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE);
      // query.setHint("org.hibernate.flushMode", FlushMode.ALWAYS);
      
       jobs = (List<Job>) query.getResultList();
       return "viewJobs";
       }
      
       public void delete(){
       em.remove(job);
       view();
       }
      
       public void refresh() {
       view();
       }
      
       @Destroy @Remove
       public void destroy() {}
      }
      


      <persistence>
       <persistence-unit name="entityManager">
       <provider>org.hibernate.ejb.HibernatePersistence</provider>
       <jta-data-source>java:/jobsDatasource</jta-data-source>
       <properties>
       <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
       <!--<property name="hibernate.hbm2ddl.auto" value="update"/>-->
       <property name="hibernate.show_sql" value="true"/>
       <property name="hibernate.format_sql" value="true" />
       <!--<property name="hibernate.cache.use_second_level_cache" value="false" />-->
      
       <!--<property name="hibernate.jdbc.batch_size" value="0" />-->
       <property name="jboss.entity.manager.factory.jndi.name" value="java:/jobsEntityManagerFactory"/>
       </properties>
       </persistence-unit>
      </persistence>
      
      


      The only way to Can get the changes to the jobs to show up is if I redeploy the web app. Am I missing something?

      Help with this is greatly appreciated

        • 1. Re: Stale Data until redeploy
          Gavin King Master

          You have a session-scope SFSB with an extended persistence context! What behavior did you expect??

          • 2. Re: Stale Data until redeploy
            Samuel Mendenhall Apprentice

            I need the Statefullness because I intent on adding pagination, and I need the extended persistence context because the job contains Lazy initialized collections.

            Am I just overlooking something very simple? All I want is for the data for this specific viewJobs SFSB to be refreshed everytime the view method gets called. There must be someway to override the default behavior?

            Please advise

            • 3. Re: Stale Data until redeploy
              Gavin King Master

              Well, OK, server-side state is *one* way to do pagination.

              But an extended persistence context caches data in the server. It is never aware of any changes you make to data via some other persistence context. So you must either:

              (1) do any updates in the scope of the same persistence context OR
              (2) use em.refresh()

              if you want to see changes made by other contexts.

              But the reality is that a SESSION scoped persistence context is always a bad thing (it is a memory leak, to begin with), and you should never do that.

              There are other ways to solve your problem. A great start is to not try to pass an entity instance directoly from the search screen to the detail screen. Instead, re-fetch it using find(), or merge it using merge().

              • 4. Re: Stale Data until redeploy
                Samuel Mendenhall Apprentice

                Thank you for the response, I am currently not passing the entity reference to the details screen like you advised not too. I pass the entity id as a parameter, then in my details screen I em.load the entity.

                What is the most accepted way to do pagination? If I don't use the SESSION should I use CONVERSATION?

                My error, then, was assuming that the IssueFinderBean.java in the issues example was standard practice to do pagination. If it is not, then this is very misleading to people who are trying to learn SEAM by the examples.

                So how do I correctly implement my goals: pagination with the most recent data everytime the page is refreshed?

                • 5. Re: Stale Data until redeploy
                  Gavin King Master

                  The example is *perfectly* fine because it does not use an extended persistence context!

                  It is the combinations of @Scope(SESSION) and @PersistenceContext(type=EXTENDED) that is the problem.

                  • 6. Re: Stale Data until redeploy
                    Samuel Mendenhall Apprentice

                    So you are saying that one way to fix it is to do a refresh on all jobs in the job list?

                    public String view() {
                     Map parameters = new HashMap();
                     StringBuffer queryString = new StringBuffer();
                    
                     queryString.append("from Job");
                     Query query = em.createQuery(queryString.toString());
                    
                     jobs = (List<Job>) query.getResultList();
                    
                     //Refresh all of the jobs
                     for(int x = 0; x < jobs.size(); x++){
                     em.refresh(jobs.get(x));
                     }
                     return "viewJobs";
                    }
                    


                    This does work to get the latest data, but isn't there a better way? Now I am doing an additonal trip to the database for every job, there must be someway to force the retrieval of the new data each call NOT from cache? Isn't this going to scale horrible when I get thousands of jobs?



                    • 7. Re: Stale Data until redeploy
                      Samuel Mendenhall Apprentice

                      I see now what you are saying with the example. However, that still begs the question, what is the correct way to implement pagination when one has Lazily initialized collections where the EXTENDED PersistenceContext must be used, but you are saying that there is a problem using that with @Scope(SESSION)

                      Also, I can't use EAGER fetching with my collections (List) because of the cannot select multiple bags bug. Or has that been fixed?

                      • 8. Re: Stale Data until redeploy
                        Gavin King Master

                        So, just especially for you, I added pagination to the booking example in CVS.

                        There is no safe way to pass an object instance from the session scope to a conversation or event and expect lazy fetching to happen automatically. Instead, when you pass an entity that lives in the session scope to another event that needs to do lazy fetching, you should refetch or merge the object, just like HotelBookingAction.selectHotel() does.

                        • 9. Re: Stale Data until redeploy
                          Gavin King Master

                          If you are saying that you need lazy fetching just to display the search screen, then the solution is to use a persistence context that spans the web request.

                          A Seam-managed persistence context does this by default (unless you start a long-running conversation). This is why we have Seam tx and pc management.