Pivotal Knowledge Base

Follow

Spring Web Flow: Retrieve View States' Status

Environment 

 Product  Version
 Spring Web Flow  All

Overview

This article outlines how to retrieve view states' status information in Spring Web Flow. We currently have a UI component used in our flows that display all the states in a flow.

Symptom

We would like to provide the same UI menu "widget" using Spring Web Flow. We have been trying to get a hold of Web Flow's FlowSessionImpl or FlowRegistry to get a list of all the states. So far we have only been able to get the "current" state via ${flowRequestContext.currentState.id}. Here we provide some guidance on how to extend Web Flow.

Resolution

Option 1:

We need to get a hold of the FlowModel. This means that we need to build it from the XML definition:

ClassPathResource resource = new ClassPathResource("booking-flow.xml", getClass());
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, flowModelRegistry);

builder.init(); builder.build(); FlowModel flow = builder.getFlowModel();  

The FlowModel will then have a method flow.getStates() which would provide access to the ViewStateModel and EndStateModel objects. 

If this is intended to be made as dynamic as possible, it may make more sense to develop a little abstraction of the menu, for example, one Pojo per menu item in an ordered set. The Pojo would then be referenced to the state ID and also contain a nice String representation for the menu label. This approach is more manual and requires manual synchronizing between the menu model and the Web Flow model. However, it will make things easier while not being as dynamic. For example, reading all possible states from the XML definitions and rendering them in a menu.

Option 2:

As an alternative to Solution 1, the same functionality can be implemented in a listener: 

@Autowired
private FlowDefinitionRegistry flowDefinitionRegistry;
private void buildMenuItemsFromFlow(RequestContext context) {
ArrayList viewStatesToDisplay = new ArrayList();
if (flowDefinitionRegistry != null) {
Flow flow = (Flow) flowDefinitionRegistry.getFlowDefinition( context.getActiveFlow().getId());
viewStatesToDisplay = populateArrayWithViewStates(flow);
context.getFlowScope().put("menuItems", viewStatesToDisplay);
}
private ArrayList populateArrayWithViewStates(Flow flow) {
ArrayList tempViewStatesToDisplay = new ArrayList();
for (String stateId : flow.getStateIds()) {
tempViewStatesToDisplay.add(stateId);
}
return tempViewStatesToDisplay;
}

Here is a snippet of a view using the above method:

<fieldset>
<c:forEach var="item" items="${menuItems}">
<div class="field">
<div class="label">VIEW STATE:</div>
<div class="output">${item}</div>
</div>
</c:forEach>
</fieldset>

Comments

Powered by Zendesk