2 Replies Latest reply on Jan 5, 2011 10:33 AM by kernstock

    CDI @Conversation plus NavigationHandler().handleNavigation()

    kernstock

      Hi,


      I have a problem with the propagation of a long runnig conversation when I redirect the view by the handleNavigation() method. Here is my test code:


      I have a conversationscoped bean and two views:


      conversationStart.xhtml is called in Browser with URL 


      http://localhost/tests/conversationStart.jsf?paramTestId=ParameterInUrl



      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
         <html xmlns="http://www.w3.org/1999/xhtml"
               xmlns:h="http://java.sun.com/jsf/html"
               xmlns:f="http://java.sun.com/jsf/core">
             
         <f:metadata>
             <f:viewParam name="paramTestId" value="#{conversationTest.fieldTestId}" />
             <f:event type="preRenderView" listener="#{conversationTest.preRenderView}" />
         </f:metadata>
         <h:head>
           <title>Conversation Test</title>
         </h:head>
         <h:body>
           <h:form>
             <h2>Startpage Test Conversation with Redirect</h2>
             <h:messages />
             <h:outputText value="Testparameter: #{conversationTest.fieldTestId}"/><br />
             <h:outputText value="Logged In: #{conversationTest.loggedIn}"/><br />
             <h:outputText value="Conversation ID: #{conversationTest.convID}"/><br />
             <h:outputText value="Conversation Transient: #{conversationTest.convTransient}"/><br />
             <h:commandButton action="#{conversationTest.startLogin}" value="Login ->" rendered="#{conversationTest.loggedIn==false}" /><br />
             <h:commandLink action="/tests/conversationLogin.xhtml?faces-redirect=true" value="Login ->" rendered="#{conversationTest.loggedIn==false}" /><br />
           </h:form>
           <h:link outcome="/tests/conversationLogin.xhtml" value="Login Link" rendered="#{conversationTest.loggedIn==false}">
                <f:param name="cid" value="#{conversationTest.convID}"></f:param>
           </h:link>
         </h:body>
      </html>
      



      The Parameter is written to the beanfield and displayed in the view correctly. There are 3 different possibilites to navigate to the next View. All 3 work fine. The beanfield shows up the next view (conversationLogin.xhtml) too:


      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
         <html xmlns="http://www.w3.org/1999/xhtml"
               xmlns:h="http://java.sun.com/jsf/html"
               xmlns:f="http://java.sun.com/jsf/core">
       
         <h:head>
           <title>Conversation Test</title>
         </h:head>
         <h:body>
           <h:form>
             <h2>Loginpage Test Conversation with Redirect</h2>
             <h:messages />
             <h:outputText value="Testparameter: #{conversationTest.fieldTestId}"/><br />
             <h:outputText value="Logged In: #{conversationTest.loggedIn}"/><br />
             <h:outputText value="Conversation ID: #{conversationTest.convID}"/><br />
             <h:outputText value="Conversation Transient: #{conversationTest.convTransient}"/><br />
             <h:commandButton action="#{conversationTest.login}" value="Login And Return" /><br />
           </h:form>
         </h:body>
      </html>




      When I return to the Startpage by clicking the button the conversation bean still contains all values. So everything is fine. Here is the bean:


      package test;
      
      import java.io.Serializable;
      
      import javax.annotation.PostConstruct;
      import javax.enterprise.context.Conversation;
      import javax.enterprise.context.ConversationScoped;
      import javax.faces.event.ComponentSystemEvent;
      import javax.inject.Inject;
      import javax.inject.Named;
      
      @Named
      @ConversationScoped
      public class ConversationTest implements Serializable{
      
           private static final long serialVersionUID = 1L;
      
           final String CONVERSATION_NAME="longRun";
           
           @Inject Conversation conversation;
           
           private boolean loggedIn;
           private String fieldTestId;
      
           @PostConstruct
           public void init(){
                if(conversation.isTransient()){
                     conversation.begin(CONVERSATION_NAME);
                     System.out.println("New Conversation started");
                }
                loggedIn=false;
           }
           
           public String getConvID(){
                return conversation.getId();
           }
           public boolean isConvTransient(){
                return conversation.isTransient();
           }
           
           public boolean getLoggedIn(){
                return loggedIn;
           }
           
           public String startLogin(){
                return "/tests/conversationLogin.xhtml?faces-redirect=true";
           }
           
           public String login(){
                loggedIn=true;
                return "/tests/conversationStart.xhtml?faces-redirect=true";
           }
           
           public void preRenderView(ComponentSystemEvent ev) {
      //          if(!loggedIn){
      //               System.out.println("Will redirect to Login");
      //               FacesContext ctx = FacesContext.getCurrentInstance();
      //               ctx.getApplication().getNavigationHandler().handleNavigation(ctx, null, "/tests/conversationLogin.xhtml?faces-redirect=true");
      //            ctx.renderResponse();
      //          }
           }
      
           public void setFieldTestId(String fieldTestId) {
                System.out.println("fieldTestID was set to: "+fieldTestId);
                this.fieldTestId = fieldTestId;
           }
      
           public String getFieldTestId() {
                return fieldTestId;
           }
      
      }



      Now comes the problem !!


      As soon as I try to redirect the page in the preRenderView method of the bean (just uncomment the code in the method), using handleNavigation() the bean is created again in the next view instead of using the allready created instance. Although the cid parameter is propagated to the next view !


      Has anybody an idea what's wrong ?


      best regards
      Thomas



        • 1. Re: CDI @Conversation plus NavigationHandler().handleNavigation()
          nickarls

          Is the conversation transient or non-transient at the beginning of the preRenderView?

          • 2. Re: CDI @Conversation plus NavigationHandler().handleNavigation()
            kernstock

            It's non-transient. I have an phase- and parameterlistener active. Here is the log:




            INFO: Before phase: RESTORE_VIEW 1
            INFO: After phase: RESTORE_VIEW 1
            INFO: Before phase: APPLY_REQUEST_VALUES 2
            INFO: Parameter: paramTestId = ParameterInUrl
            INFO: After phase: APPLY_REQUEST_VALUES 2
            INFO: Before phase: PROCESS_VALIDATIONS 3
            INFO: New Conversation started
            INFO: After phase: PROCESS_VALIDATIONS 3
            INFO: Before phase: UPDATE_MODEL_VALUES 4
            INFO: fieldTestID was set to: ParameterInUrl
            INFO: After phase: UPDATE_MODEL_VALUES 4
            INFO: Before phase: INVOKE_APPLICATION 5
            INFO: After phase: INVOKE_APPLICATION 5
            INFO: Before phase: RENDER_RESPONSE 6
            
            INFO: START: preRenderView **
            INFO: conversation id: longRun
            INFO: conversation isTransient: false
            INFO: fieldTestID : ParameterInUrl
            INFO: Will redirect to Login
            
            INFO: After phase: RENDER_RESPONSE 6
            
            INFO: Before phase: RESTORE_VIEW 1
            INFO: After phase: RESTORE_VIEW 1
            INFO: Before phase: RENDER_RESPONSE 6
            INFO: After phase: RENDER_RESPONSE 6