5 Replies Latest reply on Apr 20, 2010 2:14 PM by Adam Warski

    Flash scope depends on the page directory?

    Adam Warski Master


      today I found a very weird problem with the flash scope. I'm using @FlashScoped from Seam3-faces.

      I have a FacesMessages component, a simplified version of the Seam2 component. Its purpose is of course to preserve messages over a redirect. It is flash-scoped, as there are no transient conversations in CDI. And it works fine, unless ... the page a user is redirected to is in a different directory!

      It seems that the flash-scoped components are bound to directories, in which pages reside. If e.g. I'm doing a redirect from /a/b.xhtml to /a/c.xhtml, then the @FlashScoped components survive and the messages are displayed. If I'm doing a redirect from /a/b.xhtml to /a2/b2.xhtml, a new component is created, but then if I go back to any page in the a directory (after any number of steps), I see the messages that should be displayed on the original redirect - so the original component is used.

      Any ideas if this is a problem with JSF or Seam3-faces?

      Code for my FacesMessages:

      import javax.faces.application.FacesMessage;
      import javax.faces.bean.FlashScoped;
      import javax.faces.component.UIComponent;
      import javax.faces.context.FacesContext;
      import java.io.Serializable;
      import java.util.ArrayList;
      import java.util.Iterator;
      import java.util.List;
       * @author Seam2 authors (http://seamframework.org)
       * @author Adam Warski (adam at warski dot org)
      public class FacesMessages implements Serializable {
          private static class MessageData {
              private final String controlId;
              private final FacesMessage fm;
              private MessageData(String controlId, FacesMessage fm) {
                  this.controlId = controlId;
                  this.fm = fm;
              public String getControlId() {
                  return controlId;
              public FacesMessage getFm() {
                  return fm;
          private static final FacesMessage.Severity DEFAULT_SEVERITY = FacesMessage.SEVERITY_INFO;
          private List<MessageData> messages = new ArrayList<MessageData>();
          public void add(String message) {
              add(null, message);
          public void add(String message, FacesMessage.Severity severity) {
              add(null, message, severity);
          public void add(String controlId, String message) {
              add(controlId, message, DEFAULT_SEVERITY);
          public void add(String controlId, String message, FacesMessage.Severity severity) {
              FacesMessage fm = new FacesMessage(severity, message, message);
              messages.add(new MessageData(controlId, fm));
          public void beforeRenderResponse() {
              for (MessageData message : messages) {
                  FacesContext.getCurrentInstance().addMessage(getClientId(message.getControlId()), message.getFm());
          private String getClientId(String id) {
              if (id == null) {
                  return null;
              FacesContext facesContext = FacesContext.getCurrentInstance();
              return getClientId(facesContext.getViewRoot(), id, facesContext);
          private static String getClientId(UIComponent component, String id, FacesContext facesContext) {
              String componentId = component.getId();
              if (componentId != null && componentId.equals(id)) {
                  return component.getClientId(facesContext);
              } else {
                  Iterator iter = component.getFacetsAndChildren();
                  while (iter.hasNext()) {
                      UIComponent child = (UIComponent) iter.next();
                      String clientId = getClientId(child, id, facesContext);
                      if (clientId != null) return clientId;
                  return null;