diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupConfigurer.java index b85c92219f0..e8a39846836 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupConfigurer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupConfigurer.java @@ -79,7 +79,7 @@ import org.springframework.util.StringUtils; * @author Rossen Stoyanchev * @since 4.1 * @see GroovyMarkupView - * @see + * @see * Groovy Markup Template engine documentation */ public class GroovyMarkupConfigurer extends TemplateConfiguration diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupView.java index cd8d1b74979..83fc3c4112b 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupView.java @@ -45,7 +45,7 @@ import org.springframework.web.util.NestedServletException; * @since 4.1 * @see GroovyMarkupViewResolver * @see GroovyMarkupConfigurer - * @see + * @see * Groovy Markup Template engine documentation */ public class GroovyMarkupView extends AbstractTemplateView { diff --git a/src/asciidoc/web-view.adoc b/src/asciidoc/web-view.adoc index 7e5a01ecd31..522c40b9c92 100644 --- a/src/asciidoc/web-view.adoc +++ b/src/asciidoc/web-view.adoc @@ -5,213 +5,830 @@ [[view-introduction]] == Introduction One of the areas in which Spring excels is in the separation of view technologies from -the rest of the MVC framework. For example, deciding to use Velocity or XSLT in place of -an existing JSP is primarily a matter of configuration. This chapter covers the major -view technologies that work with Spring and touches briefly on how to add new ones. This -chapter assumes you are already familiar with <> which covers the -basics of how views in general are coupled to the MVC framework. +the rest of the MVC framework. For example, deciding to use Groovy Markup Templates +or Thymeleaf in place of an existing JSP is primarily a matter of configuration. +This chapter covers the major view technologies that work with Spring and touches +briefly on how to add new ones. This chapter assumes you are already familiar with +<> which covers the basics of how views in general are coupled +to the MVC framework. +[[view-thymeleaf]] +== Thymeleaf +http://www.thymeleaf.org/[Thymeleaf] is a good example of a view technology fitting +perfectly in the MVC framework. Support for this integration is not provided by +the Spring team but by the Thymeleaf team itself. -[[view-jsp]] -== JSP & JSTL -Spring provides a couple of out-of-the-box solutions for JSP and JSTL views. Using JSP -or JSTL is done using a normal view resolver defined in the `WebApplicationContext`. -Furthermore, of course you need to write some JSPs that will actually render the view. +Configuring Thymeleaf for Spring usually requires a few beans defined, like a +`ServletContextTemplateResolver`, a `SpringTemplateEngine` and a `ThymeleafViewResolver`. +Please refer to the http://www.thymeleaf.org/documentation.html[Thymeleaf+Spring] +documentation section for more details. -[NOTE] -==== -Setting up your application to use JSTL is a common source of error, mainly caused by -confusion over the different servlet spec., JSP and JSTL version numbers, what they mean -and how to declare the taglibs correctly. The article -http://www.mularien.com/blog/2008/04/24/how-to-reference-and-use-jstl-in-your-web-application/[How -to Reference and Use JSTL in your Web Application] provides a useful guide to the common -pitfalls and how to avoid them. Note that as of Spring 3.0, the minimum supported -servlet version is 2.4 (JSP 2.0 and JSTL 1.1), which reduces the scope for confusion -somewhat. -==== +[[view-groovymarkup]] +== Groovy Markup Templates +The http://groovy-lang.org/templating.html#_the_markuptemplateengine[Groovy Markup Template Engine] +is another view technology, supported by Spring. This template engine is a template engine primarily +aimed at generating XML-like markup (XML, XHTML, HTML5, ...​), but that can be used to generate any +text based content. -[[view-jsp-resolver]] -=== View resolvers -Just as with any other view technology you're integrating with Spring, for JSPs you'll -need a view resolver that will resolve your views. The most commonly used view resolvers -when developing with JSPs are the `InternalResourceViewResolver` and the -`ResourceBundleViewResolver`. Both are declared in the `WebApplicationContext`: +This requires Groovy 2.3.1+ on the the classpath. -[source,xml,indent=0] +[[view-groovymarkup-configuration]] +=== Configuration + +Configuring the Groovy Markup Teplate Engine is quite easy: + +[source,java,indent=0] [subs="verbatim,quotes"] ---- - - - - + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { - # And a sample properties file is uses (views.properties in WEB-INF/classes): - welcome.(class)=org.springframework.web.servlet.view.JstlView - welcome.url=/WEB-INF/jsp/welcome.jsp + @Override + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.groovy(); + } - productList.(class)=org.springframework.web.servlet.view.JstlView - productList.url=/WEB-INF/jsp/productlist.jsp + @Bean + public GroovyMarkupConfigurer groovyMarkupConfigurer() { + GroovyMarkupConfigurer configurer = new GroovyMarkupConfigurer(); + configurer.setResourceLoaderPath("/WEB-INF/"); + return configurer; + } + } ---- -As you can see, the `ResourceBundleViewResolver` needs a properties file defining the -view names mapped to 1) a class and 2) a URL. With a `ResourceBundleViewResolver` you -can mix different types of views using only one resolver. +The XML counterpart using the MVC namespace is: [source,xml,indent=0] [subs="verbatim,quotes"] ---- - - - - - ----- - -The `InternalResourceBundleViewResolver` can be configured for using JSPs as described -above. 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. + + + + + +---- -[[view-jsp-jstl]] -=== 'Plain-old' JSPs versus JSTL -When using the Java Standard Tag Library you must use a special view class, the -`JstlView`, as JSTL needs some preparation before things such as the I18N features will -work. +[[view-groovymarkup-example]] +=== Example +Unlike traditional template engines, this one relies on a DSL that uses the builder syntax. +Here is a sample template for an HTML page: +[source,groovy,indent=0] +[subs="verbatim,quotes"] +---- + yieldUnescaped '' + html(lang:'en') { + head { + meta('http-equiv':'"Content-Type" content="text/html; charset=utf-8"') + title('My page') + } + body { + p('This is an example of HTML contents') + } + } +---- -[[view-jsp-tags]] -=== Additional tags facilitating development -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 tag library descriptor (TLD) is included in the `spring-webmvc.jar`. Further -information about the individual tags can be found in the appendix entitled -<>. +[[view-velocity]] +== Velocity & FreeMarker +http://velocity.apache.org[Velocity] and http://www.freemarker.org[FreeMarker] are two +templating languages that can be used as view technologies within Spring MVC +applications. The languages are quite similar and serve similar needs and so are +considered together in this section. For semantic and syntactic differences between the +two languages, see the http://www.freemarker.org[FreeMarker] web site. -[[view-jsp-formtaglib]] -=== Using 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. +[[view-velocity-dependencies]] +=== Dependencies +Your web application will need to include `velocity-1.x.x.jar` or `freemarker-2.x.jar` +in order to work with Velocity or FreeMarker respectively and `commons-collections.jar` +is required for Velocity. Typically they are included in the `WEB-INF/lib` folder where +they are guaranteed to be found by a Java EE server and added to the classpath for your +application. It is of course assumed that you already have the `spring-webmvc.jar` in +your `'WEB-INF/lib'` directory too! If you make use of Spring's 'dateToolAttribute' or +'numberToolAttribute' in your Velocity views, you will also need to include the +`velocity-tools-generic-1.x.jar` -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 you will see in the following examples, the form tags make -JSPs easier to develop, read and maintain. -Let's 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. +[[view-velocity-contextconfig]] +=== Context configuration +A suitable configuration is initialized by adding the relevant configurer bean +definition to your `'{asterisk}-servlet.xml'` as shown below: -[[view-jsp-formtaglib-configuration]] -==== Configuration -The form tag library comes bundled in `spring-webmvc.jar`. The library descriptor is -called `spring-form.tld`. +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + -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. +[NOTE] +==== +For non web-apps add a `VelocityConfigurationFactoryBean` or a +`FreeMarkerConfigurationFactoryBean` to your application context definition file. +==== -[[view-jsp-formtaglib-formtag]] -==== The form tag -This tag renders an HTML 'form' tag 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__. +[[view-velocity-createtemplates]] +=== Creating templates +Your templates need to be stored in the directory specified by the `{asterisk}Configurer` bean +shown above. This document does not cover details of creating templates for the two +languages - please see their relevant websites for information. If you use the view +resolvers highlighted, then the logical view names relate to the template file names in +similar fashion to `InternalResourceViewResolver` for JSP's. So if your controller +returns a ModelAndView object containing a view name of "welcome" then the resolvers +will look for the `/WEB-INF/freemarker/welcome.ftl` or `/WEB-INF/velocity/welcome.vm` +template as appropriate. -Let's assume we have a domain object called `User`. It is a JavaBean with properties -such as `firstName` and `lastName`. We will use it as the form backing object of our -form controller which returns `form.jsp`. Below is an example of what `form.jsp` would -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. +[[view-velocity-advancedconfig]] +=== Advanced configuration +The basic configurations highlighted above will be suitable for most application +requirements, however additional configuration options are available for when unusual or +advanced requirements dictate. -The generated HTML looks like a standard form: + +[[view-velocity-example-velocityproperties]] +==== velocity.properties +This file is completely optional, but if specified, contains the values that are passed +to the Velocity runtime in order to configure velocity itself. Only required for +advanced configurations, if you need this file, specify its location on the +`VelocityConfigurer` bean definition above. [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), then you can bind the form to the named variable like so: +Alternatively, you can specify velocity properties directly in the bean definition for +the Velocity config bean by replacing the "configLocation" property with the following +inline properties. [source,xml,indent=0] [subs="verbatim,quotes"] ---- - - - - - - - - - - - + + + + file + + org.apache.velocity.runtime.resource.loader.FileResourceLoader + + ${webapp.root}/WEB-INF/velocity + false + + + +---- + +Refer to the +{javadoc-baseurl}/org/springframework/ui/velocity/VelocityEngineFactory.html[API +documentation] for Spring configuration of Velocity, or the Velocity documentation for +examples and definitions of the `'velocity.properties'` file itself. + + +[[views-freemarker]] +==== FreeMarker +FreeMarker 'Settings' and 'SharedVariables' can be passed directly to the FreeMarker +`Configuration` object managed by Spring by setting the appropriate bean properties on +the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a +`java.util.Properties` object and the `freemarkerVariables` property requires a +`java.util.Map`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + +---- + +See the FreeMarker documentation for details of settings and variables as they apply to +the `Configuration` object. + + + +[[view-velocity-forms]] +=== Bind support and form handling +Spring provides a tag library for use in JSP's that contains (amongst other things) a +`` tag. This tag primarily enables forms to display values from form +backing objects and to show the results of failed validations from a `Validator` in the +web or business tier. From version 1.1, Spring now has support for the same +functionality in both Velocity and FreeMarker, with additional convenience macros for +generating form input elements themselves. + + +[[view-bind-macros]] +==== The bind macros +A standard set of macros are maintained within the `spring-webmvc.jar` file for both +languages, so they are always available to a suitably configured application. + +Some of the macros defined in the Spring libraries are considered internal (private) but +no such scoping exists in the macro definitions making all macros visible to calling +code and user templates. The following sections concentrate only on the macros you need +to be directly calling from within your templates. If you wish to view the macro code +directly, the files are called spring.vm / spring.ftl and are in the packages +`org.springframework.web.servlet.view.velocity` or +`org.springframework.web.servlet.view.freemarker` respectively. + + +[[view-simple-binding]] +==== Simple binding +In your html forms (vm / ftl templates) that act as the 'formView' for a Spring form +controller, you can use code similar to the following to bind to field values and +display error messages for each input field in similar fashion to the JSP equivalent. +Note that the name of the command object is "command" by default, but can be overridden +in your MVC configuration by setting the 'commandName' bean property on your form +controller. Example code is shown below for the `personFormV` and `personFormF` views +configured earlier; + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + ... +
+ Name: + #springBind( "command.name" ) +
+ #foreach($error in $status.errorMessages) $error
#end +
+ ... + + + ... + +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + <#import "/spring.ftl" as spring /> + + ... +
+ Name: + <@spring.bind "command.name" /> +
+ <#list spring.status.errorMessages as error> ${error}
+
+ ... + + + ... + +---- + +`#springBind` / `<@spring.bind>` requires a 'path' argument which consists of the name +of your command object (it will be 'command' unless you changed it in your +FormController properties) followed by a period and the name of the field on the command +object you wish to bind to. Nested fields can be used too such as +"command.address.street". The `bind` macro assumes the default HTML escaping behavior +specified by the ServletContext parameter `defaultHtmlEscape` in web.xml + +The optional form of the macro called `#springBindEscaped` / `<@spring.bindEscaped>` +takes a second argument and explicitly specifies whether HTML escaping should be used in +the status error messages or values. Set to true or false as required. Additional form +handling macros simplify the use of HTML escaping and these macros should be used +wherever possible. They are explained in the next section. + + +[[views-form-macros]] +==== Form input generation macros +Additional convenience macros for both languages simplify both binding and form +generation (including validation error display). It is never necessary to use these +macros to generate form input fields, and they can be mixed and matched with simple HTML +or calls direct to the spring bind macros highlighted previously. + +The following table of available macros show the VTL and FTL definitions and the +parameter list that each takes. + +[[views-macros-defs-tbl]] +.Table of macro definitions +[cols="3,1,1"] +|=== +| macro| VTL definition| FTL definition + +| **message** (output a string from a resource bundle based on the code parameter) +| #springMessage($code) +| <@spring.message code/> + +| **messageText** (output a string from a resource bundle based on the code parameter, + falling back to the value of the default parameter) +| #springMessageText($code $text) +| <@spring.messageText code, text/> + +| **url** (prefix a relative URL with the application's context root) +| #springUrl($relativeUrl) +| <@spring.url relativeUrl/> + +| **formInput** (standard input field for gathering user input) +| #springFormInput($path $attributes) +| <@spring.formInput path, attributes, fieldType/> + +| **formHiddenInput *** (hidden input field for submitting non-user input) +| #springFormHiddenInput($path $attributes) +| <@spring.formHiddenInput path, attributes/> + +| **formPasswordInput** * (standard input field for gathering passwords. Note that no + value will ever be populated in fields of this type) +| #springFormPasswordInput($path $attributes) +| <@spring.formPasswordInput path, attributes/> + +| **formTextarea** (large text field for gathering long, freeform text input) +| #springFormTextarea($path $attributes) +| <@spring.formTextarea path, attributes/> + +| **formSingleSelect** (drop down box of options allowing a single required value to be + selected) +| #springFormSingleSelect( $path $options $attributes) +| <@spring.formSingleSelect path, options, attributes/> + +| **formMultiSelect** (a list box of options allowing the user to select 0 or more values) +| #springFormMultiSelect($path $options $attributes) +| <@spring.formMultiSelect path, options, attributes/> + +| **formRadioButtons** (a set of radio buttons allowing a single selection to be made + from the available choices) +| #springFormRadioButtons($path $options $separator $attributes) +| <@spring.formRadioButtons path, options separator, attributes/> + +| **formCheckboxes** (a set of checkboxes allowing 0 or more values to be selected) +| #springFormCheckboxes($path $options $separator $attributes) +| <@spring.formCheckboxes path, options, separator, attributes/> + +| **formCheckbox** (a single checkbox) +| #springFormCheckbox($path $attributes) +| <@spring.formCheckbox path, attributes/> + +| **showErrors** (simplify display of validation errors for the bound field) +| #springShowErrors($separator $classOrStyle) +| <@spring.showErrors separator, classOrStyle/> +|=== + +* In FTL (FreeMarker), these two macros are not actually required as you can use the + normal `formInput` macro, specifying ' `hidden`' or ' `password`' as the value for the + `fieldType` parameter. + +The parameters to any of the above macros have consistent meanings: + +* path: the name of the field to bind to (ie "command.name") +* options: a Map of all the available values that can be selected from in the input + field. The keys to the map represent the values that will be POSTed back from the form + and bound to the command object. Map objects stored against the keys are the labels + displayed on the form to the user and may be different from the corresponding values + posted back by the form. Usually such a map is supplied as reference data by the + controller. Any Map implementation can be used depending on required behavior. For + strictly sorted maps, a `SortedMap` such as a `TreeMap` with a suitable Comparator may + be used and for arbitrary Maps that should return values in insertion order, use a + `LinkedHashMap` or a `LinkedMap` from commons-collections. +* separator: where multiple options are available as discreet elements (radio buttons or + checkboxes), the sequence of characters used to separate each one in the list (ie + "
"). +* attributes: an additional string of arbitrary tags or text to be included within the + HTML tag itself. This string is echoed literally by the macro. For example, in a + textarea field you may supply attributes as 'rows="5" cols="60"' or you could pass + style information such as 'style="border:1px solid silver"'. +* classOrStyle: for the showErrors macro, the name of the CSS class that the span tag + wrapping each error will use. If no information is supplied (or the value is empty) + then the errors will be wrapped in tags. + +Examples of the macros are outlined below some in FTL and some in VTL. Where usage +differences exist between the two languages, they are explained in the notes. + +[[views-form-macros-input]] +===== Input Fields +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + ... + Name: + #springFormInput("command.name" "")
+ #springShowErrors("
" "")
+---- + +The formInput macro takes the path parameter (command.name) and an additional attributes +parameter which is empty in the example above. The macro, along with all other form +generation macros, performs an implicit spring bind on the path parameter. The binding +remains valid until a new bind occurs so the showErrors macro doesn't need to pass the +path parameter again - it simply operates on whichever field a bind was last created for. + +The showErrors macro takes a separator parameter (the characters that will be used to +separate multiple errors on a given field) and also accepts a second parameter, this +time a class name or style attribute. Note that FreeMarker is able to specify default +values for the attributes parameter, unlike Velocity, and the two macro calls above +could be expressed as follows in FTL: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <@spring.formInput "command.name"/> + <@spring.showErrors "
"/> +---- + +Output is shown below of the form fragment generating the name field, and displaying a +validation error after the form was submitted with no value in the field. Validation +occurs through Spring's Validation framework. + +The generated HTML looks like this: + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + Name: + +
+ required +
+
+---- + +The formTextarea macro works the same way as the formInput macro and accepts the same +parameter list. Commonly, the second parameter (attributes) will be used to pass style +information or rows and cols attributes for the textarea. + +[[views-form-macros-select]] +===== Selection Fields +Four selection field macros can be used to generate common UI value selection inputs in +your HTML forms. + +* formSingleSelect +* formMultiSelect +* formRadioButtons +* formCheckboxes + +Each of the four macros accepts a Map of options containing the value for the form +field, and the label corresponding to that value. The value and the label can be the +same. + +An example of radio buttons in FTL is below. The form backing object specifies a default +value of 'London' for this field and so no validation is necessary. When the form is +rendered, the entire list of cities to choose from is supplied as reference data in the +model under the name 'cityMap'. + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + ... + Town: + <@spring.formRadioButtons "command.address.town", cityMap, "" />

+---- + +This renders a line of radio buttons, one for each value in `cityMap` using the +separator "". No additional attributes are supplied (the last parameter to the macro is +missing). The cityMap uses the same String for each key-value pair in the map. The map's +keys are what the form actually submits as POSTed request parameters, map values are the +labels that the user sees. In the example above, given a list of three well known cities +and a default value in the form backing object, the HTML would be + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + Town: + London + Paris + New York +---- + +If your application expects to handle cities by internal codes for example, the map of +codes would be created with suitable keys like the example below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + protected Map referenceData(HttpServletRequest request) throws Exception { + Map cityMap = new LinkedHashMap(); + cityMap.put("LDN", "London"); + cityMap.put("PRS", "Paris"); + cityMap.put("NYC", "New York"); + + Map m = new HashMap(); + m.put("cityMap", cityMap); + return m; + } +---- + +The code would now produce output where the radio values are the relevant codes but the +user still sees the more user friendly city names. + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + Town: + London + Paris + New York +---- + + +[[views-form-macros-html-escaping]] +==== HTML escaping and XHTML compliance +Default usage of the form macros above will result in HTML tags that are HTML 4.01 +compliant and that use the default value for HTML escaping defined in your web.xml as +used by Spring's bind support. In order to make the tags XHTML compliant or to override +the default HTML escaping value, you can specify two variables in your template (or in +your model where they will be visible to your templates). The advantage of specifying +them in the templates is that they can be changed to different values later in the +template processing to provide different behavior for different fields in your form. + +To switch to XHTML compliance for your tags, specify a value of 'true' for a +model/context variable named xhtmlCompliant: + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + ## for Velocity.. + #set($springXhtmlCompliant = true) + + <#-- for FreeMarker --> + <#assign xhtmlCompliant = true in spring> +---- + +Any tags generated by the Spring macros will now be XHTML compliant after processing +this directive. + +In similar fashion, HTML escaping can be specified per field: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <#-- until this point, default HTML escaping is used --> + + <#assign htmlEscape = true in spring> + <#-- next field will use HTML escaping --> + <@spring.formInput "command.name" /> + + <#assign htmlEscape = false in spring> + <#-- all future fields will be bound with HTML escaping off --> +---- + + + + +[[view-jsp]] +== JSP & JSTL +Spring provides a couple of out-of-the-box solutions for JSP and JSTL views. Using JSP +or JSTL is done using a normal view resolver defined in the `WebApplicationContext`. +Furthermore, of course you need to write some JSPs that will actually render the view. + +[NOTE] +==== +Setting up your application to use JSTL is a common source of error, mainly caused by +confusion over the different servlet spec., JSP and JSTL version numbers, what they mean +and how to declare the taglibs correctly. The article +http://www.mularien.com/blog/2008/04/24/how-to-reference-and-use-jstl-in-your-web-application/[How +to Reference and Use JSTL in your Web Application] provides a useful guide to the common +pitfalls and how to avoid them. Note that as of Spring 3.0, the minimum supported +servlet version is 2.4 (JSP 2.0 and JSTL 1.1), which reduces the scope for confusion +somewhat. +==== + + + +[[view-jsp-resolver]] +=== View resolvers +Just as with any other view technology you're integrating with Spring, for JSPs you'll +need a view resolver that will resolve your views. The most commonly used view resolvers +when developing with JSPs are the `InternalResourceViewResolver` and the +`ResourceBundleViewResolver`. Both are declared in the `WebApplicationContext`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + # And a sample properties file is uses (views.properties in WEB-INF/classes): + welcome.(class)=org.springframework.web.servlet.view.JstlView + welcome.url=/WEB-INF/jsp/welcome.jsp + + productList.(class)=org.springframework.web.servlet.view.JstlView + productList.url=/WEB-INF/jsp/productlist.jsp +---- + +As you can see, the `ResourceBundleViewResolver` needs a properties file defining the +view names mapped to 1) a class and 2) a URL. With a `ResourceBundleViewResolver` you +can mix different types of views using only one resolver. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +The `InternalResourceBundleViewResolver` can be configured for using JSPs as described +above. 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. + + + +[[view-jsp-jstl]] +=== 'Plain-old' JSPs versus JSTL +When using the Java Standard Tag Library you must use a special view class, the +`JstlView`, as JSTL needs some preparation before things such as the I18N features will +work. + + + +[[view-jsp-tags]] +=== Additional tags facilitating development +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 tag library descriptor (TLD) is included in the `spring-webmvc.jar`. Further +information about the individual tags can be found in the appendix entitled +<>. + + + +[[view-jsp-formtaglib]] +=== Using 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 you will see in the following examples, the form tags make +JSPs easier to develop, read and maintain. + +Let's 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. + + +[[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. + + +[[view-jsp-formtaglib-formtag]] +==== The form tag + +This tag renders an HTML 'form' tag 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__. + +Let's assume we have a domain object called `User`. It is a JavaBean with properties +such as `firstName` and `lastName`. We will use it as the form backing object of our +form controller which returns `form.jsp`. Below is an example of what `form.jsp` would +look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +
First Name:
Last Name:
+ + + + + + + + + + + +
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 generated HTML 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), then you can bind the form to the named variable like so: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + @@ -743,819 +1360,484 @@ field-specific errors next to the fields: - -
First Name:
Last Name:
-
-
----- - -The HTML would look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- -
- Field is required.
Field is required.
- - - - - - - - - - - - - - - - ----- - - -[[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 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 is 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 simply do a POST -with the 'real' method as an additional parameter (modeled as a hidden input field in an -HTML form). This latter trick is what Spring's `HiddenHttpMethodFilter` does. This -filter is a plain Servlet Filter and therefore it can be used in combination with any -web framework (not just Spring MVC). Simply add this filter to your web.xml, and a POST -with a hidden _method parameter will be 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 taken from the updated Petclinic -sample - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - -

-
----- - -This will actually perform an HTTP POST, with the 'real' DELETE method hidden behind a -request parameter, to be picked up by the `HiddenHttpMethodFilter`, as defined in -web.xml: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - - httpMethodFilter - org.springframework.web.filter.HiddenHttpMethodFilter - - - - httpMethodFilter - petclinic - ----- - -The corresponding `@Controller` method is shown below: - -[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; - } ----- - - -[[view-jsp-formtaglib-html5]] -==== HTML5 Tags -Starting with Spring 3, the Spring form tag library allows entering dynamic attributes, -which means you can enter any HTML5 specific attributes. - -In Spring 3.1, 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. - - - - -[[view-tiles]] -== Tiles -It is possible to integrate Tiles - just as any other view technology - in web -applications using Spring. The following describes in a broad way how to do this. - - -[NOTE] -==== -This section focuses on Spring's support for Tiles v3 in the -`org.springframework.web.servlet.view.tiles3` package. -==== - - -[[view-tiles-dependencies]] -=== Dependencies -To be able to use Tiles, you have to add a dependency on Tiles version 3.0.1 or higher -and http://tiles.apache.org/framework/dependency-management.html[its transitive dependencies] -to your project. - - -[[view-tiles-integrate]] -=== How to integrate Tiles -To be able to use Tiles, you have to configure it using files containing definitions -(for basic information on definitions and other Tiles concepts, please have a look at -http://tiles.apache.org[]). In Spring this is done using the `TilesConfigurer`. Have a -look at the following piece of example ApplicationContext configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - /WEB-INF/defs/general.xml - /WEB-INF/defs/widgets.xml - /WEB-INF/defs/administrator.xml - /WEB-INF/defs/customer.xml - /WEB-INF/defs/templates.xml - - - ----- - -As you can see, there are five files containing definitions, which are all located in -the `'WEB-INF/defs'` directory. At initialization of the `WebApplicationContext`, the -files will be loaded and the definitions factory will be initialized. After that has -been done, the Tiles includes in the definition files can be used as views within your -Spring web application. To be able to use the views you have to have a `ViewResolver` -just as with any other view technology used with Spring. Below you can find two -possibilities, the `UrlBasedViewResolver` and the `ResourceBundleViewResolver`. - -You can specify locale specific Tiles definitions by adding an underscore and then -the locale. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - /WEB-INF/defs/tiles.xml - /WEB-INF/defs/tiles_fr_FR.xml - - - ----- - -With this configuration, `tiles_fr_FR.xml` will be used for requests with the `fr_FR` locale, -and `tiles.xml` will be used by default. - -[NOTE] -==== -Since underscores are used to indicate locales, it is recommended to avoid using -them otherwise in the file names for Tiles definitions. -==== - - -[[view-tiles-url]] -==== UrlBasedViewResolver + + +
First Name:Field is required.
Last Name:Field is required.
- -
+ +---- -The `UrlBasedViewResolver` instantiates the given `viewClass` for each view it has to -resolve. +The HTML would look like: [source,xml,indent=0] [subs="verbatim,quotes"] ---- - - - +
+ Field is required.
Field is required.
+ + + + + + + + + + + + + + + + ---- -[[view-tiles-resource]] -==== ResourceBundleViewResolver +[[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 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 is 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 simply do a POST +with the 'real' method as an additional parameter (modeled as a hidden input field in an +HTML form). This latter trick is what Spring's `HiddenHttpMethodFilter` does. This +filter is a plain Servlet Filter and therefore it can be used in combination with any +web framework (not just Spring MVC). Simply add this filter to your web.xml, and a POST +with a hidden _method parameter will be converted into the corresponding HTTP method +request. -The `ResourceBundleViewResolver` has to be provided with a property file containing -viewnames and viewclasses the resolver can use: +To support HTTP method conversion the Spring MVC form tag was updated to support setting +the HTTP method. For example, the following snippet taken from the updated Petclinic +sample [source,xml,indent=0] [subs="verbatim,quotes"] ---- - - - + +

+
---- +This will actually perform an HTTP POST, with the 'real' DELETE method hidden behind a +request parameter, to be picked up by the `HiddenHttpMethodFilter`, as defined in +web.xml: + [source,java,indent=0] [subs="verbatim,quotes"] ---- - ... - welcomeView.(class)=org.springframework.web.servlet.view.tiles3.TilesView - welcomeView.url=welcome (this is the name of a Tiles definition) - - vetsView.(class)=org.springframework.web.servlet.view.tiles3.TilesView - vetsView.url=vetsView (again, this is the name of a Tiles definition) + + httpMethodFilter + org.springframework.web.filter.HiddenHttpMethodFilter + - findOwnersForm.(class)=org.springframework.web.servlet.view.JstlView - findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp - ... + + httpMethodFilter + petclinic + ---- -As you can see, when using the `ResourceBundleViewResolver`, you can easily mix -different view technologies. - -Note that the `TilesView` class supports JSTL (the JSP Standard Tag Library) out of the -box. - - -[[view-tiles-preparer]] -==== SimpleSpringPreparerFactory and SpringBeanPreparerFactory - -As an advanced feature, Spring also supports two special Tiles `PreparerFactory` -implementations. Check out the Tiles documentation for details on how to use -`ViewPreparer` references in your Tiles definition files. - -Specify `SimpleSpringPreparerFactory` to autowire ViewPreparer instances based on -specified preparer classes, applying Spring's container callbacks as well as applying -configured Spring BeanPostProcessors. If Spring's context-wide annotation-config has -been activated, annotations in ViewPreparer classes will be automatically detected and -applied. Note that this expects preparer __classes__ in the Tiles definition files, just -like the default `PreparerFactory` does. - -Specify `SpringBeanPreparerFactory` to operate on specified preparer __names__ instead -of classes, obtaining the corresponding Spring bean from the DispatcherServlet's -application context. The full bean creation process will be in the control of the Spring -application context in this case, allowing for the use of explicit dependency injection -configuration, scoped beans etc. Note that you need to define one Spring bean definition -per preparer name (as used in your Tiles definitions). +The corresponding `@Controller` method is shown below: -[source,xml,indent=0] +[source,java,indent=0] [subs="verbatim,quotes"] ---- - - - - /WEB-INF/defs/general.xml - /WEB-INF/defs/widgets.xml - /WEB-INF/defs/administrator.xml - /WEB-INF/defs/customer.xml - /WEB-INF/defs/templates.xml - - - - - - - + @RequestMapping(method = RequestMethod.DELETE) + public String deletePet(@PathVariable int ownerId, @PathVariable int petId) { + this.clinic.deletePet(petId); + return "redirect:/owners/" + ownerId; + } ---- +[[view-jsp-formtaglib-html5]] +==== HTML5 Tags +Starting with Spring 3, the Spring form tag library allows entering dynamic attributes, +which means you can enter any HTML5 specific attributes. +In Spring 3.1, 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. -[[view-velocity]] -== Velocity & FreeMarker -http://velocity.apache.org[Velocity] and http://www.freemarker.org[FreeMarker] are two -templating languages that can be used as view technologies within Spring MVC -applications. The languages are quite similar and serve similar needs and so are -considered together in this section. For semantic and syntactic differences between the -two languages, see the http://www.freemarker.org[FreeMarker] web site. - - - -[[view-velocity-dependencies]] -=== Dependencies -Your web application will need to include `velocity-1.x.x.jar` or `freemarker-2.x.jar` -in order to work with Velocity or FreeMarker respectively and `commons-collections.jar` -is required for Velocity. Typically they are included in the `WEB-INF/lib` folder where -they are guaranteed to be found by a Java EE server and added to the classpath for your -application. It is of course assumed that you already have the `spring-webmvc.jar` in -your `'WEB-INF/lib'` directory too! If you make use of Spring's 'dateToolAttribute' or -'numberToolAttribute' in your Velocity views, you will also need to include the -`velocity-tools-generic-1.x.jar` - - - -[[view-velocity-contextconfig]] -=== Context configuration -A suitable configuration is initialized by adding the relevant configurer bean -definition to your `'{asterisk}-servlet.xml'` as shown below: -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ----- +[[view-script]] +== Script templates -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - +It is possible to integrate any templating library running on top of a JSR-223 +script engine in web applications using Spring. The following describes in a +broad way how to do this. The script engine must implement both `ScriptEngine` +and `Invocable` interfaces. - - - - - - ----- +It has been tested with: -[NOTE] -==== -For non web-apps add a `VelocityConfigurationFactoryBean` or a -`FreeMarkerConfigurationFactoryBean` to your application context definition file. -==== +* http://handlebarsjs.com/[Handlebars] running on http://openjdk.java.net/projects/nashorn/[Nashorn] +* https://mustache.github.io/[Mustache] running on http://openjdk.java.net/projects/nashorn/[Nashorn] +* http://facebook.github.io/react/[React] running on http://openjdk.java.net/projects/nashorn/[Nashorn] +* http://www.embeddedjs.com/[EJS] running on http://openjdk.java.net/projects/nashorn/[Nashorn] +* http://www.stuartellis.eu/articles/erb/[ERB] running on http://jruby.org[JRuby] +* https://docs.python.org/2/library/string.html#template-strings[String templates] running on http://www.jython.org/[Jython] +[[view-script-dependencies]] +=== Dependencies +To be able to use script templates integration, you need to have available in your classpath +the script engine: -[[view-velocity-createtemplates]] -=== Creating templates -Your templates need to be stored in the directory specified by the `{asterisk}Configurer` bean -shown above. This document does not cover details of creating templates for the two -languages - please see their relevant websites for information. If you use the view -resolvers highlighted, then the logical view names relate to the template file names in -similar fashion to `InternalResourceViewResolver` for JSP's. So if your controller -returns a ModelAndView object containing a view name of "welcome" then the resolvers -will look for the `/WEB-INF/freemarker/welcome.ftl` or `/WEB-INF/velocity/welcome.vm` -template as appropriate. +* http://openjdk.java.net/projects/nashorn/[Nashorn] Javascript engine is provided builtin with Java 8+ +* http://docs.oracle.com/javase/7/docs/technotes/guides/scripting/programmer_guide/#jsengine[Rhino] + Javascript engine is provided builtin with Java 6 and Java 7. + Please notice that using Rhino is not recommended since it does not + support running most template engines. +* http://jruby.org[JRuby] dependency should be added in order to get Ruby support. +* http://www.jython.org[Jython] dependency should be added in order to get Python support. +You should also need to add dependencies for your script based template engine. For example, +for Javascript you can use http://www.webjars.org/[WebJars] to add Maven/Gradle dependencies +in order to make your javascript libraries available in the classpath. -[[view-velocity-advancedconfig]] -=== Advanced configuration -The basic configurations highlighted above will be suitable for most application -requirements, however additional configuration options are available for when unusual or -advanced requirements dictate. +[[view-script-integrate]] +=== How to integrate script based templating +To be able to use script templates, you have to configure it in order to specify various parameters +like the script engine to use, the script files to load and what function should be called to +render the templates. This is done thanks to a `ScriptTemplateConfigurer` bean and optional script +files. -[[view-velocity-example-velocityproperties]] -==== velocity.properties -This file is completely optional, but if specified, contains the values that are passed -to the Velocity runtime in order to configure velocity itself. Only required for -advanced configurations, if you need this file, specify its location on the -`VelocityConfigurer` bean definition above. +For example, in order to render Mustache templates thanks to the Nashorn Javascript engine +provided with Java 8+, you should declare the following configuration: -[source,xml,indent=0] +[source,java,indent=0] [subs="verbatim,quotes"] ---- - - - + @Configuration + @EnableWebMvc + public class MustacheConfig extends WebMvcConfigurerAdapter { + + @Override + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.scriptTemplate(); + } + + @Bean + public ScriptTemplateConfigurer configurer() { + ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); + configurer.setEngineName("nashorn"); + configurer.setScripts("mustache.js"); + configurer.setRenderObject("Mustache"); + configurer.setRenderFunction("render"); + return configurer; + } + } ---- -Alternatively, you can specify velocity properties directly in the bean definition for -the Velocity config bean by replacing the "configLocation" property with the following -inline properties. +The XML counterpart using MVC namespace is: [source,xml,indent=0] [subs="verbatim,quotes"] ---- - - - - file - - org.apache.velocity.runtime.resource.loader.FileResourceLoader - - ${webapp.root}/WEB-INF/velocity - false - - - ----- + -Refer to the -{javadoc-baseurl}/org/springframework/ui/velocity/VelocityEngineFactory.html[API -documentation] for Spring configuration of Velocity, or the Velocity documentation for -examples and definitions of the `'velocity.properties'` file itself. + + + + + + +---- -[[views-freemarker]] -==== FreeMarker -FreeMarker 'Settings' and 'SharedVariables' can be passed directly to the FreeMarker -`Configuration` object managed by Spring by setting the appropriate bean properties on -the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a -`java.util.Properties` object and the `freemarkerVariables` property requires a -`java.util.Map`. +The controller is exactly what you should expect: -[source,xml,indent=0] +[source,java,indent=0] [subs="verbatim,quotes"] ---- - - - - - - - - + @Controller + public class SampleController { - + @RequestMapping + public ModelAndView test() { + ModelAndView mav = new ModelAndView(); + mav.addObject("title", "Sample title").addObject("body", "Sample body"); + mav.setViewName("template.html"); + return mav; + } + } ---- -See the FreeMarker documentation for details of settings and variables as they apply to -the `Configuration` object. - - - -[[view-velocity-forms]] -=== Bind support and form handling -Spring provides a tag library for use in JSP's that contains (amongst other things) a -`` tag. This tag primarily enables forms to display values from form -backing objects and to show the results of failed validations from a `Validator` in the -web or business tier. From version 1.1, Spring now has support for the same -functionality in both Velocity and FreeMarker, with additional convenience macros for -generating form input elements themselves. - - -[[view-bind-macros]] -==== The bind macros -A standard set of macros are maintained within the `spring-webmvc.jar` file for both -languages, so they are always available to a suitably configured application. - -Some of the macros defined in the Spring libraries are considered internal (private) but -no such scoping exists in the macro definitions making all macros visible to calling -code and user templates. The following sections concentrate only on the macros you need -to be directly calling from within your templates. If you wish to view the macro code -directly, the files are called spring.vm / spring.ftl and are in the packages -`org.springframework.web.servlet.view.velocity` or -`org.springframework.web.servlet.view.freemarker` respectively. - - -[[view-simple-binding]] -==== Simple binding -In your html forms (vm / ftl templates) that act as the 'formView' for a Spring form -controller, you can use code similar to the following to bind to field values and -display error messages for each input field in similar fashion to the JSP equivalent. -Note that the name of the command object is "command" by default, but can be overridden -in your MVC configuration by setting the 'commandName' bean property on your form -controller. Example code is shown below for the `personFormV` and `personFormF` views -configured earlier; +And the Mustache template is: -[source,xml,indent=0] +[source,html,indent=0] [subs="verbatim,quotes"] ---- - - ... -
- Name: - #springBind( "command.name" ) -
- #foreach($error in $status.errorMessages) $error
#end -
- ... - - - ... + + {{title}} + + +

{{body}}

+ ---- -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - <#import "/spring.ftl" as spring /> - - ... -
- Name: - <@spring.bind "command.name" /> -
- <#list spring.status.errorMessages as error> ${error}
-
- ... - - - ... - ----- +The render function is called with the following parameters: -`#springBind` / `<@spring.bind>` requires a 'path' argument which consists of the name -of your command object (it will be 'command' unless you changed it in your -FormController properties) followed by a period and the name of the field on the command -object you wish to bind to. Nested fields can be used too such as -"command.address.street". The `bind` macro assumes the default HTML escaping behavior -specified by the ServletContext parameter `defaultHtmlEscape` in web.xml +* template: the view template content (String) +* model: the view model (Map) -The optional form of the macro called `#springBindEscaped` / `<@spring.bindEscaped>` -takes a second argument and explicitly specifies whether HTML escaping should be used in -the status error messages or values. Set to true or false as required. Additional form -handling macros simplify the use of HTML escaping and these macros should be used -wherever possible. They are explained in the next section. +`Mustache.render()` is natively compatible with this signature, so you can call it directly. +If your templating technology requires some customization, you may provide a script that +implements a custom render function. For example, http://handlebarsjs.com[Handlerbars] +needs to compile templates before using them, and requires a +http://en.wikipedia.org/wiki/Polyfill[polyfill] in order to emulate some +browser facilities not available in the server-side script engine. -[[views-form-macros]] -==== Form input generation macros -Additional convenience macros for both languages simplify both binding and form -generation (including validation error display). It is never necessary to use these -macros to generate form input fields, and they can be mixed and matched with simple HTML -or calls direct to the spring bind macros highlighted previously. +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class MustacheConfig extends WebMvcConfigurerAdapter { -The following table of available macros show the VTL and FTL definitions and the -parameter list that each takes. + @Override + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.scriptTemplate(); + } -[[views-macros-defs-tbl]] -.Table of macro definitions -[cols="3,1,1"] -|=== -| macro| VTL definition| FTL definition + @Bean + public ScriptTemplateConfigurer configurer() { + ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); + configurer.setEngineName("nashorn"); + configurer.setScripts("polyfill.js", "handlebars.js", "render.js"); + configurer.setRenderFunction("render"); + return configurer; + } + } +---- -| **message** (output a string from a resource bundle based on the code parameter) -| #springMessage($code) -| <@spring.message code/> +`polyfill.js` only defines the `window` object needed by Handlebars to run properly: -| **messageText** (output a string from a resource bundle based on the code parameter, - falling back to the value of the default parameter) -| #springMessageText($code $text) -| <@spring.messageText code, text/> +[source,javascript,indent=0] +[subs="verbatim,quotes"] +---- + var window = {}; +---- -| **url** (prefix a relative URL with the application's context root) -| #springUrl($relativeUrl) -| <@spring.url relativeUrl/> +This basic `render.js` implementation compiles the template before using it. A production +ready implementation should also store and reused cached templates / pre-compiled templates. +This can be done on the script side, as well as any customization you need (managing +template engine configuration for example). -| **formInput** (standard input field for gathering user input) -| #springFormInput($path $attributes) -| <@spring.formInput path, attributes, fieldType/> +[source,javascript,indent=0] +[subs="verbatim,quotes"] +---- + function render(template, model) { + var compiledTemplate = Handlebars.compile(template); + return compiledTemplate(model); + } +---- -| **formHiddenInput *** (hidden input field for submitting non-user input) -| #springFormHiddenInput($path $attributes) -| <@spring.formHiddenInput path, attributes/> +Check out Spring script templates unit tests +(https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script[java], +https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script[resources]) +for more configuration examples. -| **formPasswordInput** * (standard input field for gathering passwords. Note that no - value will ever be populated in fields of this type) -| #springFormPasswordInput($path $attributes) -| <@spring.formPasswordInput path, attributes/> -| **formTextarea** (large text field for gathering long, freeform text input) -| #springFormTextarea($path $attributes) -| <@spring.formTextarea path, attributes/> -| **formSingleSelect** (drop down box of options allowing a single required value to be - selected) -| #springFormSingleSelect( $path $options $attributes) -| <@spring.formSingleSelect path, options, attributes/> -| **formMultiSelect** (a list box of options allowing the user to select 0 or more values) -| #springFormMultiSelect($path $options $attributes) -| <@spring.formMultiSelect path, options, attributes/> +[[view-xml-marshalling]] +== XML Marshalling View +The `MarshallingView` uses an XML `Marshaller` defined in the `org.springframework.oxm` +package to render the response content as XML. The object to be marshalled can be set +explicitly using `MarhsallingView`'s `modelKey` bean property. Alternatively, the view +will iterate over all model properties and marshal the first type that is supported +by the `Marshaller`. For more information on the functionality in the +`org.springframework.oxm` package refer to the chapter <>. -| **formRadioButtons** (a set of radio buttons allowing a single selection to be made - from the available choices) -| #springFormRadioButtons($path $options $separator $attributes) -| <@spring.formRadioButtons path, options separator, attributes/> -| **formCheckboxes** (a set of checkboxes allowing 0 or more values to be selected) -| #springFormCheckboxes($path $options $separator $attributes) -| <@spring.formCheckboxes path, options, separator, attributes/> -| **formCheckbox** (a single checkbox) -| #springFormCheckbox($path $attributes) -| <@spring.formCheckbox path, attributes/> -| **showErrors** (simplify display of validation errors for the bound field) -| #springShowErrors($separator $classOrStyle) -| <@spring.showErrors separator, classOrStyle/> -|=== -* In FTL (FreeMarker), these two macros are not actually required as you can use the - normal `formInput` macro, specifying ' `hidden`' or ' `password`' as the value for the - `fieldType` parameter. +[[view-tiles]] +== Tiles +It is possible to integrate Tiles - just as any other view technology - in web +applications using Spring. The following describes in a broad way how to do this. -The parameters to any of the above macros have consistent meanings: -* path: the name of the field to bind to (ie "command.name") -* options: a Map of all the available values that can be selected from in the input - field. The keys to the map represent the values that will be POSTed back from the form - and bound to the command object. Map objects stored against the keys are the labels - displayed on the form to the user and may be different from the corresponding values - posted back by the form. Usually such a map is supplied as reference data by the - controller. Any Map implementation can be used depending on required behavior. For - strictly sorted maps, a `SortedMap` such as a `TreeMap` with a suitable Comparator may - be used and for arbitrary Maps that should return values in insertion order, use a - `LinkedHashMap` or a `LinkedMap` from commons-collections. -* separator: where multiple options are available as discreet elements (radio buttons or - checkboxes), the sequence of characters used to separate each one in the list (ie - "
"). -* attributes: an additional string of arbitrary tags or text to be included within the - HTML tag itself. This string is echoed literally by the macro. For example, in a - textarea field you may supply attributes as 'rows="5" cols="60"' or you could pass - style information such as 'style="border:1px solid silver"'. -* classOrStyle: for the showErrors macro, the name of the CSS class that the span tag - wrapping each error will use. If no information is supplied (or the value is empty) - then the errors will be wrapped in tags. +[NOTE] +==== +This section focuses on Spring's support for Tiles v3 in the +`org.springframework.web.servlet.view.tiles3` package. +==== -Examples of the macros are outlined below some in FTL and some in VTL. Where usage -differences exist between the two languages, they are explained in the notes. -[[views-form-macros-input]] -===== Input Fields -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ... - Name: - #springFormInput("command.name" "")
- #springShowErrors("
" "")
----- +[[view-tiles-dependencies]] +=== Dependencies +To be able to use Tiles, you have to add a dependency on Tiles version 3.0.1 or higher +and http://tiles.apache.org/framework/dependency-management.html[its transitive dependencies] +to your project. -The formInput macro takes the path parameter (command.name) and an additional attributes -parameter which is empty in the example above. The macro, along with all other form -generation macros, performs an implicit spring bind on the path parameter. The binding -remains valid until a new bind occurs so the showErrors macro doesn't need to pass the -path parameter again - it simply operates on whichever field a bind was last created for. -The showErrors macro takes a separator parameter (the characters that will be used to -separate multiple errors on a given field) and also accepts a second parameter, this -time a class name or style attribute. Note that FreeMarker is able to specify default -values for the attributes parameter, unlike Velocity, and the two macro calls above -could be expressed as follows in FTL: +[[view-tiles-integrate]] +=== How to integrate Tiles +To be able to use Tiles, you have to configure it using files containing definitions +(for basic information on definitions and other Tiles concepts, please have a look at +http://tiles.apache.org[]). In Spring this is done using the `TilesConfigurer`. Have a +look at the following piece of example ApplicationContext configuration: [source,xml,indent=0] [subs="verbatim,quotes"] ---- - <@spring.formInput "command.name"/> - <@spring.showErrors "
"/> + + + + /WEB-INF/defs/general.xml + /WEB-INF/defs/widgets.xml + /WEB-INF/defs/administrator.xml + /WEB-INF/defs/customer.xml + /WEB-INF/defs/templates.xml + + + ---- -Output is shown below of the form fragment generating the name field, and displaying a -validation error after the form was submitted with no value in the field. Validation -occurs through Spring's Validation framework. +As you can see, there are five files containing definitions, which are all located in +the `'WEB-INF/defs'` directory. At initialization of the `WebApplicationContext`, the +files will be loaded and the definitions factory will be initialized. After that has +been done, the Tiles includes in the definition files can be used as views within your +Spring web application. To be able to use the views you have to have a `ViewResolver` +just as with any other view technology used with Spring. Below you can find two +possibilities, the `UrlBasedViewResolver` and the `ResourceBundleViewResolver`. -The generated HTML looks like this: +You can specify locale specific Tiles definitions by adding an underscore and then +the locale. For example: -[source,jsp,indent=0] +[source,xml,indent=0] [subs="verbatim,quotes"] ---- - Name: - -
- required -
-
+ + + + /WEB-INF/defs/tiles.xml + /WEB-INF/defs/tiles_fr_FR.xml + + + ---- -The formTextarea macro works the same way as the formInput macro and accepts the same -parameter list. Commonly, the second parameter (attributes) will be used to pass style -information or rows and cols attributes for the textarea. +With this configuration, `tiles_fr_FR.xml` will be used for requests with the `fr_FR` locale, +and `tiles.xml` will be used by default. -[[views-form-macros-select]] -===== Selection Fields -Four selection field macros can be used to generate common UI value selection inputs in -your HTML forms. +[NOTE] +==== +Since underscores are used to indicate locales, it is recommended to avoid using +them otherwise in the file names for Tiles definitions. +==== -* formSingleSelect -* formMultiSelect -* formRadioButtons -* formCheckboxes -Each of the four macros accepts a Map of options containing the value for the form -field, and the label corresponding to that value. The value and the label can be the -same. +[[view-tiles-url]] +==== UrlBasedViewResolver -An example of radio buttons in FTL is below. The form backing object specifies a default -value of 'London' for this field and so no validation is necessary. When the form is -rendered, the entire list of cities to choose from is supplied as reference data in the -model under the name 'cityMap'. +The `UrlBasedViewResolver` instantiates the given `viewClass` for each view it has to +resolve. -[source,jsp,indent=0] +[source,xml,indent=0] [subs="verbatim,quotes"] ---- - ... - Town: - <@spring.formRadioButtons "command.address.town", cityMap, "" />

+ + + ---- -This renders a line of radio buttons, one for each value in `cityMap` using the -separator "". No additional attributes are supplied (the last parameter to the macro is -missing). The cityMap uses the same String for each key-value pair in the map. The map's -keys are what the form actually submits as POSTed request parameters, map values are the -labels that the user sees. In the example above, given a list of three well known cities -and a default value in the form backing object, the HTML would be -[source,jsp,indent=0] -[subs="verbatim,quotes"] ----- - Town: - London - Paris - New York ----- +[[view-tiles-resource]] +==== ResourceBundleViewResolver -If your application expects to handle cities by internal codes for example, the map of -codes would be created with suitable keys like the example below. +The `ResourceBundleViewResolver` has to be provided with a property file containing +viewnames and viewclasses the resolver can use: -[source,java,indent=0] +[source,xml,indent=0] [subs="verbatim,quotes"] ---- - protected Map referenceData(HttpServletRequest request) throws Exception { - Map cityMap = new LinkedHashMap(); - cityMap.put("LDN", "London"); - cityMap.put("PRS", "Paris"); - cityMap.put("NYC", "New York"); - - Map m = new HashMap(); - m.put("cityMap", cityMap); - return m; - } + + + ---- -The code would now produce output where the radio values are the relevant codes but the -user still sees the more user friendly city names. - -[source,jsp,indent=0] +[source,java,indent=0] [subs="verbatim,quotes"] ---- - Town: - London - Paris - New York ----- + ... + welcomeView.(class)=org.springframework.web.servlet.view.tiles3.TilesView + welcomeView.url=welcome (this is the name of a Tiles definition) + vetsView.(class)=org.springframework.web.servlet.view.tiles3.TilesView + vetsView.url=vetsView (again, this is the name of a Tiles definition) -[[views-form-macros-html-escaping]] -==== HTML escaping and XHTML compliance -Default usage of the form macros above will result in HTML tags that are HTML 4.01 -compliant and that use the default value for HTML escaping defined in your web.xml as -used by Spring's bind support. In order to make the tags XHTML compliant or to override -the default HTML escaping value, you can specify two variables in your template (or in -your model where they will be visible to your templates). The advantage of specifying -them in the templates is that they can be changed to different values later in the -template processing to provide different behavior for different fields in your form. + findOwnersForm.(class)=org.springframework.web.servlet.view.JstlView + findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp + ... +---- -To switch to XHTML compliance for your tags, specify a value of 'true' for a -model/context variable named xhtmlCompliant: +As you can see, when using the `ResourceBundleViewResolver`, you can easily mix +different view technologies. -[source,jsp,indent=0] -[subs="verbatim,quotes"] ----- - ## for Velocity.. - #set($springXhtmlCompliant = true) +Note that the `TilesView` class supports JSTL (the JSP Standard Tag Library) out of the +box. - <#-- for FreeMarker --> - <#assign xhtmlCompliant = true in spring> ----- -Any tags generated by the Spring macros will now be XHTML compliant after processing -this directive. +[[view-tiles-preparer]] +==== SimpleSpringPreparerFactory and SpringBeanPreparerFactory -In similar fashion, HTML escaping can be specified per field: +As an advanced feature, Spring also supports two special Tiles `PreparerFactory` +implementations. Check out the Tiles documentation for details on how to use +`ViewPreparer` references in your Tiles definition files. + +Specify `SimpleSpringPreparerFactory` to autowire ViewPreparer instances based on +specified preparer classes, applying Spring's container callbacks as well as applying +configured Spring BeanPostProcessors. If Spring's context-wide annotation-config has +been activated, annotations in ViewPreparer classes will be automatically detected and +applied. Note that this expects preparer __classes__ in the Tiles definition files, just +like the default `PreparerFactory` does. + +Specify `SpringBeanPreparerFactory` to operate on specified preparer __names__ instead +of classes, obtaining the corresponding Spring bean from the DispatcherServlet's +application context. The full bean creation process will be in the control of the Spring +application context in this case, allowing for the use of explicit dependency injection +configuration, scoped beans etc. Note that you need to define one Spring bean definition +per preparer name (as used in your Tiles definitions). [source,xml,indent=0] [subs="verbatim,quotes"] ---- - <#-- until this point, default HTML escaping is used --> + + + + /WEB-INF/defs/general.xml + /WEB-INF/defs/widgets.xml + /WEB-INF/defs/administrator.xml + /WEB-INF/defs/customer.xml + /WEB-INF/defs/templates.xml + + - <#assign htmlEscape = true in spring> - <#-- next field will use HTML escaping --> - <@spring.formInput "command.name" /> + + - <#assign htmlEscape = false in spring> - <#-- all future fields will be bound with HTML escaping off --> + ---- - [[view-xslt]] == XSLT XSLT is a transformation language for XML and is popular as a view technology within web @@ -2357,205 +2639,6 @@ https://spring.io/blog/2009/03/16/adding-an-atom-view-to-an-application-using-sp -[[view-script]] -== Script templates - -It is possible to integrate any templating library running on top of a JSR-223 -script engine in web applications using Spring. The following describes in a -broad way how to do this. The script engine must implement both `ScriptEngine` -and `Invocable` interfaces. - -It has been tested with: - -* http://handlebarsjs.com/[Handlebars] running on http://openjdk.java.net/projects/nashorn/[Nashorn] -* https://mustache.github.io/[Mustache] running on http://openjdk.java.net/projects/nashorn/[Nashorn] -* http://facebook.github.io/react/[React] running on http://openjdk.java.net/projects/nashorn/[Nashorn] -* http://www.embeddedjs.com/[EJS] running on http://openjdk.java.net/projects/nashorn/[Nashorn] -* http://www.stuartellis.eu/articles/erb/[ERB] running on http://jruby.org[JRuby] -* https://docs.python.org/2/library/string.html#template-strings[String templates] running on http://www.jython.org/[Jython] - -[[view-script-dependencies]] -=== Dependencies - -To be able to use script templates integration, you need to have available in your classpath -the script engine: - -* http://openjdk.java.net/projects/nashorn/[Nashorn] Javascript engine is provided builtin with Java 8+ -* http://docs.oracle.com/javase/7/docs/technotes/guides/scripting/programmer_guide/#jsengine[Rhino] - Javascript engine is provided builtin with Java 6 and Java 7. - Please notice that using Rhino is not recommended since it does not - support running most template engines. -* http://jruby.org[JRuby] dependency should be added in order to get Ruby support. -* http://www.jython.org[Jython] dependency should be added in order to get Python support. - -You should also need to add dependencies for your script based template engine. For example, -for Javascript you can use http://www.webjars.org/[WebJars] to add Maven/Gradle dependencies -in order to make your javascript libraries available in the classpath. - - -[[view-script-integrate]] -=== How to integrate script based templating - -To be able to use script templates, you have to configure it in order to specify various parameters -like the script engine to use, the script files to load and what function should be called to -render the templates. This is done thanks to a `ScriptTemplateConfigurer` bean and optional script -files. - -For example, in order to render Mustache templates thanks to the Nashorn Javascript engine -provided with Java 8+, you should declare the following configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class MustacheConfig extends WebMvcConfigurerAdapter { - - @Override - public void configureViewResolvers(ViewResolverRegistry registry) { - registry.scriptTemplate(); - } - - @Bean - public ScriptTemplateConfigurer configurer() { - ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); - configurer.setEngineName("nashorn"); - configurer.setScripts("mustache.js"); - configurer.setRenderObject("Mustache"); - configurer.setRenderFunction("render"); - return configurer; - } - } ----- - -The XML counterpart using MVC namespace is: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -The controller is exactly what you should expect: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class SampleController { - - @RequestMapping - public ModelAndView test() { - ModelAndView mav = new ModelAndView(); - mav.addObject("title", "Sample title").addObject("body", "Sample body"); - mav.setViewName("template.html"); - return mav; - } - } ----- - -And the Mustache template is: - -[source,html,indent=0] -[subs="verbatim,quotes"] ----- - - - {{title}} - - -

{{body}}

- - ----- - -The render function is called with the following parameters: - -* template: the view template content (String) -* model: the view model (Map) - -`Mustache.render()` is natively compatible with this signature, so you can call it directly. - -If your templating technology requires some customization, you may provide a script that -implements a custom render function. For example, http://handlebarsjs.com[Handlerbars] -needs to compile templates before using them, and requires a -http://en.wikipedia.org/wiki/Polyfill[polyfill] in order to emulate some -browser facilities not available in the server-side script engine. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class MustacheConfig extends WebMvcConfigurerAdapter { - - @Override - public void configureViewResolvers(ViewResolverRegistry registry) { - registry.scriptTemplate(); - } - - @Bean - public ScriptTemplateConfigurer configurer() { - ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); - configurer.setEngineName("nashorn"); - configurer.setScripts("polyfill.js", "handlebars.js", "render.js"); - configurer.setRenderFunction("render"); - return configurer; - } - } ----- - -`polyfill.js` only defines the `window` object needed by Handlebars to run properly: - -[source,javascript,indent=0] -[subs="verbatim,quotes"] ----- - var window = {}; ----- - -This basic `render.js` implementation compiles the template before using it. A production -ready implementation should also store and reused cached templates / pre-compiled templates. -This can be done on the script side, as well as any customization you need (managing -template engine configuration for example). - -[source,javascript,indent=0] -[subs="verbatim,quotes"] ----- - function render(template, model) { - var compiledTemplate = Handlebars.compile(template); - return compiledTemplate(model); - } ----- - -Check out Spring script templates unit tests -(https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script[java], -https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script[resources]) -for more configuration examples. - - - - -[[view-xml-marshalling]] -== XML Marshalling View -The `MarshallingView` uses an XML `Marshaller` defined in the `org.springframework.oxm` -package to render the response content as XML. The object to be marshalled can be set -explicitly using `MarhsallingView`'s `modelKey` bean property. Alternatively, the view -will iterate over all model properties and marshal the first type that is supported -by the `Marshaller`. For more information on the functionality in the -`org.springframework.oxm` package refer to the chapter <>. - - - - [[view-json-mapping]] == JSON Mapping View The `MappingJackson2JsonView` uses the Jackson library's `ObjectMapper` to render the response
First Name:Field is required.
Last Name:Field is required.
+ +