9 Replies Latest reply on Sep 19, 2008 6:07 AM by baobaotuo

    Lost facesMessage on redirect

    baobaotuo

      I have a page topic.xhtml in which you can submit a commet.


      After you submit a commet ,you will be redirect back to the topic.xhtml.


      But once I submit a comment, FacesMessage Successfully submit the comment was lost.


      Note! There is no long conversation in topic.xhtml.


      Can anyone tell me how to solve this problem ?


      3Q

        • 1. Re: Lost facesMessage on redirect
          baobaotuo

          If redirect to the other page other than topic.xhtml, FacesMessage doesn't get lost.


          WHY?

          • 2. Re: Lost facesMessage on redirect
            vladimir.kovalyuk

            Show your code that performs redirect after queuing FacesMessage to figure out how conversation is propagated and what JSF lifecycle phase is when queuing message.


            The magic why Seam's FacesMessages survives after redirect is explained by the fact it is conversation-scoped component. A conversation (when propagated) survives redirect in post-then-redirect cycle and FacesMessages delegates queued messages to JSF. Probably somehow it does not work as described in your case.
            That's the Leaky Abstraction Law - you need to know how it is implemented in order to make it work.

            • 3. Re: Lost facesMessage on redirect
              baobaotuo
              Below is my code.I don't know How to use iText,so i just submit as plain text

              package com.jeehe.session.home;

              import java.util.Date;

              import javax.faces.application.FacesMessage;

              import org.jboss.seam.annotations.In;
              import org.jboss.seam.annotations.Name;
              import org.jboss.seam.annotations.Transactional;
              import org.jboss.seam.contexts.Contexts;
              import org.jboss.seam.faces.FacesMessages;

              import com.jeehe.dao.MemberCommentDAO;
              import com.jeehe.dao.MemberDAO;
              import com.jeehe.entity.Member;
              import com.jeehe.entity.forum.MemberComment;
              import com.jeehe.framework.EntityHome;
              import com.jeehe.framework.util.JsfHelp;

              @Name("memberCommentHome")
              public class MemberCommentHome extends EntityHome<MemberComment, MemberCommentDAO>{

                   private static final long serialVersionUID = -1844900808241983143L;
                   
                   Long memberCommentId;
                   
                   Member member;
                   
                   @In
                   MemberDAO memberDAO;
                   
                   @Override
                   public Object getId() {
                        if (memberCommentId == null) {
                             return super.getId();
                        } else {
                             return memberCommentId;
                        }
                   }
                   
                   @Transactional
                   public String persist() {
                        if(instance.getContent()==null || instance.getContent().trim().length()<=0){
                             FacesMessages.instance().add(new FacesMessage(FacesMessage.SEVERITY_ERROR,"","comment cannot be empty"));
                             return "failed";
                        }
                        Member currentMember = (Member) Contexts.getSessionContext().get(Member.sessionName);
                        if(currentMember == null)
                             return "failed";
                        Date date = new Date();
                        instance.setCreateTime(date);
                        instance.setLastUpdateTime(date);
                        currentMember = memberDAO.find(currentMember.getId());
                        instance.setCreator(currentMember);
                        member = memberDAO.find(Long.valueOf(JsfHelp.getRequestParameter("memberId")));
                        member.getComments().add(instance);
                        memberDAO.persist(member);
                        instance.setMember(member);
                        getEntityDAO().persist(instance);
                        FacesMessages.instance().add(new FacesMessage(FacesMessage.SEVERITY_INFO,"","success."));
                        return "persistMemberComment";
                   }
                   
                   @Transactional
                   public String update(){
                        getEntityDAO().persist(instance);
                        return "update";
                   }

                   public Long getMemberCommentId() {
                        return memberCommentId;
                   }

                   public void setMemberCommentId(Long memberCommentId) {
                        this.memberCommentId = memberCommentId;
                   }

                   public Member getMember() {
                        return member;
                   }

                   public void setMember(Member member) {
                        this.member = member;
                   }
              }

              As you can see,after successfully persisted a comment, the "success." message should seen.
              And There is no Long conversation here.

              FacesMessages.instance().add(new FacesMessage(FacesMessage.SEVERITY_INFO,"","success."));
              return "persistMemberComment";
              • 4. Re: Lost facesMessage on redirect
                baobaotuo
                Below is the relevant code in my pages.xml.

                <page view-id="/member/home.xhtml" login-required="true">
                          <param name="memberId" value="#{memberHome.memberId}"/>
                          <navigation>
                            <rule if-outcome="persistMemberComment">
                                <redirect view-id="/member/home.xhtml">
                                     <param name="memberId" value="#{memberCommentHome.member.id}"/>
                                </redirect>
                            </rule>
                        </navigation>
                </page>

                in the case , no facesMassage show up when I successfully persist one comment.

                • 5. Re: Lost facesMessage on redirect
                  baobaotuo
                  And I change the code for test.

                  <page view-id="/member/home.xhtml" login-required="true">
                            <param name="memberId" value="#{memberHome.memberId}"/>
                            <navigation>
                              <rule if-outcome="persistMemberComment">
                                  <redirect view-id="/error.xhtml">
                                       <param name="memberId" value="#{memberCommentHome.member.id}"/>
                                  </redirect>
                              </rule>
                          </navigation>
                  </page>

                  Then the facesMessage "success." show up.

                  It is just a test.it show that facesMessage get lost when redirected to the former page,but survived when redirected to another page.
                  • 6. Re: Lost facesMessage on redirect
                    baobaotuo
                    I have debuged with seam code.

                    @Scope(ScopeType.CONVERSATION)
                    @Name("org.jboss.seam.faces.facesMessages")
                    @Install(precedence=BUILT_IN, classDependencies="javax.faces.context.FacesContext")
                    @BypassInterceptors
                    public class FacesMessages implements Serializable

                       public void beforeRenderResponse() //called after redirect
                       {
                          for (Message message: facesMessages)
                          {
                             FacesContext.getCurrentInstance().addMessage( null,message.toFacesMessage() );
                          }
                          for ( Map.Entry<String, List<Message>> entry: keyedFacesMessages.entrySet() )
                          {
                             for ( Message msg: entry.getValue() )
                             {
                                FacesContext.getCurrentInstance().addMessage( entry.getKey(), msg.toFacesMessage() );
                             }
                          }
                          clear();
                       }

                       public void add(FacesMessage facesMessage) //add message to the FacesMessages
                       {
                          if (facesMessage!=null)
                          {
                             facesMessages.add( new Message(facesMessage) );
                          }
                       }

                    Above are the two method called which is the most directly related to this issue.

                    I seams that when redirect to another page,the "public void add(FacesMessage facesMessage) " method taht used to add facesMessage and later "public void beforeRenderResponse() " which is called after redirect reference to the same FacesMessage instance.

                    when redirect to seam page,the "public void add(FacesMessage facesMessage) " method and later "public void beforeRenderResponse() " which is called after redirect reference to the different FacesMessage instance.

                    So I find out that there is something wrong when "public static FacesMessages instance()" is called after redirect.
                    It refer to the different FacesMessage instance when redirect to the same page.
                    • 7. Re: Lost facesMessage on redirect
                      baobaotuo
                      For now I change the "public static FacesMessages instance()" method  in FacesMessages.java to

                         public static FacesMessages instance()
                         {
                            if ( !Contexts.isConversationContextActive() )
                            {
                               throw new IllegalStateException("No active conversation context");
                            }
                           
                            //return (FacesMessages) Component.getInstance(FacesMessages.class, ScopeType.CONVERSATION);//omit this to avoid the problem, it is so hard to trace
                                                                                                                        //into the "Component.getInstance" to see what cause this problem
                           
                            if(Contexts.getSessionContext().get("facesMessages")==null){
                                FacesMessages facesMessages = (FacesMessages) Component.getInstance(FacesMessages.class, ScopeType.CONVERSATION);
                                Contexts.getSessionContext().set("facesMessages", facesMessages);                     //Save the facesMessaage directly in seesion to bypass this problem
                            }
                            return (FacesMessages) Contexts.getSessionContext().get("facesMessages");
                         }
                      • 8. Re: Lost facesMessage on redirect
                        baobaotuo

                        Should I file a jira for this?


                        I hope that the seam team can help me to solve this problem.


                        thanks ,Vladimir Kovalyuk!

                        • 9. Re: Lost facesMessage on redirect
                          baobaotuo