Spring Framework has built-in integration for using Spring MVC with JSP and JSTL.

View Resolvers

When developing JSP, it is common to declare an InternalResourceViewResolver bean.

InternalResourceViewResolver can be used to dispatch to any servlet resource, but especially to JSPs. As a best practice, we strongly recommend placing JSP files in a directory under the "WEB-INF" directory so that clients cannot access them directly.


<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

JSPs vs. JSTL

When using the JSP Standard Tag Library (JSTL), you must use a special view class JstlView, since JSTL requires some preparation for things like I18N functions to work.

JSP tag library for Spring

Spring provides binding of request parameter data to objects commands as described in previous chapters. To make it easier to develop JSP pages in conjunction with these data binding features, Spring provides several tags that make things even easier. All Spring tags have HTML escaping features that can be enabled or disabled to escape characters.

The spring.tld tag library (TLD) descriptor is included in spring-webmvc.jar. For comprehensive information on individual tags, view API reference or refer to the tag library description.

Spring Form Tag Library

Since version 2.0 Spring provides a full set of tags that support data binding for working with form elements when using JSP and Spring Web MVC. Each tag provides support for a set of attributes of the corresponding HTML tag counterpart, which makes the tags familiar and intuitive to use. The HTML generated by the tags complies with HTML 4.01/XHTML 1.0 standards.

Unlike other form/input tag libraries, the Form Tag Library for Spring is integrated with Spring Web MVC, allowing tags to have access to command object and reference data , which your controller works with. As shown in the following examples, form tags make JSPs easier to develop, read, and maintain.

We'll walk through form tags and look at an example of how to use each tag. We have included generated HTML fragments where certain tags require additional comments.

Configuration

Form tag library included from spring-webmvc.jar. The library descriptor is called spring-form.tld.

To use tags from this library, add the following directive to the top of your JSP page:

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

where form is the prefix of the tag name that you want to use for tags from this library.

Form tag

This tag renders the HTML "form" element and exposes the binding path to internal tags for anchoring. It places the command object in a PageContext so that the command object can be accessed by internal tags. All other tags in this library are subtags of the form tag.

Suppose we have a domain object called User. It is a JavaBean with properties like firstName and lastName. We can use it as the base form object of our form controller, which returns a form.jsp file. The following example shows what form.jsp might look like:


<form:form>
    <table>
        <tr>
            <td>First Name:</td>
            <td><form:input path="firstName"/></td>
        </tr>
        <tr>
            <td>Last Name:</td>
            <td><form:input path="lastName"/></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Save Changes"/>
            </td>
        </tr>
    </table>
</form:form>

The firstName and lastName values are retrieved from the command object placed in PageContext by the page controller. Continue reading to see more advanced examples of using inner tags with the form tag.

The following listing shows the generated HTML, which looks like a standard form:


<form method="POST">
    <table>
        <tr>
            <td>First Name:</td>
            <td><input name="firstName" type="text" value="Harry"/></td>
        </tr>
        <tr>
            <td>Last Name:</td>
            <td><input name="lastName" type="text" value="Potter"/></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Save Changes"/>
            </td>
        </tr>
    </table>
</form>

The previous JSP assumes that the variable name of the underlying form object is command. If you placed the underlying form object in the model under a different name (definitely the best option), you can bind the form to a named variable, as shown in the following example:


<form:form modelAttribute="user">
    <table>
        <tr>
            <td>First Name:</td>
            <td><form:input path="firstName"/></td>
        </tr>
        <tr>
            <td>Last Name:</td>
            <td><form:input path="lastName"/></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Save Changes"/>
            </td>
        </tr>
    </table>
</form:form>

The input tag

This tag renders the HTML element input with a bound value and type='text' by default. You can also use HTML5-specific types such as email, tel, date and others.

The checkbox tag

This tag renders an HTML input tag with type set to checkbox.

Let's assume that our User has personal user parameters such as a newsletter subscription and a list of hobbies. The following example shows the Preferences class:

