From d4e4250bb10f24a6356a326a082e94246d56ffd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Mon, 15 Dec 2025 18:42:59 +0100 Subject: [PATCH] Remove JavaScript/Kotlin from ScriptEngine documentation Closes gh-27919 --- .../modules/ROOT/pages/web/webflux-view.adoc | 117 +------------ .../pages/web/webmvc-view/mvc-script.adoc | 159 +++--------------- .../view/script/ScriptTemplateConfigurer.java | 6 +- .../view/script/ScriptTemplateView.java | 4 - .../view/script/ScriptTemplateConfigurer.java | 6 +- .../view/script/ScriptTemplateView.java | 4 - .../web/servlet/config/spring-mvc.xsd | 4 +- 7 files changed, 33 insertions(+), 267 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/web/webflux-view.adoc b/framework-docs/modules/ROOT/pages/web/webflux-view.adoc index 115012fad28..17b165d5677 100644 --- a/framework-docs/modules/ROOT/pages/web/webflux-view.adoc +++ b/framework-docs/modules/ROOT/pages/web/webflux-view.adoc @@ -210,13 +210,8 @@ The following table shows the templating libraries that we have tested on differ [%header] |=== |Scripting Library |Scripting Engine -|https://handlebarsjs.com/[Handlebars] |https://openjdk.java.net/projects/nashorn/[Nashorn] -|https://mustache.github.io/[Mustache] |https://openjdk.java.net/projects/nashorn/[Nashorn] -|https://react.dev/[React] |https://openjdk.java.net/projects/nashorn/[Nashorn] -|https://ejs.co/[EJS] |https://openjdk.java.net/projects/nashorn/[Nashorn] |https://docs.ruby-lang.org/en/master/ERB.html[ERB] |https://www.jruby.org[JRuby] |https://docs.python.org/2/library/string.html#template-strings[String templates] |https://www.jython.org/[Jython] -|https://github.com/sdeleuze/kotlin-script-templating[Kotlin Script templating] |{kotlin-site}[Kotlin] |=== TIP: The basic rule for integrating any other script engine is that it must implement the @@ -228,17 +223,8 @@ TIP: The basic rule for integrating any other script engine is that it must impl You need to have the script engine on your classpath, the details of which vary by script engine: -* The https://openjdk.java.net/projects/nashorn/[Nashorn] JavaScript engine is provided with -Java 8+. Using the latest update release available is highly recommended. * https://www.jruby.org[JRuby] should be added as a dependency for Ruby support. * https://www.jython.org[Jython] should be added as a dependency for Python support. -* `org.jetbrains.kotlin:kotlin-script-util` dependency and a `META-INF/services/javax.script.ScriptEngineFactory` - file containing a `org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory` - line should be added for Kotlin script support. See - https://github.com/sdeleuze/kotlin-script-templating[this example] for more detail. - -You need to have the script templating library. One way to do that for JavaScript is -through https://www.webjars.org/[WebJars]. [[webflux-view-script-integrate]] === Script Templates @@ -246,7 +232,7 @@ through https://www.webjars.org/[WebJars]. You can declare a `ScriptTemplateConfigurer` bean to specify the script engine to use, the script files to load, what function to call to render templates, and so on. -The following example uses Mustache templates and the Nashorn JavaScript engine: +The following example uses the Jython Python engine: [tabs] ====== @@ -255,7 +241,6 @@ Java:: [source,java,indent=0,subs="verbatim,quotes"] ---- @Configuration - @EnableWebFlux public class WebConfig implements WebFluxConfigurer { @Override @@ -266,9 +251,8 @@ Java:: @Bean public ScriptTemplateConfigurer configurer() { ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); - configurer.setEngineName("nashorn"); - configurer.setScripts("mustache.js"); - configurer.setRenderObject("Mustache"); + configurer.setEngineName("jython"); + configurer.setScripts("render.py"); configurer.setRenderFunction("render"); return configurer; } @@ -280,7 +264,6 @@ Kotlin:: [source,kotlin,indent=0,subs="verbatim,quotes"] ---- @Configuration - @EnableWebFlux class WebConfig : WebFluxConfigurer { override fun configureViewResolvers(registry: ViewResolverRegistry) { @@ -289,9 +272,8 @@ Kotlin:: @Bean fun configurer() = ScriptTemplateConfigurer().apply { - engineName = "nashorn" - setScripts("mustache.js") - renderObject = "Mustache" + engineName = "jython" + setScripts("render.py") renderFunction = "render" } } @@ -305,94 +287,7 @@ The `render` function is called with the following parameters: * `RenderingContext renderingContext`: The {spring-framework-api}/web/servlet/view/script/RenderingContext.html[`RenderingContext`] that gives access to the application context, the locale, the template loader, and the - URL (since 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 provide a script that -implements a custom render function. For example, https://handlebarsjs.com[Handlerbars] -needs to compile templates before using them and requires a -https://en.wikipedia.org/wiki/Polyfill[polyfill] in order to emulate some -browser facilities not available in the server-side script engine. -The following example shows how to set a custom render function: - -[tabs] -====== -Java:: -+ -[source,java,indent=0,subs="verbatim,quotes"] ----- - @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:: -+ -[source,kotlin,indent=0,subs="verbatim,quotes"] ----- - @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 - } - } ----- -====== - -NOTE: Setting the `sharedEngine` property to `false` is required when using non-thread-safe -script engines with templating libraries not designed for concurrency, such as Handlebars or -React running on Nashorn. In that case, Java SE 8 update 60 is required, due to -https://bugs.openjdk.java.net/browse/JDK-8076099[this bug], but it is generally -recommended to use a recent Java SE patch release in any case. - -`polyfill.js` defines only the `window` object needed by Handlebars to run properly, -as the following snippet shows: - -[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 or pre-compiled templates. -This can be done on the script side, as well as any customization you need (managing -template engine configuration for example). -The following example shows how compile a template: - -[source,javascript,indent=0,subs="verbatim,quotes"] ----- - function render(template, model) { - var compiledTemplate = Handlebars.compile(template); - return compiledTemplate(model); - } ----- + URL Check out the Spring Framework unit tests, {spring-framework-code}/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script[Java], and diff --git a/framework-docs/modules/ROOT/pages/web/webmvc-view/mvc-script.adoc b/framework-docs/modules/ROOT/pages/web/webmvc-view/mvc-script.adoc index 87a61ad6ab3..1db1c46cbe2 100644 --- a/framework-docs/modules/ROOT/pages/web/webmvc-view/mvc-script.adoc +++ b/framework-docs/modules/ROOT/pages/web/webmvc-view/mvc-script.adoc @@ -11,13 +11,8 @@ templating libraries on different script engines: [%header] |=== |Scripting Library |Scripting Engine -|https://handlebarsjs.com/[Handlebars] |https://openjdk.java.net/projects/nashorn/[Nashorn] -|https://mustache.github.io/[Mustache] |https://openjdk.java.net/projects/nashorn/[Nashorn] -|https://react.dev/[React] |https://openjdk.java.net/projects/nashorn/[Nashorn] -|https://ejs.co/[EJS] |https://openjdk.java.net/projects/nashorn/[Nashorn] |https://docs.ruby-lang.org/en/master/ERB.html[ERB] |https://www.jruby.org[JRuby] |https://docs.python.org/2/library/string.html#template-strings[String templates] |https://www.jython.org/[Jython] -|https://github.com/sdeleuze/kotlin-script-templating[Kotlin Script templating] |{kotlin-site}[Kotlin] |=== TIP: The basic rule for integrating any other script engine is that it must implement the @@ -30,18 +25,8 @@ TIP: The basic rule for integrating any other script engine is that it must impl You need to have the script engine on your classpath, the details of which vary by script engine: -* The https://openjdk.java.net/projects/nashorn/[Nashorn] JavaScript engine is provided with -Java 8+. Using the latest update release available is highly recommended. * https://www.jruby.org[JRuby] should be added as a dependency for Ruby support. * https://www.jython.org[Jython] should be added as a dependency for Python support. -* `org.jetbrains.kotlin:kotlin-script-util` dependency and a `META-INF/services/javax.script.ScriptEngineFactory` - file containing a `org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory` - line should be added for Kotlin script support. See - https://github.com/sdeleuze/kotlin-script-templating[this example] for more details. - -You need to have the script templating library. One way to do that for JavaScript is -through https://www.webjars.org/[WebJars]. - [[mvc-view-script-integrate]] == Script Templates @@ -49,7 +34,7 @@ through https://www.webjars.org/[WebJars]. You can declare a `ScriptTemplateConfigurer` bean to specify the script engine to use, the script files to load, what function to call to render templates, and so on. -The following example uses Mustache templates and the Nashorn JavaScript engine: +The following example uses the Jython Python engine: [tabs] ====== @@ -58,7 +43,6 @@ Java:: [source,java,indent=0,subs="verbatim,quotes"] ---- @Configuration - @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override @@ -69,9 +53,8 @@ Java:: @Bean public ScriptTemplateConfigurer configurer() { ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); - configurer.setEngineName("nashorn"); - configurer.setScripts("mustache.js"); - configurer.setRenderObject("Mustache"); + configurer.setEngineName("jython"); + configurer.setScripts("render.py"); configurer.setRenderFunction("render"); return configurer; } @@ -83,7 +66,6 @@ Kotlin:: [source,kotlin,indent=0,subs="verbatim,quotes"] ---- @Configuration - @EnableWebMvc class WebConfig : WebMvcConfigurer { override fun configureViewResolvers(registry: ViewResolverRegistry) { @@ -92,17 +74,15 @@ Kotlin:: @Bean fun configurer() = ScriptTemplateConfigurer().apply { - engineName = "nashorn" - setScripts("mustache.js") - renderObject = "Mustache" + engineName = "jython" + setScripts("render.py") renderFunction = "render" } } ---- -====== - -The following example shows the same arrangement in XML: +XML:: ++ [source,xml,indent=0,subs="verbatim,quotes"] ---- @@ -111,12 +91,22 @@ The following example shows the same arrangement in XML: - - + + ---- +====== -The controller would look no different for the Java and XML configurations, as the following example shows: +The render function is called with the following parameters: + +* `String template`: The template content +* `Map model`: The view model +* `RenderingContext renderingContext`: The +{spring-framework-api}/web/servlet/view/script/RenderingContext.html[`RenderingContext`] +that gives access to the application context, the locale, the template loader, and the +URL + +The controller is used to populate the model attributes and specify the view name, as the following example shows: [tabs] ====== @@ -153,115 +143,6 @@ Kotlin:: ---- ====== -The following example shows the Mustache template: - -[source,html,indent=0,subs="verbatim,quotes"] ----- - - - {{title}} - - -

