Here's another possible solution, which does not involve redirection or JS.
This one is a bit more general, since it will return the last valid FlowExecution for any invalid state id (in the same conversation, ofc). You may change this if you want, but it currently suits my needs.
Here are teh codez :P
Modified FlowExecutionRepository:
Code:
public class CtqFlowExecutionRepository extends DefaultFlowExecutionRepository {
private Log log = LogFactory.getLog(CtqFlowExecutionRepository.class);
private final static String LAST_VALID_STATE_KEY = "CtqFlowExecutionRepository_LAST_VALID_STATE_KEY";
public CtqFlowExecutionRepository(DefaultFlowExecutionRepository lParent) {
super(lParent.getConversationManager(), lParent.getSnapshotFactory());
}
/* (non-Javadoc)
* @see org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository#getFlowExecution(org.springframework.webflow.execution.FlowExecutionKey)
*/
@Override
public FlowExecution getFlowExecution(FlowExecutionKey pKey) {
log.trace("snapshot id: " + getSnapshotId(pKey));
try {
FlowExecution lFEx = super.getFlowExecution(pKey);
Conversation lC = getConversation(pKey);
lC.lock();
try {
lC.putAttribute(LAST_VALID_STATE_KEY, getSnapshotId(pKey));
} finally {
lC.unlock();
}
return lFEx;
} catch (FlowExecutionRestorationFailureException e) {
log.debug("FlowExecutionRestorationFailureException levée: l'état le plus récent sera retourné.");
Conversation lC = getConversation(pKey);
Serializable lSnapshotId = (Serializable) lC.getAttribute(LAST_VALID_STATE_KEY);
log.debug(LAST_VALID_STATE_KEY + " = " + lSnapshotId);
FlowExecutionSnapshot lSnapshot = getSnapshotGroup(lC).getSnapshot(lSnapshotId);
return restoreFlowExecution(lSnapshot, pKey, lC);
}
}
}
Since we have to inject that into a FlowExecutor, here's the FactoryBean I used (SWF 2.0 does not let you inject a custom FlowExecutionRepository, as far as I know)
Code:
public class CtqFlowExecutorFactoryBean implements FactoryBean {
private FlowExecutorImpl defaultFlowExecutor;
private Object singleton;
public Object getObject() throws Exception {
if (defaultFlowExecutor == null) {
throw new FactoryBeanNotInitializedException("defaultFlowExecutor ne peut être null");
}
if (singleton != null) { return singleton; }
FlowExecutorImpl lFEx = defaultFlowExecutor;
FlowDefinitionLocator lOriginalLocator = lFEx.getDefinitionLocator();
FlowExecutionFactory lOriginalFactory = lFEx.getExecutionFactory();
FlowExecutionRepository lCtqFER =
new CtqFlowExecutionRepository((DefaultFlowExecutionRepository)lFEx.getExecutionRepository());
singleton = new FlowExecutorImpl(lOriginalLocator, lOriginalFactory, lCtqFER);
return singleton;
}
public Class getObjectType() {
return FlowExecutorImpl.class;
}
public boolean isSingleton() {
return true;
}
/**
* @param pDefaultFlowExecutor the defaultFlowExecutor to set
*/
public void setDefaultFlowExecutor(FlowExecutorImpl pDefaultFlowExecutor) {
defaultFlowExecutor = pDefaultFlowExecutor;
}
}
Finally, XML snippets that glue all of this together:
Code:
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
</webflow:flow-executor>
<bean id="ctqFlowExecutor" class="[properclasspath].CtqFlowExecutorFactoryBean" >
<property name="defaultFlowExecutor" ref="flowExecutor" />
</bean>
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter" id="FHA">
<property name="flowExecutor" ref="ctqFlowExecutor" />
</bean>
Tested quickly, and works. I'll post an update if I find a glitch with this.