[[mvc-view-jsp]] = JSP and JSTL The Spring Framework has a built-in integration for using Spring MVC with JSP and JSTL. [[mvc-view-jsp-resolver]] == View Resolvers When developing with JSPs, you typically declare an `InternalResourceViewResolver` bean. `InternalResourceViewResolver` can be used for dispatching to any Servlet resource but in particular for JSPs. As a best practice, we strongly encourage placing your JSP files in a directory under the `WEB-INF` directory so there can be no direct access by clients. This is what is done by the configuration below which registers a JSP view resolver using a default view name prefix of `"/WEB-INF/"` and a default suffix of `".jsp"`. [tabs] ====== Java:: + [source,java,indent=0,subs="verbatim,quotes"] ---- @EnableWebMvc @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp(); } } ---- XML:: + [source,xml,indent=0,subs="verbatim,quotes"] ---- ---- ====== [NOTE] You can specify custom prefix and suffix. [[mvc-view-jsp-jstl]] == JSPs versus JSTL When using the JSP Standard Tag Library (JSTL) you must use a special view class, the `JstlView`, as JSTL needs some preparation before things such as the I18N features can work. [[mvc-view-jsp-tags]] == Spring's JSP Tag Library Spring provides data binding of request parameters to command objects, as described in earlier chapters. To facilitate the development of JSP pages in combination with those data binding features, Spring provides a few tags that make things even easier. All Spring tags have HTML escaping features to enable or disable escaping of characters. The `spring.tld` tag library descriptor (TLD) is included in the `spring-webmvc.jar`. For a comprehensive reference on individual tags, browse the {spring-framework-api}/web/servlet/tags/package-summary.html#package.description[API reference] or see the tag library description. [[mvc-view-jsp-formtaglib]] == Spring's form tag library As of version 2.0, Spring provides a comprehensive set of data binding-aware tags for handling form elements when using JSP and Spring Web MVC. Each tag provides support for the set of attributes of its corresponding HTML tag counterpart, making the tags familiar and intuitive to use. The tag-generated HTML is HTML 4.01/XHTML 1.0 compliant. Unlike other form/input tag libraries, Spring's form tag library is integrated with Spring Web MVC, giving the tags access to the command object and reference data your controller deals with. As we show in the following examples, the form tags make JSPs easier to develop, read, and maintain. We go through the form tags and look at an example of how each tag is used. We have included generated HTML snippets where certain tags require further commentary. [[mvc-view-jsp-formtaglib-configuration]] === Configuration The form tag library comes bundled in `spring-webmvc.jar`. The library descriptor is called `spring-form.tld`. To use the tags from this library, add the following directive to the top of your JSP page: [source,xml,indent=0,subs="verbatim,quotes"] ---- <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> ---- where `form` is the tag name prefix you want to use for the tags from this library. [[mvc-view-jsp-formtaglib-formtag]] === The Form Tag This tag renders an HTML 'form' element and exposes a binding path to inner tags for binding. It puts the command object in the `PageContext` so that the command object can be accessed by inner tags. All the other tags in this library are nested tags of the `form` tag. Assume that we have a domain object called `User`. It is a JavaBean with properties such as `firstName` and `lastName`. We can use it as the form-backing object of our form controller, which returns `form.jsp`. The following example shows what `form.jsp` could look like: [source,xml,indent=0,subs="verbatim,quotes"] ----
First Name:
Last Name:
---- The `firstName` and `lastName` values are retrieved from the command object placed in the `PageContext` by the page controller. Keep reading to see more complex examples of how inner tags are used with the `form` tag. The following listing shows the generated HTML, which looks like a standard form: [source,xml,indent=0,subs="verbatim,quotes"] ----
First Name:
Last Name:
---- The preceding JSP assumes that the variable name of the form-backing object is `command`. If you have put the form-backing object into the model under another name (definitely a best practice), you can bind the form to the named variable, as the following example shows: [source,xml,indent=0,subs="verbatim,quotes"] ----
First Name:
Last Name:
---- [[mvc-view-jsp-formtaglib-inputtag]] === The `input` Tag This tag renders an HTML `input` element with the bound value and `type='text'` by default. For an example of this tag, see xref:web/webmvc-view/mvc-jsp.adoc#mvc-view-jsp-formtaglib-formtag[The Form Tag]. You can also use HTML5-specific types, such as `email`, `tel`, `date`, and others. [[mvc-view-jsp-formtaglib-checkboxtag]] === The `checkbox` Tag This tag renders an HTML `input` tag with the `type` set to `checkbox`. Assume that our `User` has preferences such as newsletter subscription and a list of hobbies. The following example shows the `Preferences` class: [tabs] ====== Java:: + [source,java,indent=0,subs="verbatim,quotes"] ---- 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:: + [source,kotlin,indent=0,subs="verbatim,quotes"] ---- class Preferences( var receiveNewsletter: Boolean, var interests: StringArray, var favouriteWord: String ) ---- ====== The corresponding `form.jsp` could then resemble the following: [source,xml,indent=0,subs="verbatim,quotes"] ---- <%-- Approach 1: Property is of type java.lang.Boolean --%> <%-- Approach 2: Property is of an array or of type java.util.Collection --%> <%-- Approach 3: Property is of type java.lang.Object --%>
Subscribe to newsletter?:
Interests: Quidditch: Herbology: Defence Against the Dark Arts:
Favourite Word: Magic:
---- There are three approaches to the `checkbox` tag, which should meet all your checkbox needs. * Approach One: When the bound value is of type `java.lang.Boolean`, the `input(checkbox)` is marked as `checked` if the bound value is `true`. The `value` attribute corresponds to the resolved value of the `setValue(Object)` value property. * Approach Two: When the bound value is of type `array` or `java.util.Collection`, the `input(checkbox)` is marked as `checked` if the configured `setValue(Object)` value is present in the bound `Collection`. * Approach Three: For any other bound value type, the `input(checkbox)` is marked as `checked` if the configured `setValue(Object)` is equal to the bound value. Note that, regardless of the approach, the same HTML structure is generated. The following HTML snippet defines some checkboxes: [source,xml,indent=0,subs="verbatim,quotes"] ---- Interests: Quidditch: Herbology: Defence Against the Dark Arts: ---- You might not expect to see the additional hidden field after each checkbox. When a checkbox in an HTML page is not checked, its value is not sent to the server as part of the HTTP request parameters once the form is submitted, so we need a workaround for this quirk in HTML for Spring form data binding to work. The `checkbox` tag follows the existing Spring convention of including a hidden parameter prefixed by an underscore (`_`) for each checkbox. By doing this, you are effectively telling Spring that "`the checkbox was visible in the form, and I want my object to which the form data binds to reflect the state of the checkbox, no matter what.`" [[mvc-view-jsp-formtaglib-checkboxestag]] === The `checkboxes` Tag This tag renders multiple HTML `input` tags with the `type` set to `checkbox`. This section build on the example from the previous `checkbox` tag section. Sometimes, you prefer not to have to list all the possible hobbies in your JSP page. You would rather provide a list at runtime of the available options and pass that in to the tag. That is the purpose of the `checkboxes` tag. You can pass in an `Array`, a `List`, or a `Map` that contains the available options in the `items` property. Typically, the bound property is a collection so that it can hold multiple values selected by the user. The following example shows a JSP that uses this tag: [source,xml,indent=0,subs="verbatim,quotes"] ----
Interests: <%-- Property is of an array or of type java.util.Collection --%>
---- This example assumes that the `interestList` is a `List` available as a model attribute that contains strings of the values to be selected from. If you use a `Map`, the map entry 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 provide the property names for the value by using `itemValue` and the label by using `itemLabel`. [[mvc-view-jsp-formtaglib-radiobuttontag]] === The `radiobutton` Tag This tag renders an HTML `input` element with the `type` set to `radio`. A typical usage pattern involves multiple tag instances bound to the same property but with different values, as the following example shows: [source,xml,indent=0,subs="verbatim,quotes"] ---- Sex: Male:
Female: ---- [[mvc-view-jsp-formtaglib-radiobuttonstag]] === The `radiobuttons` Tag This tag renders multiple HTML `input` elements with the `type` set to `radio`. As with the xref:web/webmvc-view/mvc-jsp.adoc#mvc-view-jsp-formtaglib-checkboxestag[`checkboxes` tag], you might want to pass in the available options as a runtime variable. For this usage, you can use the `radiobuttons` tag. You pass in an `Array`, a `List`, or a `Map` that contains the available options in the `items` property. If you use a `Map`, the map entry key is used as the value and the map entry's value are used as the label to be displayed. You can also use a custom object where you can provide the property names for the value by using `itemValue` and the label by using `itemLabel`, as the following example shows: [source,xml,indent=0,subs="verbatim,quotes"] ---- Sex: ---- [[mvc-view-jsp-formtaglib-passwordtag]] === The `password` Tag This tag renders an HTML `input` tag with the type set to `password` with the bound value. [source,xml,indent=0,subs="verbatim,quotes"] ---- Password: ---- Note that, by default, the password value is not shown. If you do want the password value to be shown, you can set the value of the `showPassword` attribute to `true`, as the following example shows: [source,xml,indent=0,subs="verbatim,quotes"] ---- Password: ---- [[mvc-view-jsp-formtaglib-selecttag]] === The `select` Tag This tag renders an HTML 'select' element. It supports data binding to the selected option as well as the use of nested `option` and `options` tags. Assume that a `User` has a list of skills. The corresponding HTML could be as follows: [source,xml,indent=0,subs="verbatim,quotes"] ---- Skills: ---- If the `User's` skill are in Herbology, the HTML source of the 'Skills' row could be as follows: [source,xml,indent=0,subs="verbatim,quotes"] ---- Skills: ---- [[mvc-view-jsp-formtaglib-optiontag]] === The `option` Tag This tag renders an HTML `option` element. It sets `selected`, based on the bound value. The following HTML shows typical output for it: [source,xml,indent=0,subs="verbatim,quotes"] ---- House: ---- If the `User's` house was in Gryffindor, the HTML source of the 'House' row would be as follows: [source,xml,indent=0,subs="verbatim,quotes"] ---- House: ---- <1> Note the addition of a `selected` attribute. [[mvc-view-jsp-formtaglib-optionstag]] === The `options` Tag This tag renders a list of HTML `option` elements. It sets the `selected` attribute, based on the bound value. The following HTML shows typical output for it: [source,xml,indent=0,subs="verbatim,quotes"] ---- Country: ---- If the `User` lived in the UK, the HTML source of the 'Country' row would be as follows: [source,xml,indent=0,subs="verbatim,quotes"] ---- Country: ---- <1> Note the addition of a `selected` attribute. As the preceding example shows, the combined usage of an `option` tag with the `options` tag generates the same standard HTML but lets you explicitly specify a value in the JSP that is for display only (where it belongs), such as the default string in the example: "-- Please Select". The `items` attribute is typically populated with a collection or array of item objects. `itemValue` and `itemLabel` refer to bean properties of those item objects, if specified. Otherwise, the item objects themselves are turned into strings. Alternatively, you can specify a `Map` of items, in which case the map keys are interpreted as option values and the map values correspond to option labels. If `itemValue` or `itemLabel` (or both) happen to be specified as well, the item value property applies to the map key, and the item label property applies to the map value. [[mvc-view-jsp-formtaglib-textareatag]] === The `textarea` Tag This tag renders an HTML `textarea` element. The following HTML shows typical output for it: [source,xml,indent=0,subs="verbatim,quotes"] ---- Notes: ---- [[mvc-view-jsp-formtaglib-hiddeninputtag]] === The `hidden` Tag This tag renders an HTML `input` tag with the `type` set to `hidden` with the bound value. To submit an unbound hidden value, use the HTML `input` tag with the `type` set to `hidden`. The following HTML shows typical output for it: [source,xml,indent=0,subs="verbatim,quotes"] ---- ---- If we choose to submit the `house` value as a hidden one, the HTML would be as follows: [source,xml,indent=0,subs="verbatim,quotes"] ---- ---- [[mvc-view-jsp-formtaglib-errorstag]] === The `errors` Tag This tag renders field errors in an HTML `span` element. It provides access to the errors created in your controller or those that were created by any validators associated with your controller. Assume that we want to display all error messages for the `firstName` and `lastName` fields once we submit the form. We have a validator for instances of the `User` class called `UserValidator`, as the following example shows: [tabs] ====== Java:: + [source,java,indent=0,subs="verbatim,quotes"] ---- 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:: + [source,kotlin,indent=0,subs="verbatim,quotes"] ---- 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.") } } ---- ====== The `form.jsp` could be as follows: [source,xml,indent=0,subs="verbatim,quotes"] ---- <%-- Show errors for firstName field --%> <%-- Show errors for lastName field --%>
First Name:
Last Name:
---- If we submit a form with empty values in the `firstName` and `lastName` fields, the HTML would be as follows: [source,xml,indent=0,subs="verbatim,quotes"] ----
<%-- Associated errors to firstName field displayed --%> <%-- Associated errors to lastName field displayed --%>
First Name: Field is required.
Last Name: Field is required.
---- What if we want to display the entire list of errors for a given page? The next example shows that the `errors` tag also supports some basic wildcard functionality. * `path="{asterisk}"`: Displays all errors. * `path="lastName"`: Displays all errors associated with the `lastName` field. * If `path` is omitted, only object errors are displayed. The following example displays a list of errors at the top of the page, followed by field-specific errors next to the fields: [source,xml,indent=0,subs="verbatim,quotes"] ----
First Name:
Last Name:
---- The HTML would be as follows: [source,xml,indent=0,subs="verbatim,quotes"] ----
Field is required.
Field is required.
First Name: Field is required.
Last Name: Field is required.
---- The `spring-form.tld` tag library descriptor (TLD) is included in the `spring-webmvc.jar`. For a comprehensive reference on individual tags, browse the {spring-framework-api}/web/servlet/tags/form/package-summary.html#package.description[API reference] or see the tag library description. [[mvc-rest-method-conversion]] === HTTP Method Conversion A key principle of REST is the use of the "`Uniform Interface`". This means that all resources (URLs) can be manipulated by using the same four HTTP methods: GET, PUT, POST, and DELETE. For each method, the HTTP specification defines the exact semantics. For instance, a GET should always be a safe operation, meaning that it has no side effects, and a PUT or DELETE should be idempotent, meaning that you can repeat these operations over and over again, but the end result should be the same. While HTTP defines these four methods, HTML only supports two: GET and POST. Fortunately, there are two possible workarounds: you can either use JavaScript to do your PUT or DELETE, or you can do a POST with the "`real`" method as an additional parameter (modeled as a hidden input field in an HTML form). Spring's `HiddenHttpMethodFilter` uses this latter trick. This filter is a plain Servlet filter and, therefore, it can be used in combination with any web framework (not just Spring MVC). Add this filter to your web.xml, and a POST with a hidden `method` parameter is converted into the corresponding HTTP method request. To support HTTP method conversion, the Spring MVC form tag was updated to support setting the HTTP method. For example, the following snippet comes from the Pet Clinic sample: [source,xml,indent=0,subs="verbatim,quotes"] ----

