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 2a6a7fe349c..33c4d654e2e 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 @@ -157,10 +157,12 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig { /** * Set the render function name (mandatory). - * This function will be called with the following parameters: + * + *

This function will be called with the following parameters: *

    - *
  1. {@code template}: the view template content (String)
  2. - *
  3. {@code model}: the view model (Map)
  4. + *
  5. {@code String template}: the template content
  6. + *
  7. {@code Map model}: the view model
  8. + *
  9. {@code String url}: the template url (since 4.2.2)
  10. *
*/ public void setRenderFunction(String renderFunction) { 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 0086237cbe7..bd0e7093f9e 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 @@ -323,14 +323,15 @@ public class ScriptTemplateView extends AbstractUrlBasedView { try { ScriptEngine engine = getEngine(); Invocable invocable = (Invocable) engine; - String template = getTemplate(getUrl()); + String url = getUrl(); + String template = getTemplate(url); Object html; if (this.renderObject != null) { Object thiz = engine.eval(this.renderObject); - html = invocable.invokeMethod(thiz, this.renderFunction, template, model); + html = invocable.invokeMethod(thiz, this.renderFunction, template, model, url); } else { - html = invocable.invokeFunction(this.renderFunction, template, model); + html = invocable.invokeFunction(this.renderFunction, template, model, url); } response.getWriter().write(String.valueOf(html)); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/NashornScriptTemplateTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/NashornScriptTemplateTests.java index a777584dbf2..db33559d24a 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/NashornScriptTemplateTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/NashornScriptTemplateTests.java @@ -56,22 +56,31 @@ public class NashornScriptTemplateTests { Map model = new HashMap<>(); model.put("title", "Layout example"); model.put("body", "This is the body"); - MockHttpServletResponse response = renderViewWithModel("org/springframework/web/servlet/view/script/nashorn/template.html", model); + MockHttpServletResponse response = renderViewWithModel("org/springframework/web/servlet/view/script/nashorn/template.html", + model, ScriptTemplatingConfiguration.class); assertEquals("Layout example

This is the body

", response.getContentAsString()); } - private MockHttpServletResponse renderViewWithModel(String viewUrl, Map model) throws Exception { - ScriptTemplateView view = createViewWithUrl(viewUrl); + @Test // SPR-13453 + public void renderTemplateWithUrl() throws Exception { + MockHttpServletResponse response = renderViewWithModel("org/springframework/web/servlet/view/script/nashorn/template.html", + null, ScriptTemplatingWithUrlConfiguration.class); + assertEquals("Check url parameter

org/springframework/web/servlet/view/script/nashorn/template.html

", + response.getContentAsString()); + } + + private MockHttpServletResponse renderViewWithModel(String viewUrl, Map model, Class configuration) throws Exception { + ScriptTemplateView view = createViewWithUrl(viewUrl, configuration); MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletRequest request = new MockHttpServletRequest(); view.renderMergedOutputModel(model, request, response); return response; } - private ScriptTemplateView createViewWithUrl(String viewUrl) throws Exception { + private ScriptTemplateView createViewWithUrl(String viewUrl, Class configuration) throws Exception { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.register(ScriptTemplatingConfiguration.class); + ctx.register(configuration); ctx.refresh(); ScriptTemplateView view = new ScriptTemplateView(); @@ -94,4 +103,17 @@ public class NashornScriptTemplateTests { } } + @Configuration + static class ScriptTemplatingWithUrlConfiguration { + + @Bean + public ScriptTemplateConfigurer nashornConfigurer() { + ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); + configurer.setEngineName("nashorn"); + configurer.setScripts("org/springframework/web/servlet/view/script/nashorn/render.js"); + configurer.setRenderFunction("renderWithUrl"); + return configurer; + } + } + } diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/jruby/render.rb b/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/jruby/render.rb index 6825f3a9356..e5db6520d58 100644 --- a/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/jruby/render.rb +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/jruby/render.rb @@ -3,8 +3,7 @@ require 'ostruct' require 'java' # Renders an ERB template against a hashmap of variables. -# template should be a Java InputStream -def render(template, variables) +def render(template, variables, url) context = OpenStruct.new(variables).instance_eval do variables.each do |k, v| instance_variable_set(k, v) if k[0] == '@' diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/jython/render.py b/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/jython/render.py index f78ad68b8d0..07c73ae869b 100644 --- a/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/jython/render.py +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/jython/render.py @@ -1,5 +1,5 @@ from string import Template -def render(template, model): +def render(template, model, url): s = Template(template) return s.substitute(model) \ No newline at end of file diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/nashorn/render.js b/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/nashorn/render.js index bc4db9adcea..8b6a7120283 100644 --- a/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/nashorn/render.js +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/nashorn/render.js @@ -1,3 +1,7 @@ function render(template, model) { return template.replace("{{title}}", model.title).replace("{{body}}", model.body); -} \ No newline at end of file +} + +function renderWithUrl(template, model, url) { + return template.replace("{{title}}", "Check url parameter").replace("{{body}}", url); +} diff --git a/src/asciidoc/web-view.adoc b/src/asciidoc/web-view.adoc index 3c2b67ea257..ea2e2569e61 100644 --- a/src/asciidoc/web-view.adoc +++ b/src/asciidoc/web-view.adoc @@ -1589,8 +1589,9 @@ And the Mustache template is: The render function is called with the following parameters: -* template: the view template content (String) -* model: the view model (Map) +* `String template`: the template content +* `Map model`: the view model +* `String url`: the template url (since 4.2.2) `Mustache.render()` is natively compatible with this signature, so you can call it directly.