wizard form with spring mvc
DESCRIPTION
sdffdTRANSCRIPT
2 0 1 1 - 1 0 - 3 0
Wizard form with Spring MVC
A B O U T M E
M ICHAŁ HUNIEWICZ
Michał Huniewicz is
a software engineer,
currently living in
England.
VIEW MY COM PLETE PROFILE
F O L L O W E R S
with Google Friend Connect
Members (80) More »
Already a member? Sign in
A F E W L I N K S . . .
My GitHub
My Homepage
My photos
Tamara BeJot [PL]
L A B E L S
Programming JavaPhotography Maven JBoss
Scala JPA Spring Hibernate CDI
HSQLDB JSF REST Gradle Guice
0 More Next Blog» Create Blog Sign In
B L O G . M 1 K E Y . M EJ A V A , J E E , S P R I N G , P H O T O G R A P H Y B L O G .
blog.m1key.me: Wizard form with Spring MVC http://blog.m1key.me/2011/10/wizard-form-with-spring-mvc.html
1 of 7 6/30/2013 1:57 PM
Today I will show you how to create a wizard form with Spring MVC.
A wizard form is a multi-step form that allows users to submit
information gradually. With Spring MVC it's very easy to make such
a form, as well as validate already submitted data on each step and
on finish.
Controller
This is the main thing. Let's take a detailed look.
The controller is annotated with the @Controller annotation.
@RequestMapping specifies its path. Also, we are storing user
submitted data (an instance of my custom transfer object called
PersonTo) in session with the @SessionAttributes annotation.
@Controller
@RequestMapping("/personRegistration")
@SessionAttributes("personTo")
public class PersonRegistrationController {
Now, let's take a look at initialisation code. The controller expects an
appropriate validator to be passed during construction time. The
validator is, in our case, a Spring bean, so we can have it autowired.
Then we initialise an init binder for the custom Gender enum. That
allows incoming string parameters to be converted into enum
instances.
@Autowired
public PersonRegistrationController(PersonRegistrationValidator valida
super();
this.validator = validator;
}
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Gender.class, new GenderEditor());
}
Next, look at the method that handles GET requests. This method
resets the potentially submitted data by creating a new PersonTo
object and storing it in session. It requests the registration name
form to be displayed. (The forms code will soon follow)
@RequestMapping(method = RequestMethod.GET)
public String setupForm(Model model) {
PersonTo personTo = new PersonTo();
model.addAttribute(PERSON_TO, personTo);
return REGISTRATION_NAME_FORM;
B L O G A R C H I V E
► 2013 (11)
► 2012 (33)
▼ 2011 (27)
► December (3)
► November (1)
▼ October (3)
Wizard form with Spring MVC
JEE6: Integration testing with
JBoss 7
jQuery UI Autocomplete +
Spring MVC
► September (2)
► August (1)
► July (3)
► May (9)
► April (2)
► March (3)
► 2010 (53)
S E A R C H T H I S B L O G
Loading...
blog.m1key.me: Wizard form with Spring MVC http://blog.m1key.me/2011/10/wizard-form-with-spring-mvc.html
2 of 7 6/30/2013 1:57 PM
}
And now the big thing. The method that handles POST requests
which are those where the user actually submitted data.
@RequestMapping(method = RequestMethod.POST)
public String submitForm(HttpServletRequest request,
HttpServletResponse response,
@ModelAttribute(PERSON_TO) PersonTo personTo, BindingResult re
SessionStatus status, @RequestParam("_page") int currentPage,
Model model) {
Map<Integer, String> pageForms = new HashMap<Integer, String>();
pageForms.put(0, REGISTRATION_NAME_FORM);
pageForms.put(1, REGISTRATION_GENDER_FORM);
if (userClickedCancel(request)) {
status.setComplete();
return REDIRECT_TO_HOMEPAGE;
} else if (userIsFinished(request)) {
validator.validate(personTo, result);
if (result.hasErrors()) {
return pageForms.get(currentPage);
} else {
log.info("Registration finished for person [{}: {}].",
personTo.getGender(), personTo.getName());
personTo.setRegistrationComplete(true);
return REDIRECT_TO_SUCCESS_PAGE;
}
} else {
int targetPage = WebUtils.getTargetPage(request, "_target",
currentPage);
if (userClickedPrevious(currentPage, targetPage)) {
return pageForms.get(targetPage);
} else {
switch (currentPage) {
case 0:
validator.validateName(personTo, result);
break;
}
case 1:
validator.validateGender(personTo, result);
break;
}
if (result.hasErrors()) {
blog.m1key.me: Wizard form with Spring MVC http://blog.m1key.me/2011/10/wizard-form-with-spring-mvc.html
3 of 7 6/30/2013 1:57 PM
return pageForms.get(currentPage);
} else {
return pageForms.get(targetPage);
}
}
}
}
If the user clicked cancel, cancel the whole thing by ending
the session and redirect to the home page.
1.
If the user is finished, validate the whole session stored
transfer object. Redirect to success page or display errors.
2.
Otherwise, this is another step in the wizard. In that case,
establish which step it is and apply correct validation. If there
are errors, show the current page where Spring will display
error messages. If everything is OK, go to the next page.
3.
View
I'm using Velocity. Here's the first form where the user types their
name. Look at the Next and Cancel buttons (the names are
important, _target1 and _cancel) and at the hidden input with page
number (zero, since this is the first page in the wizard).
<form method="post" modelAttribute="personTo">
<table>
<tr>
<td>Your name:</td>
<td>#springFormInput("personTo.name" "")
</td>
<td>#springShowErrors("" "")
</td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Next" name="_target1">
<input type="submit" value="Cancel" name="_cancel"
<input type="hidden" value="0" name="_page">
</td>
</tr>
</table>
</form>
And the gender selection page. Note we are using a drop down list
here.
<form method="post" modelAttribute="personTo">
<table>
blog.m1key.me: Wizard form with Spring MVC http://blog.m1key.me/2011/10/wizard-form-with-spring-mvc.html
4 of 7 6/30/2013 1:57 PM
<tr>
<td>Your gender:</td>
<td>#springFormSingleSelect("personTo.gender" $genders
</td>
<td>#springShowErrors("" "")
</td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Previous" name="_targe
<input type="submit" value="Finish" name="_finish"
<input type="submit" value="Cancel" name="_cancel"
<input type="hidden" value="1" name="_page">
</td>
</tr>
</table>
</form>
Property editor
Here's the GenderEditor, if you're interested.
public class GenderEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
if (getValue() == null) {
return null;
} else {
Gender gender = (Gender) getValue();
return gender.toString();
}
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.isEmpty(text)) {
setValue("");
} else if (text.equalsIgnoreCase("m")) {
setValue(Gender.MALE);
} else if (text.equalsIgnoreCase("f")) {
setValue(Gender.FEMALE);
} else if (text.equalsIgnoreCase("o")) {
setValue(Gender.OTHER);
}
}
blog.m1key.me: Wizard form with Spring MVC http://blog.m1key.me/2011/10/wizard-form-with-spring-mvc.html
5 of 7 6/30/2013 1:57 PM
Newer Post Older Post
}
We need the getAsText() method for validation purposes. That
makes sure that if an unknown value is passed from the view, the
resulting value is null (as opposed to the String "null").
Download the source code
The source code for this is available on GitHub.
POSTED BY M ICHAŁ HUN IEW ICZ AT 7:47 PM
LABELS: JAVA, PROGRAMMING, SPR ING, VELOCITY
2 C O M M E N T S :
Add comment
Comment as:
Home
Subscribe to: Post Comments (Atom)
Rossen Stoyanchev November 1, 2011 at 3:18 PM
This is a good case for using Spring Web Flow. If yourapplication has a few of these wizards.
Reply
Michał Huniewicz November 1, 2011 at 11:35 PM
Hi Rossen, thanks for your comment. I am going to look intoSpring Web Flow in future.
Reply
blog.m1key.me: Wizard form with Spring MVC http://blog.m1key.me/2011/10/wizard-form-with-spring-mvc.html
6 of 7 6/30/2013 1:57 PM