CDI @Conversation not propagated with handleNavigation()
- by Thomas Kernstock
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