{{body}}

- - ----- - -The render function is called with the following parameters: - -* `String template`: The template content -* `Map model`: The view model -* `RenderingContext renderingContext`: The - {spring-framework-api}/web/servlet/view/script/RenderingContext.html[`RenderingContext`] - that gives access to the application context, the locale, the template loader, and the - URL (since 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 provide a script that -implements a custom render function. For example, https://handlebarsjs.com[Handlerbars] -needs to compile templates before using them and requires a -https://en.wikipedia.org/wiki/Polyfill[polyfill] to emulate some -browser facilities that are not available in the server-side script engine. - -The following example shows how to do so: - -[tabs] -====== -Java:: -+ -[source,java,indent=0,subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig implements WebMvcConfigurer { - - @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:: -+ -[source,kotlin,indent=0,subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - class WebConfig : WebMvcConfigurer { - - 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 - } - } ----- -====== - -NOTE: Setting the `sharedEngine` property to `false` is required when using non-thread-safe -script engines with templating libraries not designed for concurrency, such as Handlebars or -React running on Nashorn. In that case, Java SE 8 update 60 is required, due to -https://bugs.openjdk.java.net/browse/JDK-8076099[this bug], but it is generally -recommended to use a recent Java SE patch release in any case. - -`polyfill.js` defines only the `window` object needed by Handlebars to run properly, as follows: - -[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 any reused cached templates or pre-compiled templates. -You can do so on the script side (and handle any customization you need -- managing -template engine configuration, for example). The following example shows how to do so: - -[source,javascript,indent=0,subs="verbatim,quotes"] ----- - function render(template, model) { - var compiledTemplate = Handlebars.compile(template); - return compiledTemplate(model); - } ----- - Check out the Spring Framework unit tests, {spring-framework-code}/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script[Java], and {spring-framework-code}/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script[resources], diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateConfigurer.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateConfigurer.java index 78c9c8e06c3..c5076570dda 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateConfigurer.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateConfigurer.java @@ -42,8 +42,8 @@ import org.jspecify.annotations.Nullable; * * *

NOTE: It is possible to use non thread-safe script engines with - * templating libraries not designed for concurrency, like Handlebars or React running on - * Nashorn, by setting the {@link #setSharedEngine sharedEngine} property to {@code false}. + * templating libraries not designed for concurrency by setting the + * {@link #setSharedEngine sharedEngine} property to {@code false}. * * @author Sebastien Deleuze * @since 5.0 @@ -143,7 +143,7 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig { * for each request, else the same instance will be reused. * This flag should be set to {@code false} for those using non thread-safe script * engines with templating libraries not designed for - * concurrency, like Handlebars or React running on Nashorn for example. + * concurrency. *

When this flag is set to {@code false}, the script engine must be specified using * {@link #setEngineName(String)}. Using {@link #setEngine(ScriptEngine)} is not * possible because multiple instances of the script engine need to be created for diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateView.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateView.java index 083d3e4b4de..b9e298db838 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateView.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateView.java @@ -58,10 +58,6 @@ import org.springframework.web.server.ServerWebExchange; * {@link ScriptTemplateConfig} bean in the web application context and using * it to obtain the configured properties. * - *

The Nashorn JavaScript engine requires Java 8+ and may require setting the - * {@code sharedEngine} property to {@code false} in order to run properly. See - * {@link ScriptTemplateConfigurer#setSharedEngine(Boolean)} for more details. - * * @author Sebastien Deleuze * @author Juergen Hoeller * @since 5.0 diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateConfigurer.java index 6d8c0019e56..f47bcd00e68 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateConfigurer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateConfigurer.java @@ -42,8 +42,8 @@ import org.jspecify.annotations.Nullable; * * *

NOTE: It is possible to use non thread-safe script engines with - * templating libraries not designed for concurrency, like Handlebars or React running on - * Nashorn, by setting the {@link #setSharedEngine sharedEngine} property to {@code false}. + * templating libraries not designed for concurrency by setting the + * {@link #setSharedEngine sharedEngine} property to {@code false}. * * @author Sebastien Deleuze * @since 4.2 @@ -144,7 +144,7 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig { * When set to {@code false}, use thread-local {@link ScriptEngine} instances instead * of one single shared instance. This flag should be set to {@code false} for those * using non thread-safe script engines with templating libraries not designed for - * concurrency, like Handlebars or React running on Nashorn for example. + * concurrency. *

When this flag is set to {@code false}, the script engine must be specified using * {@link #setEngineName(String)} or {@link #setEngineSupplier(Supplier)}. * Using {@link #setEngine(ScriptEngine)} is not possible because multiple instances diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java index 0ee1774e1d0..3f6cc6344b7 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java @@ -62,10 +62,6 @@ import org.springframework.web.servlet.view.AbstractUrlBasedView; * {@link ScriptTemplateConfig} bean in the web application context and using * it to obtain the configured properties. * - *

The Nashorn JavaScript engine requires Java 8+ and may require setting the - * {@code sharedEngine} property to {@code false} in order to run properly. See - * {@link ScriptTemplateConfigurer#setSharedEngine(Boolean)} for more details. - * * @author Sebastien Deleuze * @author Juergen Hoeller * @since 4.2 diff --git a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd index dcb56f5cc31..7b8da7ba4fc 100644 --- a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd +++ b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd @@ -1201,9 +1201,7 @@