• No results found

Displaying a web form

In document Spring (Page 130-134)

Basic web forms

4.1 Displaying a web form

PREREQUISITES

None

KEY TECHNOLOGIES

Spring Web MVC, Spring form tag library

This chapter covers

Building a web form

Externalizing strings in a view

Validating and saving form data

Background

Users establish a relationship with a website or an organization by registering. The resulting user account allows logins, order placement, community participation, and so on. The first step in supporting a user registration process is to display a registra-tion form.

Problem

Create a web-based form.

Solution

In this recipe you’ll use Spring Web MVC to display a user registration form. You’ll build a user account form bean, a web controller, a registration form, and a confirma-tion page.

It won’t hurt to have a visual on the UI you’re planning to create in this recipe. Fig-ure 4.1 shows what you’re aiming for.

Let’s begin by creating a form bean for your user accounts.

CREATING AN ACCOUNT FORM BEAN

You use a form bean to store form data, as shown in the following listing.

package com.springinpractice.ch04.web;

import org.apache.commons.lang3.builder.ToStringBuilder;

import org.apache.commons.lang3.builder.ToStringStyle;

public class AccountForm {

private String username, password, confirmPassword, firstName, lastName, email;

private boolean marketingOk = true;

private boolean acceptTerms = false;

public String getUsername() { return username; }

public void setUsername(String username) { this.username = username; } ... other getter/setter pairs ...

public String toString() {

return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("username", username)

.append("firstName", firstName) .append("lastName", lastName) .append("email", email)

.append("marketingOk", marketingOk) .append("acceptTerms", acceptTerms) .toString();

} }

Listing 4.1 AccountForm.java, a form bean for user accounts

Demographic data

B

Marketing preference

C

Legal confirmation

D

toString() implementation

E

AccountForm is a POJO.1 It has properties for personal

B

, marketing

C

, and legal

D

data. These are typical concerns when modeling user accounts. You also include a descriptive toString() method

E

, based on the Commons Lang library, so you can observe the form-binding later in the recipe. By design, you suppress the password here to avoid accidentally revealing it.

You default the marketingOk property to true because you’d like to market to your users unless they explicitly opt out. On the other hand, you default acceptTerms to false because you want the user’s acceptance of the terms of use to be active rather than passive. Presumably this gives you a stronger legal leg to stand on in the event of a disagreement with the user.2

You have a form bean, but without a web controller, it’s inert. Let’s take care of that.

CREATING A WEB CONTROLLER

Your account controller, which appears in the following listing, handles form delivery and processing.

1 See http://en.wikipedia.org/wiki/Plain_Old_Java_Object.

2 Disclaimer: We aren’t lawyers! Consult a qualified legal expert if necessary.

Figure 4.1 The simple web-based registration form that you’ll build in this recipe

package com.springinpractice.ch04.web;

LoggerFactory.getLogger(AccountController.class);

@RequestMapping(value = "new", method = RequestMethod.GET) public String getRegistrationForm(Model model) { model.addAttribute("account", new AccountForm());

return "users/registrationForm";

}

@RequestMapping(value = "", method = RequestMethod.POST) public String postRegistrationForm(AccountForm form) { log.info("Created registration: {}", form);

return "redirect:registration_ok";

} }

At

B

the @Controller annotation tells Spring that this is a web controller. You estab-lish a base path for request mapping using the @RequestMapping annotation

C

. This path contextualizes paths declared at the method level. At

D

you’re not implement-ing any special interfaces or extendimplement-ing special classes.

You serve the empty form bean at

E

. The associated request mapping is /users/

new, which you obtain by combining the class-level /users base path with the method-level new mapping. (To override a class-method-level mapping rather than refine it, place a slash in front of the method-level mapping.) The method itself places a new Account-Form instance on the model under the key account and returns the view name.

You process form submissions at

F

, specifying the POST request method. The request mapping is just /users because that’s the result of combining the base path with the empty string. For now, when users post form data, you log it and redirect them to a view that thanks them for registering

G

. We’ll discuss the redirection in more detail later in the recipe.

Let’s move on to the two view pages. First you’ll create the view for the registration form, and after that you’ll create the “thanks” page for successful form submissions.

CREATING THE VIEW PAGES

The next listing shows how to implement the registration form from figure 4.1. Note that we’ve suppressed the layout and CSS code; see the code download (src/main/

webapp/WEB-INF/jsp/users/registrationForm.jsp) for the full version.

Listing 4.2 AccountController.java to handle user registrations

Declares

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<html>

<head><title>New User Registration</title></head>

<body>

<form:form action="." modelAttribute="account">

<h1>New User Registration</h1>

<div>Username: <form:input path="username" /></div>

<div>Password: <form:password path="password" /></div>

<div>Confirm password: <form:password path="confirmPassword" /></div>

<div>E-mail address: <form:input path="email" /></div>

<div>First name: <form:input path="firstName" /></div>

<div>Last name: <form:input path="lastName" /></div>

<div><form:checkbox id="marketingOk" path="marketingOk" />

Please send me product updates by e-mail.</div>

<div><form:checkbox id="acceptTerms" path="acceptTerms" />

I accept the <a href="#">terms of use</a>.</div>

<div><input type="submit" value="Register" /></div>

</form:form>

</body>

</html>

The registration page uses the form

B

tag to create an HTML form. You use action="." to post the form submission to /main/users/. The modelAttribute attri-bute references the model object to be used as the form-backing bean. The HTML form elements are bound to the form bean’s properties in both directions:

Inbound—The form bean is populated with the HTML form element values when the form is submitted and passed to the controller for validation and processing.

Outbound—The form elements are prepopulated with the form bean’s values.

You use this, for example, to set the default value of the marketingOk check box to true and acceptTerms to false. Form elements are also prepopulated before representing a form to a user for remediating invalid form data; you’ll see this in recipe 4.3.

Figure 4.2 presents a high-level view of form binding.

Listing 4.3 registrationForm.jsp: view to display your registration form

Renders

In document Spring (Page 130-134)