Java

public class Preferences {
    private boolean receiveNewsletter;
    private String[] interests;
    private String favouriteWord;
    public boolean isReceiveNewsletter() {
        return receiveNewsletter;
    }
    public void setReceiveNewsletter(boolean receiveNewsletter) {
        this.receiveNewsletter = receiveNewsletter;
    }
    public String[] getInterests() {
        return interests;
    }
    public void setInterests(String[] interests) {
        this.interests = interests;
    }
    public String getFavouriteWord() {
        return favouriteWord;
    }
    public void setFavouriteWord(String favouriteWord) {
        this.favouriteWord = favouriteWord;
    }
}
Kotlin

class Preferences(
        var receiveNewsletter: Boolean,
        var interests: StringArray,
        var favouriteWord: String
)

The corresponding form.jsp file might look like this:


<form:form>
    <table>
        <tr>
            <td>Subscribe to newsletter?:</td>
            <%-- Approach 1: The property is of type java.lang.Boolean --%>
            <td><form:checkbox path="preferences.receiveNewsletter"/></td>
        </tr>
        <tr>
            <td>Interests:</td>
             <%-- Approach 2: The property is an array or has type java.util.Collection --%>
            <td>
                Quidditch: <form:checkbox path="preferences.interests" value="Quidditch"/>
                Herbology: <form:checkbox path="preferences.interests" value="Herbology"/>
                Defence Against the Dark Arts: <form:checkbox path="preferences.interests" value="Defence Against the Dark Arts"/>
            </td>
        </tr>
        <tr>
            <td>Favourite Word:</td>
             <%-- Approach 3: The property is of type java.lang.Object --%>
            <td>
                Magic: <form:checkbox path="preferences.favouriteWord" value="Magic"/>
            </td>
        </tr>
    </table>
</form:form>
        

There are three approaches to the checkbox tag that should suit all your checkbox needs.

  • Approach one: If the associated value is of type java.lang.Boolean, input(checkbox) is marked as checked if the associated value is true. The value attribute corresponds to the allowed value of the setValue(Object) value property.

  • Approach two: If the associated value is of type array or java.util.Collection, input(checkbox) is marked as checked if the configured value is setValue(Object) is present in the associated Collection.

  • Approach three: In case of any other type of associated value input(checkbox) is marked as checked if the configured setValue(Object) is equal to the associated value.

Note that Regardless of the approach, the same HTML structure is generated. The following HTML snippet defines several checkboxes:


<tr>
    <td>Interests:</td>
    <td>
        Quidditch: <input name="preferences.interests" type="checkbox" value="Quidditch"/>
        <input type="hidden" value="1" name="_preferences.interests"/>
        Herbology: <input name="preferences.interests" type="checkbox" value="Herbology"/>
        <input type="hidden" value="1" name="_preferences.interests"/>
        Defence Against the Dark Arts: <input name="preferences.interests" type="checkbox" value="Defence Against the Dark Arts"/>
        <input type="hidden" value="1" name="_preferences.interests"/>
    </td>
</tr>

You might not expect to see an extra hidden field after each checkbox. If a checkbox on an HTML page is not checked, its value is not sent to the server as part of the HTTP request parameters after the form is submitted, so a workaround for this HTML feature is needed in order for Spring form data binding to work. The checkbox tag follows the existing Spring convention of including a hidden parameter prefixed with an underscore (_) for each checkbox. By doing this, you are effectively telling Spring that "the checkbox was visible on the form, and I want my object that the form data is bound to reflect the state of the checkbox, no matter what."

The checkboxes tag

This tag renders multiple HTML input tags with type set to checkbox.

This section builds on the example from the previous section about the checkbox tag. Sometimes it is preferable not to list all possible hobbies on a JSP page. It's better to specify a list of available options at runtime and pass it to the tag. This is the purpose of the checkboxes tag. You can pass a Array, List, or Map containing the available options in the items property. Typically, the bound property is a collection so that it can contain multiple values selected by the user. The following example shows a JSP page that uses this tag:


