Thymeleaf

Thymeleaf is a modern server-side Java templating engine that emphasizes natural HTML templates that can be previewed in the browser with a double click, which is very useful when working on UI templates yourself (eg , designer) without the need for a running server. Thymeleaf offers an extensive feature set and is actively developed and maintained. More complete introductory information can be found on the project home page Thymeleaf.

Integration of Thymeleaf with Spring WebFlux is managed by the Thymeleaf project. The configuration provides several bean declarations such as SpringResourceTemplateResolver, SpringWebFluxTemplateEngine and ThymeleafReactiveViewResolver. For more information, see "Thymeleaf+Spring" and announcement integration with WebFlux.

FreeMarker

Apache FreeMarker is a template engine to generate any kind of text output from HTML to email and more. The Spring Framework has built-in integration for using Spring WebFlux with templates from FreeMarker.

View Configuration

The following example shows how you can configure FreeMarker as a presentation technology:

Java

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
}
// Configure FreeMarker...
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("classpath:/templates/freemarker");
return configurer;
}
}
Kotlin

@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.freeMarker()
}
// Configure FreeMarker...
@Bean
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
setTemplateLoaderPath("classpath:/templates/freemarker")
}
}

Your templates should be stored in the directory specified by FreeMarkerConfigurer, as shown in the previous example. Given the previous configuration, if the controller returns the view name welcome, the resolver looks for the template classpath:/templates/freemarker/welcome.ftl.

FreeMarker Configuration

It is possible to pass the FreeMarker handler's "Settings" and "SharedVariable" directly into the FreeMarker handler's Configuration object (which is managed by Spring) by setting the appropriate bean properties in FreeMarkerConfigurer. The freemarkerSettings property requires a java.util.Properties object, and the freemarkerVariables property requires a java.util.Map object. The following example shows how to use FreeMarkerConfigurer:

Java

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
// ...
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
Map<String, Object> variables = new HashMap<>();
variables.put("xml_escape", new XmlEscape());
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("classpath:/templates");
configurer.setFreemarkerVariables(variables);
return configurer;
}
}
Kotlin

@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
// ...
@Bean
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
setTemplateLoaderPath("classpath:/templates")
setFreemarkerVariables(mapOf("xml_escape" to XmlEscape()))
}
}

Details For settings and variables that apply to the Configuration object, see the FreeMarker documentation.

Form Handling

Spring provides a tag library for use in JSP that contains, among other things, the <spring:bind/> element. This element primarily allows forms to display values from underlying form objects and display the results of failed validations from a Validator in the web or business tier. Spring also has support for the same functionality in FreeMarker, with additional convenience macros for generating the form input elements themselves.

Binding macros

The support for the standard set of macros is in the file spring-webflux.jar for FreeMarker, so they are always available to a suitably configured application.

Some macros defined in Spring templating libraries are considered internal (private), but there is no such restriction in macro definitions , which makes all macros visible to calling code and user templates. The following sections cover only those macros that need to be called directly from templates. If you need to view the macro code directly, the file is called spring.ftl and is located in the package org.springframework.web.reactive.result.view.freemarker.

Form Macros

For detailed information about form macro support for FreeMarker templates in Spring, see the following sections of the Spring MVC documentation.

  • Input Macros

  • Input fields

  • Selection fields

  • HTML escaping

Scripting Views

Spring Framework has built-in integration for using Spring WebFlux with any templating library that can run on top of the specification scripting engine JSR-223 in Java. The following table shows the template libraries that we tested on various script execution engines:

The basic rule for integrating any other script engine is that it must implement the ScriptEngine and Invocable.

Requirements

You must provide a scripting engine in your classpath, the details of which depend on the scripting engine:

  • A JavaScript processing engine called Nashorn ships with Java 8+. It is strongly recommended that you use the latest available update release.

  • JRuby required add as a dependency to provide support for the Ruby language.

  • Jython must be added as a dependency to provide support for the Python language.

  • To provide support for Kotlin scripts, the dependency org.jetbrains.kotlin:kotlin-script-util must be added and a file META-INF/services/javax.script.ScriptEngineFactory containing the line org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory. For more information, see this example.

You need to add a script template library. One way to do this in the case of JavaScript is WebJars.

Script templates

You can declare a ScriptTemplateConfigurer bean to specify which script engine to use, which script files to load, which function to call to render templates, and so on. The following example uses Mustache templates and a JavaScript engine called Nashorn:

Java

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@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;
}
}
Kotlin

@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.scriptTemplate()
}
@Bean
fun configurer() = ScriptTemplateConfigurer().apply {
engineName = "nashorn"
setScripts("mustache.js")
renderObject = "Mustache"
renderFunction = "render"
}
}

The render function is called with the following parameters:

  • String template: Contents of the template

  • Map model: View model

  • RenderingContext renderingContext: RenderingContext, which provides access to the application context, locale, template loader, and URL (since version 5.0).

Mustache.render() is natively compatible with this signature, so you can call it directly.

If your templating technology requires some customization, you can pass in a script that implements a custom rendering function. For example, Handlerbars requires templates to be compiled before using them and requires polyfill to emulate some browser capabilities that are not available in the server-side scripting engine. The following example shows how to set a custom rendering function:

Java

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@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");
configurer.setSharedEngine(false);
return configurer;
}
}
Kotlin

@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.scriptTemplate()
}
@Bean
fun configurer() = ScriptTemplateConfigurer().apply {
engineName = "nashorn"
setScripts("polyfill.js", "handlebars.js", "render.js")
renderFunction = "render"
isSharedEngine = false
}
}
Setting the sharedEngine property to false is necessary when using thread-unsafe scripting engines with template libraries that are not designed for concurrency, such as Handlebars or React running on Nashorn. In this case, Java SE 8 update 60 is required due to this bug, but it is generally recommended to use the latest Java SE patch release anyway.

polyfill.js only defines the window object that Handlebars needs to work properly, as shown in the following snippet:

var window = {};

This is a basic implementation of render.jscompiles the template before using it. A production-ready implementation must also store any reusable cached templates or precompiled templates. This can be done on the script side, as well as with any settings you need (for example, managing the template engine configuration). The following example shows how to compile the template:


function render(template, model) {
var compiledTemplate = Handlebars.compile(template);
return compiledTemplate(model);
}

Check out the Spring Framework unit tests, Java and resourcesto view more configuration examples.

JSON and XML

For content consistency reasons, it is useful to be able to alternate between displaying a model with a template in HTML or other formats (such as JSON or XML), in depending on the type of content requested by the client. To support this feature, Spring WebFlux provides a HttpMessageWriterView, which can be used to connect any of the available codecs from Spring-web, such as Jackson2JsonEncoder, Jackson2SmileEncoder, or Jaxb2XmlEncoder.

Unlike other presentation technologies, HttpMessageWriterView does not require ViewResolver, but is configured as the default view. You can configure one or more of these default views to wrap them around different HttpMessageWriter instances or Encoder instances. At runtime, the one that matches the requested content type is used.

In most cases, a model contains multiple attributes. To determine which one to serialize, you can configure HttpMessageWriterView with the name of the model attribute that you want to use for rendering. If the model contains only one attribute, then that one will be used.