Browse Source

Remove JavaScript/Kotlin from ScriptEngine documentation

Closes gh-27919
pull/36032/head
Sébastien Deleuze 2 months ago
parent
commit
d4e4250bb1
  1. 117
      framework-docs/modules/ROOT/pages/web/webflux-view.adoc
  2. 159
      framework-docs/modules/ROOT/pages/web/webmvc-view/mvc-script.adoc
  3. 6
      spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateConfigurer.java
  4. 4
      spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateView.java
  5. 6
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateConfigurer.java
  6. 4
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java
  7. 4
      spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd

117
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] [%header]
|=== |===
|Scripting Library |Scripting Engine |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.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://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 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: 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.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. * 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]] [[webflux-view-script-integrate]]
=== Script Templates === 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, 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 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] [tabs]
====== ======
@ -255,7 +241,6 @@ Java::
[source,java,indent=0,subs="verbatim,quotes"] [source,java,indent=0,subs="verbatim,quotes"]
---- ----
@Configuration @Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer { public class WebConfig implements WebFluxConfigurer {
@Override @Override
@ -266,9 +251,8 @@ Java::
@Bean @Bean
public ScriptTemplateConfigurer configurer() { public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn"); configurer.setEngineName("jython");
configurer.setScripts("mustache.js"); configurer.setScripts("render.py");
configurer.setRenderObject("Mustache");
configurer.setRenderFunction("render"); configurer.setRenderFunction("render");
return configurer; return configurer;
} }
@ -280,7 +264,6 @@ Kotlin::
[source,kotlin,indent=0,subs="verbatim,quotes"] [source,kotlin,indent=0,subs="verbatim,quotes"]
---- ----
@Configuration @Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer { class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) { override fun configureViewResolvers(registry: ViewResolverRegistry) {
@ -289,9 +272,8 @@ Kotlin::
@Bean @Bean
fun configurer() = ScriptTemplateConfigurer().apply { fun configurer() = ScriptTemplateConfigurer().apply {
engineName = "nashorn" engineName = "jython"
setScripts("mustache.js") setScripts("render.py")
renderObject = "Mustache"
renderFunction = "render" renderFunction = "render"
} }
} }
@ -305,94 +287,7 @@ The `render` function is called with the following parameters:
* `RenderingContext renderingContext`: The * `RenderingContext renderingContext`: The
{spring-framework-api}/web/servlet/view/script/RenderingContext.html[`RenderingContext`] {spring-framework-api}/web/servlet/view/script/RenderingContext.html[`RenderingContext`]
that gives access to the application context, the locale, the template loader, and the that gives access to the application context, the locale, the template loader, and the
URL (since 5.0) URL
`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);
}
----
Check out the Spring Framework unit tests, Check out the Spring Framework unit tests,
{spring-framework-code}/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script[Java], and {spring-framework-code}/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script[Java], and

159
framework-docs/modules/ROOT/pages/web/webmvc-view/mvc-script.adoc

@ -11,13 +11,8 @@ templating libraries on different script engines:
[%header] [%header]
|=== |===
|Scripting Library |Scripting Engine |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.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://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 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: 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.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. * 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]] [[mvc-view-script-integrate]]
== Script Templates == 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, 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 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] [tabs]
====== ======
@ -58,7 +43,6 @@ Java::
[source,java,indent=0,subs="verbatim,quotes"] [source,java,indent=0,subs="verbatim,quotes"]
---- ----
@Configuration @Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer { public class WebConfig implements WebMvcConfigurer {
@Override @Override
@ -69,9 +53,8 @@ Java::
@Bean @Bean
public ScriptTemplateConfigurer configurer() { public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn"); configurer.setEngineName("jython");
configurer.setScripts("mustache.js"); configurer.setScripts("render.py");
configurer.setRenderObject("Mustache");
configurer.setRenderFunction("render"); configurer.setRenderFunction("render");
return configurer; return configurer;
} }
@ -83,7 +66,6 @@ Kotlin::
[source,kotlin,indent=0,subs="verbatim,quotes"] [source,kotlin,indent=0,subs="verbatim,quotes"]
---- ----
@Configuration @Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer { class WebConfig : WebMvcConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) { override fun configureViewResolvers(registry: ViewResolverRegistry) {
@ -92,17 +74,15 @@ Kotlin::
@Bean @Bean
fun configurer() = ScriptTemplateConfigurer().apply { fun configurer() = ScriptTemplateConfigurer().apply {
engineName = "nashorn" engineName = "jython"
setScripts("mustache.js") setScripts("render.py")
renderObject = "Mustache"
renderFunction = "render" renderFunction = "render"
} }
} }
---- ----
======
The following example shows the same arrangement in XML:
XML::
+
[source,xml,indent=0,subs="verbatim,quotes"] [source,xml,indent=0,subs="verbatim,quotes"]
---- ----
<mvc:annotation-driven/> <mvc:annotation-driven/>
@ -111,12 +91,22 @@ The following example shows the same arrangement in XML:
<mvc:script-template/> <mvc:script-template/>
</mvc:view-resolvers> </mvc:view-resolvers>
<mvc:script-template-configurer engine-name="nashorn" render-object="Mustache" render-function="render"> <mvc:script-template-configurer engine-name="jython" render-function="render">
<mvc:script location="mustache.js"/> <mvc:script location="render.py"/>
</mvc:script-template-configurer> </mvc:script-template-configurer>
---- ----
======
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 would look no different for the Java and XML configurations, as the following example shows: The controller is used to populate the model attributes and specify the view name, as the following example shows:
[tabs] [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, 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/java/org/springframework/web/servlet/view/script[Java], and
{spring-framework-code}/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script[resources], {spring-framework-code}/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script[resources],

6
spring-webflux/src/main/java/org/springframework/web/reactive/result/view/script/ScriptTemplateConfigurer.java

@ -42,8 +42,8 @@ import org.jspecify.annotations.Nullable;
* </pre> * </pre>
* *
* <p><b>NOTE:</b> It is possible to use non thread-safe script engines with * <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 * templating libraries not designed for concurrency by setting the
* Nashorn, by setting the {@link #setSharedEngine sharedEngine} property to {@code false}. * {@link #setSharedEngine sharedEngine} property to {@code false}.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 5.0 * @since 5.0
@ -143,7 +143,7 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
* for each request, else the same instance will be reused. * 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 * This flag should be set to {@code false} for those using non thread-safe script
* engines with templating libraries not designed for * 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 * <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 * {@link #setEngineName(String)}. Using {@link #setEngine(ScriptEngine)} is not
* possible because multiple instances of the script engine need to be created for * possible because multiple instances of the script engine need to be created for

4
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 * {@link ScriptTemplateConfig} bean in the web application context and using
* it to obtain the configured properties. * 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 Sebastien Deleuze
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 5.0 * @since 5.0

6
spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateConfigurer.java

@ -42,8 +42,8 @@ import org.jspecify.annotations.Nullable;
* </pre> * </pre>
* *
* <p><b>NOTE:</b> It is possible to use non thread-safe script engines with * <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 * templating libraries not designed for concurrency by setting the
* Nashorn, by setting the {@link #setSharedEngine sharedEngine} property to {@code false}. * {@link #setSharedEngine sharedEngine} property to {@code false}.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 4.2 * @since 4.2
@ -144,7 +144,7 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
* When set to {@code false}, use thread-local {@link ScriptEngine} instances instead * 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 * 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 * 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 * <p>When this flag is set to {@code false}, the script engine must be specified using
* {@link #setEngineName(String)} or {@link #setEngineSupplier(Supplier)}. * {@link #setEngineName(String)} or {@link #setEngineSupplier(Supplier)}.
* Using {@link #setEngine(ScriptEngine)} is not possible because multiple instances * Using {@link #setEngine(ScriptEngine)} is not possible because multiple instances

4
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 * {@link ScriptTemplateConfig} bean in the web application context and using
* it to obtain the configured properties. * 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 Sebastien Deleuze
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 4.2 * @since 4.2

4
spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd

@ -1201,9 +1201,7 @@
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
When set to false, use thread-local ScriptEngine instances instead of one single shared 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 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 with templating libraries not designed for concurrency.
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.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>

Loading…
Cancel
Save