6

I have a problem with the propagation of a long running 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 possibilities 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 already created instance. Although the cid parameter is propagated to the next view !

Has anybody an idea what's wrong ?

best regards Thomas

Apostolos
  • 10,033
  • 5
  • 24
  • 39
  • Hi, Im not use to use the conversation scope I rather use the view scope but if you are trying to pass values from one view to another I recommend you to use: get_parameter_value #{actualbean.value} in the transition in the faces config file. – IturPablo Apr 09 '12 at 23:09
  • Are you getting any exceptions in your server log? I've seen problems with conversation state when trying to establish the conversation in the initial request, when the session is also being established. Check out [IllegalStateException: Cannot create a session after the response has been committed](http://stackoverflow.com/a/8072445/244191) and see if anything in there helps you. – Brian Jun 06 '12 at 13:19
  • 1
    Have you tried adding the CID directly to the URL? "/tests/conversationLogin.xhtml?faces-redirect=true&cid="+getConvID() – Yamada Jan 28 '14 at 16:04

0 Answers0