7 Replies Latest reply on Feb 3, 2008 5:44 PM by pmuir

    Force method to be run before page redirect (no pages.xml!)

    w17chm4n

      Hi again ;)

      I have another problem with seam. Is there a way to force seam to run some method before it redirects to the page ? And is it possible that seam is cache`ing lists used as datamodels ?

      If you are a bit confussed, let me explain.

      Here I have my view

      <h:dataTable styleClass="dataTable" columnClasses="categoryName" var="question" value="#{cat.questionList}">
       <h:column>
       <h:outputText value="#{question.questionText}"/>
       </h:column>
       <h:column>
       <h:commandButton type="button" image="./images/tbl_ico_del.png" style="border: none" action="#{QuestionController.removeQuestion(question)}"/>
       </h:column>
       </h:dataTable>
      


      As U can see it uses questionCategoryList generated by the bean below.

      @Stateless
      @Name("QuestionCategoryController")
      public class QuestionCategoryControllerBean implements QuestionCategoryController {
      
       @Logger
       private Log log;
      
       @In(create = true)
       private QuestionCategoryManager questionCategoryManager;
      
       @In(create = true)
       private QuestionCategory questionCategory;
      
       @DataModel
       private List<QuestionCategory> questionCategoryList;
      
       @In(required = true)
       private FieldValidator fieldValidator;
      
       public void addCategory() {
       if(fieldValidator.validate(questionCategory,"addCategoryForm","categoryName")) {
       questionCategoryManager.addCategory(this.questionCategory);
       this.questionCategory = null;
       this.questionCategoryList = null;
       }
       }
      
       @SuppressWarnings("unchecked")
       public void removeSelectedCategories() {
       QuestionCategory qc;
       Iterator it = questionCategoryList.iterator();
      
       while(it.hasNext()) {
       qc = (QuestionCategory) it.next();
      
       if(qc.isSelected()) {
       questionCategoryManager.removeCategory(qc);
       }
       }
      
       this.questionCategoryList = null;
       }
      
       public void removeCategory(QuestionCategory questionCategory) {
       questionCategoryManager.removeCategory(questionCategory);
       this.questionCategory = null;
       this.questionCategoryList = null;
       }
      
       public QuestionCategory getQuestionCategory() {
       return questionCategory;
       }
      
       public void setQuestionCategory(QuestionCategory questionCategory) {
       this.questionCategory = questionCategory;
       }
      
       @Factory("questionCategoryList")
       public void createQuestionCategoryList() {
       this.questionCategoryList = this.questionCategoryManager.getAllQuestionCategories();
       }
      
       @Remove
       public void destroy() {
       }
      }
      


      Well the view works, and it renders ok, but the problem is when I want to remove a question from the category by running #{QuestionController.removeQuestion(question)} from the view.

      The question is removed from the database, but when the page reloads, it`s still in the list !

      I`m removing question by using another bean
      @Stateless
      @Name("questionManager")
      public class QuestionManagerBean implements QuestionManager {
      
       @Logger
       Log log;
      
       @In
       private EntityManager entityManager;
      
       public void addQuestion(Question question) {
       question.setCreated(new Date());
       entityManager.persist(question);
       log.info("Question successfully persisted. [" + question.getQuestionText() + "]");
       }
      
       public void removeQuestion(Question question) {
       log.info("Removing question [" + question.getQuestionText() + "]");
       entityManager.flush();
       entityManager.remove(entityManager.merge(question));
       }
      
       public Question getQuestion(Question question) {
       return null;
       }
      
       @SuppressWarnings("unchecked")
       public List<Question> getAllQuestions() {
       return entityManager.createQuery("from Question q").getResultList();
       }
      
       @Remove
       public void destroy() {}
      
      }
      


      After putting some breakepoints and running this metod from view I found this:
      17:04:36,893 INFO [QuestionCategoryManagerBean] Reciving QuestionCategory list
      17:04:37,494 INFO [QuestionManagerBean] Removing question [hdfghdfghf]
      


      As far as I`m concerned, as the questionCategoryList is generated by a stateless bean, the list has to be recived from the database everytime my code recals to it. So as I want to remove question from some category, seam needs to get current list from the database, then lazy-fetch the question, inject it to the metod, and pass to the removeQuestion method in the questionManagerBean. It`s allright, but why Seam isn`t refreshing the list after the question is removed ? I mean that even though question is removed form the database, the list rendered as dataModel on view by dataTable, just after reloading the page, the question is still on the list. But what is strange, when I hit reload on my browser (F5 or sth) the list is recived from the database once again and rendered view is correct, without removed question !

      I`ve tryed a couple of my ideas (including <action execute="refresh_this_stupid_list> setted in the view section in pages.xml) to fix this crap, even something like this
      @In(value="#{questionCategoryList}")
      private ListDataModel tmp;
      .
      .
      .
      public void removeQuestion(Question question) {
       if(question.getQuestionType().getId().equals(questionTypeManager.getQuestionTypeByName(propertiesManager.get("questiontype.input")).getId())) {
       questionManager.removeQuestion(question);
       } else {
       answerManager.removeAnswers(question.getAnswers());
       questionManager.removeQuestion(question);
       }
       tmp.setWrappedData(questionCategoryManager.getAllQuestionCategories());
       }
      


      But even though that in logs it looked allright
      17:04:36,893 INFO [QuestionCategoryManagerBean] Reciving QuestionCategory list
      17:04:37,494 INFO [QuestionManagerBean] Removing question [hdfghdfghf]
      17:04:37,516 INFO [QuestionCategoryManagerBean] Reciving QuestionCategory list
      


      The list rendered on the view, wasn`t refreshed and contained removed question.

      Any idea how to work this thing out ?

        • 1. Re: Force method to be run before page redirect (no pages.xm
          jteb

          I guess you could use an Interceptor on the action-method.

          • 2. Re: Force method to be run before page redirect (no pages.xm
            jteb

            It's been a while, but from the top of my head:

            @Target(TYPE)
            @Retention(RUNTIME)
            @Interceptors(QuestionRemovedInterceptor.class)
            public @interface QuestionRemoved {}
            
            @Interceptor
            public class QuestionRemovedInterceptor {
            
             @AroundInvoke
             public aroundInvoke(SecurityContext ctx) {
            
             // your code
             return ctx.proceed();
             }
            }
            


            Check section 5 of the manual

            • 3. Re: Force method to be run before page redirect (no pages.xm
              jteb

              sorry InvocationContext

              • 4. Re: Force method to be run before page redirect (no pages.xm
                w17chm4n

                Using interceptor didn`t help :|

                @Interceptor
                public class QuestionRemovedInterceptor {
                
                 @AroundInvoke
                 public Object aroundInvoke(InvocationContext invocation) throws Exception {
                 Contexts.removeFromAllContexts("questionCategoryList");
                 return invocation.proceed();
                 }
                }
                


                @Target(ElementType.TYPE)
                @Retention(RetentionPolicy.RUNTIME)
                @Interceptors(QuestionRemovedInterceptor.class)
                public @interface QuestionRemoved {}
                


                Logs look almost allright (doubled reciving questionCategoryList, but this is because the questionCategoryController is stateless)

                09:00:15,046 INFO [QuestionCategoryManagerBean] Reciving QuestionCategory list
                09:00:15,118 INFO [QuestionCategoryManagerBean] Reciving QuestionCategory list
                09:00:15,312 INFO [QuestionManagerBean] Removing question [afgdfgsdfg]
                09:00:15,362 INFO [QuestionCategoryManagerBean] Reciving QuestionCategory list
                09:00:15,429 INFO [QuestionCategoryManagerBean] Reciving QuestionCategory list
                


                I`ve also tryed to change annotation type to method

                @Target(ElementType.METHOD)
                @Retention(RetentionPolicy.RUNTIME)
                @Interceptors(QuestionRemovedInterceptor.class)
                public @interface QuestionRemoved {}
                


                and than use it on removeQuestion

                @QuestionRemoved
                 public void removeQuestion(Question question) {
                 if(question.getQuestionType().getId().equals(questionTypeManager.getQuestionTypeByName(propertiesManager.get("questiontype.input")).getId())) {
                 questionManager.removeQuestion(question);
                 } else {
                 answerManager.removeAnswers(question.getAnswers());
                 questionManager.removeQuestion(question);
                 }
                 }
                


                But that didn`t work either. Any other ideas?

                • 5. Re: Force method to be run before page redirect (no pages.xm
                  pmuir

                  Where do you outject the list you use for the dataModel - #{cat.questionList}

                  • 6. Re: Force method to be run before page redirect (no pages.xm
                    w17chm4n

                    Nowhere, it`s lazy fatched from the database.

                    • 7. Re: Force method to be run before page redirect (no pages.xm
                      pmuir

                      Ok, what I meant was post the bean for #{cat}