¿Cómo funciona JSF 2 ConversationScope?
jsf-2 seam-conversation (1)
Tengo una página de facetas JSF que muestra una tabla de datos según la página que están viendo. Cuando muestro la página 1, llamo al método de acción view()
para obtener los datos de la base de datos de ambas páginas y almacenarlos como un campo miembro privado del bean (dos matrices). También llamo a conversation.start()
en la instancia de conversación inyectada en el método view()
.
Cuando el usuario hace clic en el botón "siguiente" ( h:commandButton
) para ir a la página 2, estoy ejecutando un método next()
para actualizar el bean de respaldo para que apunte a la matriz 2 para que imprima su contenido. El problema es que la matriz 2 ya no existe. No sé por qué estoy perdiendo el alcance de la conversación. ¿Algunas ideas?
//tells the object which page we are on, and thus what data to display.
private int part = 1;
// These arrays are filled with data but conversation scope doesn''t
// keep them on the next postback.
private int[] part1 = new int[15], part2 = new int[15];
Debes pegar un poco más de código para que podamos ayudarte mejor. Por lo que dice, no puedo ver dónde llamó al método para finalizar la conversación (también lo necesita cuando trabaja con el alcance de la conversación).
Pegaré aquí un pequeño ejemplo que creo que te ayudará a comprender cómo funciona el alcance de la conversación:
Esta es la página de inicio de un asistente (el alcance de la conversación es ideal para los asistentes)
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>ConversationScoped demo CDI(Component Dependency
Injection)</title>
</h:head>
<h:body>
<h3>ConversationScoped demo CDI(Component Dependency Injection)</h3>
<p>A conversation scope provides persistence until a goal is
reached<br />
In this example the first entered value will remain until the end
method is called<br />
in some page.<br />
This is a really useful gadget, for making registration wizards and
similar tools...</p>
<h:form>
<h:outputText value="Type something" />
<h:inputText value="#{ supportBB.someValue}" />
<h:commandButton value="continue" action="#{ supportBB.onClick}" />
</h:form>
</h:body>
</html>
Esta es la segunda página del asistente.
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>ConversationScoped demo CDI(Component Dependency
Injection)</title>
</h:head>
<h:body>
<h3>This is the next page(The value is saved in the conversation)</h3>
<h4><h:outputText value="#{ supportBB.someValue}"/></h4>
<h:form>
<h:commandButton value="Finish conversation" action="#{ supportBB.onKeepGoing}"/>
</h:form>
</h:body>
</html>
Y esta es la página donde termina el alcance.
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>ConversationScoped demo CDI(Component Dependency
Injection)</title>
</h:head>
<h:body>
<h3>This is the last page.The value still saved in conversation(until the end() method is called)</h3>
<h4><h:outputText value="#{ supportBB.someValue}" /></h4>
<h:form>
<h:outputText
value="Click finish to end the conversation(So saved values are disposed)" />
<h:commandButton value="Finish" action="#{ supportBB.onFinish}" />
</h:form>
</h:body>
</html>
Aquí el bean de respaldo @ConversationScoped que inicia y finaliza la conversación.
package backingbeans;
import java.io.Serializable;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named()
@ConversationScoped()
public class SupportBB implements Serializable {
private static final long serialVersionUID = 1L;
private String someValue;
@Inject
private Conversation conversation;
// Control start and end of conversation
public void start() {
conversation.begin();
}
public void end() {
conversation.end();
}
// Navigation
public String onClick() {
if(someValue.equals("") || conversation == null) {
return "";//Dont go anywhere if the there was no input the field
}
start();
return "nextpage?faces-redirect=true";
}
public String onKeepGoing() {
return "finish?faces-redirect=true";
}
public String onFinish() {
end();// If triggered when there is no conversation(i.e URL Navigation)
// there will be an exception
return "index?faces-redirect=true";
}
// Getters & Setters
public String getSomeValue() {
return someValue;
}
public void setSomeValue(String someValue) {
this.someValue = someValue;
}
}
Creo que este ejemplo es muy simple y puede ayudarte a entender cómo funciona. Pregunta si no entiendes algo
NOTA:
Creo que pero no estoy seguro al 100%, pero ConversationScope solo funciona si el bean de respaldo es un bean CDI. Este medio utiliza la anotación @Named. Será mejor que revise eso.