<form:form>
    <table>
        <tr>
            <td>Interests:</td>
            <td>
                <%-- Property is an array or is of type java.util.Collection --%>
                <form:checkboxes path="preferences.interests" items="${interestList}"/>
            </td>
        </tr>
    </table>
</form:form>

This example assumes that interestList is a List , available as a model attribute that contains strings of values to select from. If you use Map, the key of the Map entry is used as the value, and the value of the Map entry is used as the label to display. You can also use a custom object in which you can specify property names for the value using itemValue and the label using itemLabel.

The radiobutton tag

This tag renders an HTML input element with type set to radio.

A typical usage involves multiple instances of tags bound to the same property but with different values, as shown in the following example:


<tr>
    <td>Sex:</td>
    <td>
        Male: <form:radiobutton path="sex" value="M"/> <br/>
        Female: <form:radiobutton path="sex" value="F"/>
    </td>
</tr>

The radiobuttons tag

This tag renders several input HTML elements with type set to radio.

As with the >checkboxes tag, you can pass available options as a runtime variable. To do this, you can use the radiobuttons tag. You pass a Array, List, or Map containing the available options in the items property. If you use Map, the Map entry's key is used as the value and the Map entry's value is used as the label to be displayed. You can also use a custom object where you can specify property names for a value using itemValue and a label using itemLabel, as shown in the following example:


<tr>
    <td>Sex:</td>
    <td><form:radiobuttons path="sex" items="${sexOptions}"/></td>
</tr>

The password tag

This tag renders the HTML input tag with type set to password, with value bound.


<tr>
    <td>Password:</td>
    <td>
        <form:password path="password"/>
    </td>
</tr>

Please note that by default the password value is not shown. If you want the password value to be shown, you can set the value of the showPassword attribute to true, as shown in the following example:


<tr>
    <td>Password:</td>
    <td>
        <form:password path="password" value="^76525bvHGq" showPassword="true"/>
    </td>
</tr>>

The select tag

This tag renders the "select" HTML element. It supports data binding to the selected option, as well as the use of nested option and options tags.

Assume that User there is a list of skills. The corresponding HTML might look like this:


<tr>
    <td>Skills:</td>
    <td><form:select path="skills" items="${skills}"/></td>
</tr>

If User has herbology skills, then the HTML source for the "Skills" string might look like this:


<tr>
    <td>Skills:</td>
    <td>
        <select name="skills" multiple="true">
            <option value="Potions">Potions</option>
            <option value="Herbology" selected="selected">Herbology</option>
            <option value="Quidditch">Quidditch</option>
        </select>
    </td>
</tr>

The option tag

This tag renders the option HTML element. It sets selected based on the associated value. The following HTML shows typical output for it:

 
<tr>
    <td>House:</td>
    <td>
        <form:select path="house">
            <form:option value="Gryffindor"/>
            <form:option value="Hufflepuff"/>
            <form:option value="Ravenclaw"/>
            <form:option value="Slytherin"/>
        </form:select>
    </td>
</tr>

If User's house is in Gryffindor, then the HTML source for the string "House" will look like as follows:


<tr>
    <td>House:</td>
    <td>
        <select name="house">
            <option value="Gryffindor" selected="selected">Gryffindor</option> 
            <option value="Hufflepuff">Hufflepuff</option>
            <option value="Ravenclaw">Ravenclaw</option>
            <option value="Slytherin">Slytherin</option>
        </select>
    </td>
</tr>
  1. Note the addition of the selected attribute.

The options tag

This tag renders a list of HTML option elements. It sets the selected attribute based on the associated value. The following HTML shows typical output for it:

 
<tr>
    <td>Country:</td>
    <td>
        <form:select path="country">
            <form:option value="-" label="--Please Select"/>
            <form:options items="${countryList}" itemValue="code" itemLabel="name"/>
        </form:select>
    </td>
