@@ -210,13 +210,8 @@ The following table shows the templating libraries that we have tested on differ
210210[%header]
211211|===
212212|Scripting Library |Scripting Engine
213- |https://handlebarsjs.com/[Handlebars] |https://openjdk.java.net/projects/nashorn/[Nashorn]
214- |https://mustache.github.io/[Mustache] |https://openjdk.java.net/projects/nashorn/[Nashorn]
215- |https://react.dev/[React] |https://openjdk.java.net/projects/nashorn/[Nashorn]
216- |https://ejs.co/[EJS] |https://openjdk.java.net/projects/nashorn/[Nashorn]
217213|https://docs.ruby-lang.org/en/master/ERB.html[ERB] |https://www.jruby.org[JRuby]
218214|https://docs.python.org/2/library/string.html#template-strings[String templates] |https://www.jython.org/[Jython]
219- |https://github.com/sdeleuze/kotlin-script-templating[Kotlin Script templating] |{kotlin-site}[Kotlin]
220215|===
221216
222217TIP: The basic rule for integrating any other script engine is that it must implement the
@@ -228,25 +223,16 @@ TIP: The basic rule for integrating any other script engine is that it must impl
228223
229224You need to have the script engine on your classpath, the details of which vary by script engine:
230225
231- * The https://openjdk.java.net/projects/nashorn/[Nashorn] JavaScript engine is provided with
232- Java 8+. Using the latest update release available is highly recommended.
233226* https://www.jruby.org[JRuby] should be added as a dependency for Ruby support.
234227* https://www.jython.org[Jython] should be added as a dependency for Python support.
235- * `org.jetbrains.kotlin:kotlin-script-util` dependency and a `META-INF/services/javax.script.ScriptEngineFactory`
236- file containing a `org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory`
237- line should be added for Kotlin script support. See
238- https://github.com/sdeleuze/kotlin-script-templating[this example] for more detail.
239-
240- You need to have the script templating library. One way to do that for JavaScript is
241- through https://www.webjars.org/[WebJars].
242228
243229[[webflux-view-script-integrate]]
244230=== Script Templates
245231[.small]#xref:web/webmvc-view/mvc-script.adoc#mvc-view-script-integrate[See equivalent in the Servlet stack]#
246232
247233You can declare a `ScriptTemplateConfigurer` bean to specify the script engine to use,
248234the script files to load, what function to call to render templates, and so on.
249- The following example uses Mustache templates and the Nashorn JavaScript engine:
235+ The following example uses the Jython Python engine:
250236
251237[tabs]
252238======
@@ -255,7 +241,6 @@ Java::
255241[source,java,indent=0,subs="verbatim,quotes"]
256242----
257243 @Configuration
258- @EnableWebFlux
259244 public class WebConfig implements WebFluxConfigurer {
260245
261246 @Override
@@ -266,9 +251,8 @@ Java::
266251 @Bean
267252 public ScriptTemplateConfigurer configurer() {
268253 ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
269- configurer.setEngineName("nashorn");
270- configurer.setScripts("mustache.js");
271- configurer.setRenderObject("Mustache");
254+ configurer.setEngineName("jython");
255+ configurer.setScripts("render.py");
272256 configurer.setRenderFunction("render");
273257 return configurer;
274258 }
@@ -280,7 +264,6 @@ Kotlin::
280264[source,kotlin,indent=0,subs="verbatim,quotes"]
281265----
282266 @Configuration
283- @EnableWebFlux
284267 class WebConfig : WebFluxConfigurer {
285268
286269 override fun configureViewResolvers(registry: ViewResolverRegistry) {
@@ -289,9 +272,8 @@ Kotlin::
289272
290273 @Bean
291274 fun configurer() = ScriptTemplateConfigurer().apply {
292- engineName = "nashorn"
293- setScripts("mustache.js")
294- renderObject = "Mustache"
275+ engineName = "jython"
276+ setScripts("render.py")
295277 renderFunction = "render"
296278 }
297279 }
@@ -305,94 +287,7 @@ The `render` function is called with the following parameters:
305287* `RenderingContext renderingContext`: The
306288 {spring-framework-api}/web/servlet/view/script/RenderingContext.html[`RenderingContext`]
307289 that gives access to the application context, the locale, the template loader, and the
308- URL (since 5.0)
309-
310- `Mustache.render()` is natively compatible with this signature, so you can call it directly.
311-
312- If your templating technology requires some customization, you can provide a script that
313- implements a custom render function. For example, https://handlebarsjs.com[Handlerbars]
314- needs to compile templates before using them and requires a
315- https://en.wikipedia.org/wiki/Polyfill[polyfill] in order to emulate some
316- browser facilities not available in the server-side script engine.
317- The following example shows how to set a custom render function:
318-
319- [tabs]
320- ======
321- Java::
322- +
323- [source,java,indent=0,subs="verbatim,quotes"]
324- ----
325- @Configuration
326- @EnableWebFlux
327- public class WebConfig implements WebFluxConfigurer {
328-
329- @Override
330- public void configureViewResolvers(ViewResolverRegistry registry) {
331- registry.scriptTemplate();
332- }
333-
334- @Bean
335- public ScriptTemplateConfigurer configurer() {
336- ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
337- configurer.setEngineName("nashorn");
338- configurer.setScripts("polyfill.js", "handlebars.js", "render.js");
339- configurer.setRenderFunction("render");
340- configurer.setSharedEngine(false);
341- return configurer;
342- }
343- }
344- ----
345-
346- Kotlin::
347- +
348- [source,kotlin,indent=0,subs="verbatim,quotes"]
349- ----
350- @Configuration
351- @EnableWebFlux
352- class WebConfig : WebFluxConfigurer {
353-
354- override fun configureViewResolvers(registry: ViewResolverRegistry) {
355- registry.scriptTemplate()
356- }
357-
358- @Bean
359- fun configurer() = ScriptTemplateConfigurer().apply {
360- engineName = "nashorn"
361- setScripts("polyfill.js", "handlebars.js", "render.js")
362- renderFunction = "render"
363- isSharedEngine = false
364- }
365- }
366- ----
367- ======
368-
369- NOTE: Setting the `sharedEngine` property to `false` is required when using non-thread-safe
370- script engines with templating libraries not designed for concurrency, such as Handlebars or
371- React running on Nashorn. In that case, Java SE 8 update 60 is required, due to
372- https://bugs.openjdk.java.net/browse/JDK-8076099[this bug], but it is generally
373- recommended to use a recent Java SE patch release in any case.
374-
375- `polyfill.js` defines only the `window` object needed by Handlebars to run properly,
376- as the following snippet shows:
377-
378- [source,javascript,indent=0,subs="verbatim,quotes"]
379- ----
380- var window = {};
381- ----
382-
383- This basic `render.js` implementation compiles the template before using it. A production
384- ready implementation should also store and reused cached templates or pre-compiled templates.
385- This can be done on the script side, as well as any customization you need (managing
386- template engine configuration for example).
387- The following example shows how compile a template:
388-
389- [source,javascript,indent=0,subs="verbatim,quotes"]
390- ----
391- function render(template, model) {
392- var compiledTemplate = Handlebars.compile(template);
393- return compiledTemplate(model);
394- }
395- ----
290+ URL
396291
397292Check out the Spring Framework unit tests,
398293{spring-framework-code}/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script[Java], and
0 commit comments