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