Flash scope depends on the page directory?
adamw Apr 7, 2010 11:14 AMHello,
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) */ @FlashScoped 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; } } }
Adam