
Here we are again dealing with the Abstract Wizard Form Controller, a form controller for typical wizard-style workflows, provided by Spring, a Java Web Application Framework. This time we discuss a more frequent problem: skipping steps.
For istance, let’s consider the situation in which you are at page n of your wizard and submitting a form for target n+1. What if, for some reason, you need to skip the step n+1 and go forward one step?
The first attempt to face this problem might consists in conditionally changing the target value inside the form included in the jsp page corresponding to the view for page n. For example we might switch between passing the request parameter _target3 or _target4 by using the JSTL Core TagLib. This works, but we are putting a conditional control inside a View, that is a very bad practice in a MVC-based framework like Spring.
Let’s move the conditional control into our wizard controller, and to be more precise into the getTargetPage method:
protected int getTargetPage
(HttpServletRequest request,
Object command, Errors errors,
int currentPage
) {
if (currentPage == 2 /* n */) {
if (/* insert your condition here*/) {
return 3; /* n+1 */
}
}
return super.getTargetPage(request, command, errors, currentPage);
}
This solution is clean and makes your application more readable, your code more reusable and so on…
But what if the step we want to jump to is the final step? We cannot reach it by using the getTargetPage method because the final step has no page number assigned: the finish action is triggered by the request parameter _finish and the view name is retrieved by the ModelAndView object that the processFinish method returns.
To solve this problem we can modify the view name for target n+1 at runtime by overriding the getViewName method as following:
protected String getViewName
(HttpServletRequest request,
Object command,
int page
) {
if (page == 3 /* n+1 */) {
retun "redirect:myWizard.html?_finish="; // go to final step
}
return super.getViewName(request, command, page);
}
In this way we simply redirect the flow to the final step. Obviously, at finish all pages get validated to guarantee a consistent state, so you cannot skip a step whose page needs validation.