</tr>

If User lived in the UK, the HTML source for the "Country" string would look like this:


<tr>
    <td>Country:</td>
    <td>
        <select name="country">
            <option value="-">--Please Select</option>
            <option value="AT">Austria</option>
            <option value="UK" selected="selected">United Kingdom</option> 
            <option value="US">United States</option>
        </select>
    </td>
</tr>
  1. Note the addition of the selected attribute.

As shown in the previous example, combining the option tag with the options tag produces the same standard HTML, but allows you to explicitly specify the value in JSP, which is intended only for display (where it belongs), as in the case of the default string in the example: "-- Please Select".

The items usually populated with a collection or array of data item objects. itemValue and itemLabel refer to the bean properties of these item objects, if specified. Otherwise, the item objects themselves become strings. Alternatively, you can specify a Map of elements, in which case the Map keys will be interpreted as option values, and the Map values will correspond to option labels. If itemValue or itemLabel (or both) are also specified, then the data item's value property will be applied to the Map key, and the data item's label property will be applied to the Map value.

The textarea tag

This tag renders the textarea HTML element. The following HTML shows the typical output for it:


<tr>
    <td>Notes:</td>
    <td><form:textarea path="notes" rows="3" cols="20"/></td>
    <td><form:errors path="notes"/></td>
</tr>

The hidden tag

This tag renders the HTML input tag with type set to hidden, with a value bound. To send an unbound hidden value, use the input HTML tag with type set to hidden. The following HTML shows the typical output for it:

<form:hidden path="house"/>

If you decide to pass the value of house as hidden, then the HTML will look like this:

 <input name="house" type="hidden" value="Gryffindor"/>

The errors tag

This tag renders field errors in the HTML span element. It provides access to errors thrown in your controller or errors that were thrown by any validators associated with your controller.

Suppose we want to display all error messages for the firstName fields and lastName after submitting the form. We have a validator for instances of the User class called UserValidator, as shown in the following example:

Java

public class UserValidator implements Validator {
    public boolean supports(Class candidate) {
        return User.class.isAssignableFrom(candidate);
    }
    public void validate(Object obj, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required", "Field is required.");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required", "Field is required.");
    }
}
Kotlin

class UserValidator : Validator {
    override fun supports(candidate: Class<*>): Boolean {
        return User::class.java.isAssignableFrom(candidate)
    }
    override fun validate(obj: Any, errors: Errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required", "Field is required.")
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required", "Field is required.")
    }
}

form.jsp might look like this:


<form:form>
    <table>
        <tr>
            <td>First Name:</td>
            <td><form:input path="firstName"/></td>
            <%-- Show errors for firstName field --%>
            <td><form:errors path="firstName"/></td>
        </tr>
        <tr>
            <td>Last Name:</td>
            <td><form:input path="lastName"/></td>
            <%-- Show errors for lastName field --%>
            <td><form:errors path="lastName"/></td>
        </tr>
        <tr>
            <td colspan="3">
                <input type="submit" value="Save Changes"/>
            </td>
        </tr>
    </table>
</form:form>

If we submit a form with empty values in the firstName and lastName fields, then the HTML will look like this:


<form method="POST">
    <table>
        <tr>
            <td>First Name:</td>
            <td><input name="firstName" type="text" value=""/></td>
            <%-- Associated errors to firstName field displayed --%>
            <td><span name="firstName.errors">Field is required.</span></td>
        </tr>
        <tr>
            <td>Last Name:</td>
            <td><input name="lastName" type="text" value=""/></td>
            <%-- Associated errors to lastName field displayed --%>
            <td><span name="lastName.errors">Field is required.</span></td>
        </tr>
        <tr>
            <td colspan="3">
                <input type="submit" value="Save Changes"/>
            </td>
        </tr>
    </table>
</form>

