tipos - Cómo reemplazar @ManagedBean/@ViewScope por CDI en JSF 2.0/2.1
view scope jsf (5)
Creo que puede beneficiarse de la extensión CDI para crear su propio ámbito de manera que pueda implementar el contexto y usar @NormalScope
.
- CDI
AfterBeanDiscovery
un eventoAfterBeanDiscovery
después de cada llamada de bean - Puede usar la extensión CDI para
@Observes
este evento y agregar su implementación de contexto - En su implementación de alcance puede:
- Use
Contextual
para obtener su bean por su nombre deFacesContext
ViewRoot
Map
y devuélvalo después de cada llamada ajax - Use
CreationalContext
si no se encuentra el nombre del bean desde el primer paso para crearlo en elMap
FacesContext
ViewRoot
- Use
Para una explicación más detallada, recomiendo este enlace: http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/
Actualmente estoy evaluando Java EE 6 / JSF 2.1 con RichFaces.
Un frijol que se declara como
@ManagedBean
@ViewScoped
- Obtiene un conjunto de ID (para preparar, por ejemplo, una operación de eliminación).
- A través de JSF se muestra una ventana emergente de confirmación.
- Si el usuario confirma, el método de eliminación se invoca y elimina la fila para la que se almacenó la ID en el paso 1.
Como los beans CDI no tienen un ViewScope, intenté declarar el bean como:
@Named
@ConversationScoped
Ahora, el procesamiento falla en el paso 3. porque el valor que se estableció en el paso 1 (verificó que) ya no está disponible.
¿Tengo que usar los métodos Conversation.begin()
y Conversation.end()
?
Si es así, ¿dónde sería un buen lugar para invocarlos?
Hay un proyecto que tiene una extensión de las características de la pila de Java EE: DeltaSpike . Es una consolidación de Seam 3, Apache CODI. Por encima de otros, incluye el @ViewScoped en CDI. Este es un artículo antiguo y ya ha alcanzado la versión 1.3.0.
Inyecte la conversación en su bean y en el método @PostConstructor
inicie la conversación si la conversación es transitoria.
Y después de eliminar el registro, finalice su conversación y navegue a la página de destino. Al comenzar una conversación. Aquí hay un ejemplo
public class BaseWebBean implements Serializable {
private final static Logger logger = LoggerFactory.getLogger(BaseWebBean.class);
@Inject
protected Conversation conversation;
@PostConstruct
protected void initBean(){
}
public void continueOrInitConversation() {
if (conversation.isTransient()) {
conversation.begin();
logger.trace("conversation with id {} has started by {}.", conversation.getId(), getClass().getName());
}
}
public void endConversationIfContinuing() {
if (!conversation.isTransient()) {
logger.trace("conversation with id {} has ended by {}.", conversation.getId(), getClass().getName());
conversation.end();
}
}
}
@ConversationScoped
@Named
public class yourBean extends BaseWebBean implements Serializable {
@PostConstruct
public void initBean() {
super.initBean();
continueOrInitConversation();
}
public String deleteRow(Row row)
{
/*delete your row here*/
endConversationIfContinuing();
return "yourDestinationPageAfter removal";
}
}
Puedes usar:
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
@Named
@ViewScoped
public class PageController implements Serializable {
private String value;
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void execute() {
setValue("value");
}
@PostConstruct
public void init() {
System.out.println("postcontructor");
}
}
Si puedes actualizar a JSF 2.2, hazlo inmediatamente. Ofrece una anotación nativa de @ViewScoped
para CDI.
import javax.faces.view.ViewScoped;
import javax.inject.Named;
@Named
@ViewScoped
public class Bean implements Serializable {
// ...
}
Alternativamente, instale OmniFaces que trae su propio @ViewScoped
compatible con CDI, incluyendo un @PreDestroy
funcionamiento (que está roto en JSF @ViewScoped
).
import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;
@Named
@ViewScoped
public class Bean implements Serializable {
// ...
}
Otra alternativa es instalar MyFaces CODI que puentea de forma transparente JSF 2.0 / 2.1 @ViewScoped
to CDI. Esto solo agrega un parámetro de solicitud autogenerado a la URL (como haría @ConversationScoped
).
import javax.faces.bean.ViewScoped;
import javax.inject.Named;
@Named
@ViewScoped
public class Bean implements Serializable {
// ...
}
Si realmente necesita usar @ConversationScoped
, entonces realmente necesita comenzar y finalizarlo. Necesita @Inject
una Conversation
e invocar begin()
en @PostConstruct
y end()
en el último paso de la conversación, generalmente un método de acción que redirige a una nueva vista.
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;
@Named
@ConversationScoped
public class Bean implements Serializable {
@Inject
private Conversation conversation;
// ...
@PostConstruct
public void init() {
conversation.begin();
}
public String submit() {
// ...
conversation.end();
return "some.xhtml?faces-redirect=true";
}
}