I recently ran into a rather common issue with using SWF: messages are not preserved across a top-level flow redirect. I didn't find any good solutions here (or was I just not looking hard enough), so I came up with something which solves the problem, and thought I'd share it with anyone interested.
MessagePreserver is a FlowExecutionListener overriding the sessionEnding() and sessionStarting() methods. It's looking for an attribute in the end-state called PRESERVE_MESSAGES. If it finds it, it saves the message snapshot to session scope under PRESERVED_FLOW_MESSAGES. In sessionStarting(), if it finds the snapshot in session scope, it restores the messages.
To use this, you'll need to add the bean to your webflow config file and add it as a flow execution listener. Whenever you need to preserve across a redirect, add the PRESERVE_MESSAGES attribute to the end-state. Here's the code:
Code:// Use your own package! import java.io.Serializable; import org.springframework.binding.message.DefaultMessageContext; import org.springframework.webflow.core.collection.MutableAttributeMap; import org.springframework.webflow.execution.FlowExecutionListenerAdapter; import org.springframework.webflow.execution.FlowSession; import org.springframework.webflow.execution.RequestContext; public class MessagePreserver extends FlowExecutionListenerAdapter { public static final String PRESERVE_MESSAGES = "PRESERVE_MESSAGES"; private static final String PRESERVED_FLOW_MESSAGES = "PRESERVED_FLOW_MESSAGES"; public void sessionStarting(RequestContext requestContext, FlowSession flowSession, MutableAttributeMap attributeMap) { Serializable preservedMessages = (Serializable) requestContext.getExternalContext().getSessionMap().get(PRESERVED_FLOW_MESSAGES); if (preservedMessages != null) { DefaultMessageContext currentMessageContext = (DefaultMessageContext) requestContext.getMessageContext(); currentMessageContext.restoreMessages(preservedMessages); requestContext.getExternalContext().getSessionMap().remove(PRESERVED_FLOW_MESSAGES); } } public void sessionEnding(RequestContext requestContext, FlowSession flowSession, String string, MutableAttributeMap attributeMap) { if (requestContext.getCurrentState().getAttributes().contains(PRESERVE_MESSAGES)) { Serializable messageSnapshot = ((DefaultMessageContext) requestContext.getMessageContext()).createMessagesMemento(); requestContext.getExternalContext().getSessionMap(). put(PRESERVED_FLOW_MESSAGES, messageSnapshot); } } }


), so I came up with something which solves the problem, and thought I'd share it with anyone interested.
Reply With Quote