---- The preceding example performs an HTTP POST, with the "`real`" DELETE method hidden behind a request parameter. It is picked up by the `HiddenHttpMethodFilter`, which is defined in web.xml, as the following example shows: [source,xml,indent=0,subs="verbatim,quotes"] ---- httpMethodFilter org.springframework.web.filter.HiddenHttpMethodFilter httpMethodFilter petclinic ---- The following example shows the corresponding `@Controller` method: [tabs] ====== Java:: + [source,java,indent=0,subs="verbatim,quotes"] ---- @RequestMapping(method = RequestMethod.DELETE) public String deletePet(@PathVariable int ownerId, @PathVariable int petId) { this.clinic.deletePet(petId); return "redirect:/owners/" + ownerId; } ---- Kotlin:: + [source,kotlin,indent=0,subs="verbatim,quotes"] ---- @RequestMapping(method = [RequestMethod.DELETE]) fun deletePet(@PathVariable ownerId: Int, @PathVariable petId: Int): String { clinic.deletePet(petId) return "redirect:/owners/$ownerId" } ---- ====== [[mvc-view-jsp-formtaglib-html5]] === HTML5 Tags The Spring form tag library allows entering dynamic attributes, which means you can enter any HTML5 specific attributes. The form `input` tag supports entering a type attribute other than `text`. This is intended to allow rendering new HTML5 specific input types, such as `email`, `date`, `range`, and others. Note that entering `type='text'` is not required, since `text` is the default type.