diff --git a/spring-webflux/spring-webflux.gradle b/spring-webflux/spring-webflux.gradle index 1ff013b71c92ca5f3bb82dd0981196077e8ac7c5..25da0991cf21946defcb05e2de0d33466d8f4d12 100644 --- a/spring-webflux/spring-webflux.gradle +++ b/spring-webflux/spring-webflux.gradle @@ -55,10 +55,9 @@ dependencies { testCompile("org.eclipse.jetty:jetty-servlet") testCompile("org.eclipse.jetty:jetty-reactive-httpclient:1.0.3") testCompile("com.squareup.okhttp3:mockwebserver:3.14.2") - testCompile("org.jetbrains.kotlin:kotlin-script-runtime:${kotlinVersion}") testCompile(project(":spring-core-coroutines")) - testRuntime("org.jetbrains.kotlin:kotlin-script-util:${kotlinVersion}") - testRuntime("org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}") + testCompile("org.jetbrains.kotlin:kotlin-script-runtime:${kotlinVersion}") + testRuntime("org.jetbrains.kotlin:kotlin-scripting-jsr223-embeddable:${kotlinVersion}") testRuntime("org.jruby:jruby:9.2.7.0") testRuntime("org.python:jython-standalone:2.7.1") testRuntime("org.synchronoss.cloud:nio-multipart-parser:1.1.0") diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script/KotlinScriptTemplateTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script/KotlinScriptTemplateTests.java index 1cb9e1ebb344bdcdef0ec5d097e841c9294d29ea..252bb6e202b77c1af918ab62d3fa92b00c3a482a 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script/KotlinScriptTemplateTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script/KotlinScriptTemplateTests.java @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import org.junit.Ignore; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -41,7 +40,6 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class KotlinScriptTemplateTests { - @Ignore @Test public void renderTemplateWithFrenchLocale() throws Exception { Map model = new HashMap<>(); @@ -51,7 +49,6 @@ public class KotlinScriptTemplateTests { assertThat(response.getBodyAsString().block()).isEqualTo("\n

Bonjour Foo

\n"); } - @Ignore @Test public void renderTemplateWithEnglishLocale() throws Exception { Map model = new HashMap<>(); @@ -61,7 +58,6 @@ public class KotlinScriptTemplateTests { assertThat(response.getBodyAsString().block()).isEqualTo("\n

Hello Foo

\n"); } - @Ignore @Test public void renderTemplateWithoutRenderFunction() throws Exception { Map model = new HashMap<>(); diff --git a/spring-webflux/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory b/spring-webflux/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory deleted file mode 100644 index fa84d5e499706de3c3fe378506fe0334f610b21d..0000000000000000000000000000000000000000 --- a/spring-webflux/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory +++ /dev/null @@ -1 +0,0 @@ -org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory diff --git a/spring-webmvc/spring-webmvc.gradle b/spring-webmvc/spring-webmvc.gradle index db9de5769ac385283bcd64ca9ee94323ee531be6..0e9cf262f823d5d4b0a7b0393705ab05d031efc6 100644 --- a/spring-webmvc/spring-webmvc.gradle +++ b/spring-webmvc/spring-webmvc.gradle @@ -73,8 +73,7 @@ dependencies { testCompile("io.reactivex:rxjava-reactive-streams:${rxjavaAdapterVersion}") testCompile("io.reactivex.rxjava2:rxjava:${rxjava2Version}") testCompile("org.jetbrains.kotlin:kotlin-script-runtime:${kotlinVersion}") - testRuntime("org.jetbrains.kotlin:kotlin-script-util:${kotlinVersion}") - testRuntime("org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}") + testRuntime("org.jetbrains.kotlin:kotlin-scripting-jsr223-embeddable:${kotlinVersion}") testRuntime("org.jruby:jruby:9.2.7.0") testRuntime("org.python:jython-standalone:2.7.1") testRuntime("org.webjars:underscorejs:1.8.3") diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/KotlinScriptTemplateTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/KotlinScriptTemplateTests.java index 76d25f39dada7a61ebbf22076bafef90a6af8a37..b155eb11ba3c77878c5c0e0f88aca30944fbb4af 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/KotlinScriptTemplateTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/KotlinScriptTemplateTests.java @@ -22,7 +22,6 @@ import java.util.Map; import javax.servlet.ServletContext; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -56,7 +55,6 @@ public class KotlinScriptTemplateTests { this.servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.webAppContext); } - @Ignore @Test public void renderTemplateWithFrenchLocale() throws Exception { Map model = new HashMap<>(); @@ -66,7 +64,6 @@ public class KotlinScriptTemplateTests { assertThat(response.getContentAsString()).isEqualTo("\n

Bonjour Foo

\n"); } - @Ignore @Test public void renderTemplateWithEnglishLocale() throws Exception { Map model = new HashMap<>(); @@ -76,7 +73,6 @@ public class KotlinScriptTemplateTests { assertThat(response.getContentAsString()).isEqualTo("\n

Hello Foo

\n"); } - @Ignore @Test public void renderTemplateWithoutRenderFunction() throws Exception { Map model = new HashMap<>(); diff --git a/spring-webmvc/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory b/spring-webmvc/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory deleted file mode 100644 index fa84d5e499706de3c3fe378506fe0334f610b21d..0000000000000000000000000000000000000000 --- a/spring-webmvc/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory +++ /dev/null @@ -1 +0,0 @@ -org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory diff --git a/src/docs/asciidoc/languages/kotlin.adoc b/src/docs/asciidoc/languages/kotlin.adoc index 47468da686ce05e0c97884c318e55bac33672178..4c8de7ff6413e2bce307ac437181cf14770c854d 100644 --- a/src/docs/asciidoc/languages/kotlin.adoc +++ b/src/docs/asciidoc/languages/kotlin.adoc @@ -337,39 +337,49 @@ mockMvc.get("/person/{name}", "Lee") { === Kotlin Script Templates -As of version 4.3, Spring Framework provides a +Spring Framework provides a https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/view/script/ScriptTemplateView.html[`ScriptTemplateView`] -to render templates by using script engines. It supports -https://www.jcp.org/en/jsr/detail?id=223[JSR-223]. -Spring Framework 5 goes even further by extending this feature to WebFlux and supporting -https://jira.spring.io/browse/SPR-15064[i18n and nested templates]. +which supports https://www.jcp.org/en/jsr/detail?id=223[JSR-223] to render templates by using script engines. -Kotlin provides similar support and allows the rendering of Kotlin-based templates. See -https://github.com/spring-projects/spring-framework/commit/badde3a479a53e1dd0777dd1bd5b55cb1021cf9e[this commit] for details. +By leveraging `kotlin-script-runtime` and `scripting-jsr223-embeddable` dependencies, it +is possible to use such feature to render Kotlin-based templates with +https://github.com/Kotlin/kotlinx.html[kotlinx.html] DSL or Kotlin multiline interpolated `String`. -This enables some interesting use cases - such as writing type-safe templates by using -https://github.com/Kotlin/kotlinx.html[kotlinx.html] DSL or by a using Kotlin multiline `String` with interpolation. +`build.gradle.kts` +[source,kotlin,indent=0] +---- +dependencies { + compile("org.jetbrains.kotlin:kotlin-script-runtime:${kotlinVersion}") + runtime("org.jetbrains.kotlin:kotlin-scripting-jsr223-embeddable:${kotlinVersion}") +} +---- -This can let you write Kotlin templates with full autocompletion and -refactoring support in a supported IDE, as the following example shows: +Configuration is usually done with `ScriptTemplateConfigurer` and `ScriptTemplateViewResolver` +beans. + +`KotlinScriptConfiguration.kt` [source,kotlin,indent=0] ---- - import io.spring.demo.* +@Configuration +class KotlinScriptConfiguration { + + @Bean + fun kotlinScriptConfigurer() = ScriptTemplateConfigurer().apply { + engineName = "kotlin" + setScripts("scripts/render.kts") + renderFunction = "render" + isSharedEngine = false + } - """ - ${include("header")} -

${i18n("title")}

-
    - ${users.joinToLine{ "
  • ${i18n("user")} ${it.firstname} ${it.lastname}
  • " }} -
- ${include("footer")} - """ + @Bean + fun kotlinScriptViewResolver() = ScriptTemplateViewResolver().apply { + setPrefix("templates/") + setSuffix(".kts") + } +} ---- -WARNING: Kotlin Script Templates support is experimental and not compatible yet with Spring Boot fatjar mechanism, see related -https://youtrack.jetbrains.com/issue/KT-21443[KT-21443] and https://youtrack.jetbrains.com/issue/KT-27956[KT-27956] -issues. See the https://github.com/sdeleuze/kotlin-script-templating[kotlin-script-templating] example project for more details.