What if we want to display the entire list of errors for a given page? The following example shows that the errors tag also supports some basic substitution functionality.

  • path="*": Outputs to display all errors.

  • path="lastName": Displays all errors associated with the lastName field.

  • If path is omitted, only object errors are printed.

In the following example, in A list of errors is displayed at the top of the page, and next to the fields there are errors specific to each field:


<form:form>
    <form:errors path="*" cssClass="errorBox"/>
    <table>
        <tr>
            <td>First Name:</td>
            <td><form:input path="firstName"/></td>
            <td><form:errors path="firstName"/></td>
        </tr>
        <tr>
            <td>Last Name:</td>
            <td><form:input path="lastName"/></td>
            <td><form:errors path="lastName"/></td>
        </tr>
        <tr>
            <td colspan="3">
                <input type="submit" value="Save Changes"/>
            </td>
        </tr>
    </table>
</form:form>

HTML will look like this:


<form method="POST">
    <span name="*.errors" class="errorBox">Field is required.<br/>Field is required.</span>
    <table>
        <tr>
            <td>First Name:</td>
            <td><input name="firstName" type="text" value=""/></td>
            <td><span name="firstName.errors">Field is required.</span></td>
        </tr>
        <tr>
            <td>Last Name:</td>
            <td><input name="lastName" type="text" value=""/></td>
            <td><span name="lastName.errors">Field is required.</span></td>
        </tr>
        <tr>
            <td colspan="3">
                <input type="submit" value="Save Changes"/>
            </td>
        </tr>
    </table>
</form>

The spring-form.tld tag library descriptor (TLD) is included in spring-webmvc.jar. For comprehensive information on individual tags, see API reference or refer to the tag library description.

Translating HTTP methods

Key principle REST is the use of a "unified interface". This means that all resources (URLs) can be manipulated using the same four HTTP methods: GET, PUT, POST and DELETE. For each method, the HTTP specification defines the exact semantics. For example, GET should always be a safe operation, meaning it has no side effects, and PUT or DELETE should be idempotent, meaning you can repeat these operations over and over again, but the end result should be the same. Although HTTP defines these four methods, HTML only supports two of them: GET and POST. Luckily, there are two possible workarounds: you can either use JavaScript to do a PUT or DELETE, or you can do a POST with a "real" method as an additional parameter (much like a hidden input field in an HTML form). Spring's HiddenHttpMethodFilter takes advantage of this last trick. This filter is a regular servlet filter, so it can be used in conjunction with any web framework (not just Spring MVC). Add this filter to your web.xml and a POST with a hidden method parameter will be converted to a request for the corresponding HTTP method.

In order to convert HTTP methods, the Spring MVC form tag has been updated in order to provide support for setting the HTTP method. For example, the following snippet is taken from the Pet Clinic example:


<form:form method="delete">
    <p class="submit"><input type="submit" value="Delete Pet"/></p>
</form:form>

The previous example executes the HTTP POST method, while the "real" DELETE method is hidden behind a request parameter. It is picked up by the HiddenHttpMethodFilter, which is defined in web.xml, as shown in the following example:


<filter>
    <filter-name>httpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>httpMethodFilter</filter-name>
    <servlet-name>petclinic</servlet-name>
</filter-mapping>

The following example shows the corresponding method with the @Controller annotation:

Java

@RequestMapping(method = RequestMethod.DELETE)
public String deletePet(@PathVariable int ownerId, @PathVariable int petId) {
    this.clinic.deletePet(petId);
    return "redirect:/owners/" + ownerId;
}
Kotlin

@RequestMapping(method = [RequestMethod.DELETE])
fun deletePet(@PathVariable ownerId: Int, @PathVariable petId: Int): String {
    clinic.deletePet(petId)
    return "redirect:/owners/$ownerId"
}

HTML5 tags

The Spring form tag library allows dynamic attribute input, which means you can enter any HTML5-specific attributes.

The input form tag supports type attribute input , different from text. This allows you to visualize new HTML5-specific input types such as email, date, range and others. Note that entering type='text' is not required because text is the default type.