Agregar un mensaje de caras a la página redirigida utilizando ExternalContext.redirect ()

Estoy usando ExternalContext.redirect (String); método para redirigir al usuario a otra página:

FacesContext.getCurrentInstance().addMessage(new FacesMessage("Bla bla bla...")); FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true); ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); ec.redirect(ec.getRequestContextPath() + "/scenario.xhtml"); 

Como mencionó Matt Handy en su respuesta, utilicé Flash.setKeepMessages (true); pero no parece funcionar con ExternalContext.redirect. (Aunque funciona cuando redirecciono devolviendo un nombre de página del método de acción de bean).

Ahora, ¿cómo puedo agregar FacesMessage para que esté visible en la página redireccionada (scenario.xhtml)?

Esto parece ser un problema de tiempo. Este método de escucha se invoca durante el evento preRenderView . De acuerdo con el código fuente de ELFlash (la implementación de Flash de Mojarra devuelta por ExternalContext#getFlash() ) resulta que no configurará la cookie flash cuando usted está actualmente sentado en la fase de respuesta de renderizado y la cookie flash no tiene establecido aún para la solicitud actual:

Estas son las líneas relevantes de ELFlash :

 if (currentPhase.getOrdinal() < PhaseId.RENDER_RESPONSE.getOrdinal()) { flashInfo = flashManager.getPreviousRequestFlashInfo(); } else { flashInfo = flashManager.getNextRequestFlashInfo(this, true); maybeWriteCookie(context, flashManager); } 

El maybeWriteCookie solo establecería la cookie cuando la cookie flash deba pasarse por segunda vez (es decir, cuando la página redireccionada a su vez redirija a otra página).

Este es un desafortunado caso de esquina. Esta lógica ELFlash tiene sentido, pero esto no es lo que realmente quieres. Básicamente , debe agregar el mensaje durante la fase INVOKE_APPLICATION . Sin embargo, no existe tal evento como postInvokeAction . Con la nueva etiqueta JSF 2.2 debería ser posible ya que realmente se ejecuta durante la fase de invocación de la aplicación.

  

Siempre y cuando no estés en JSF 2.2, tendrás que buscar formas alternativas. La manera más fácil sería crear un ComponentSystemEvent personalizado.

 @NamedEvent(shortName="postInvokeAction") public class PostInvokeActionEvent extends ComponentSystemEvent { public PostInvokeActionEvent(UIComponent component) { super(component); } } 

Ahora necesitas un gancho para publicar este evento. El lugar más sensato es un PhaseListener escuchando después de la fase de INVOKE_APPLICATION .

 public class PostInvokeActionListener implements PhaseListener { @Override public PhaseId getPhaseId() { return PhaseId.INVOKE_APPLICATION; } @Override public void beforePhase(PhaseEvent event) { // NOOP. } @Override public void afterPhase(PhaseEvent event) { FacesContext context = FacesContext.getCurrentInstance(); context.getApplication().publishEvent(context, PostInvokeActionEvent.class, context.getViewRoot()); } } 

Si lo registra de la siguiente manera en faces-config.xml

  com.example.PostInvokeActionListener  

entonces podrás usar el nuevo evento de la siguiente manera

  

Actualice esto también está disponible en la biblioteca de utilidades JSF OmniFaces , por lo que no necesita crear home run uno y otro. Consulte también el ejemplo de presentación de InvokeActionEventListener .

Use el flash para guardar los mensajes durante una redirección.

Agregue estas dos líneas a su código antes de redirigir:

 FacesContext context = FacesContext.getCurrentInstance(); context.getExternalContext().getFlash().setKeepMessages(true); 

Tenga en cuenta que hay algunos problemas con la implementación del scope de flash de Mojarra . Tenga esto en cuenta si lo usa.