Remove JavaScript/Kotlin from ScriptEngine documentation

Closes gh-27919
This commit is contained in:
Sébastien Deleuze 2025-12-15 18:42:59 +01:00
parent 93bc022a46
commit d4e4250bb1
7 changed files with 33 additions and 267 deletions

View File

@ -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

View File

@ -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"]
----
<mvc:annotation-driven/>
@ -111,12 +91,22 @@ The following example shows the same arrangement in XML:
<mvc:script-template/>
</mvc:view-resolvers>
<mvc:script-template-configurer engine-name="nashorn" render-object="Mustache" render-function="render">
<mvc:script location="mustache.js"/>
<mvc:script-template-configurer engine-name="jython" render-function="render">
<mvc:script location="render.py"/>
</mvc:script-template-configurer>
----
======
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"]
----
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<p>{{body}}</p>
</body>
</html>
----
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],

View File

@ -42,8 +42,8 @@ import org.jspecify.annotations.Nullable;
* </pre>
*
* <p><b>NOTE:</b> 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.
* <p>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

View File

@ -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.
*
* <p>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

View File

@ -42,8 +42,8 @@ import org.jspecify.annotations.Nullable;
* </pre>
*
* <p><b>NOTE:</b> 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.
* <p>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

View File

@ -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.
*
* <p>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

View File

@ -1201,9 +1201,7 @@
<xsd:documentation><![CDATA[
When set to false, use thread-local ScriptEngine instances instead of one single shared
instance. This flag should be set to 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. In this case, Java 8u60 or greater is required due to
this bug: https://bugs.openjdk.java.net/browse/JDK-8076099.
with templating libraries not designed for concurrency.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>