From f3b7e9ff2d42af7fd507ed817cc413f0a1523fe4 Mon Sep 17 00:00:00 2001 From: Sebastien Deleuze Date: Wed, 9 Sep 2015 18:05:04 +0200 Subject: [PATCH] Expose view url to render function in ScriptTemplateView After this change, with Nashorn it is possible to use either render(template, model) or render(template, model, url). With JRuby or Jython, specifying the 3 parameters is mandatory. Issue: SPR-13453 --- .../view/script/ScriptTemplateConfigurer.java | 8 +++-- .../view/script/ScriptTemplateView.java | 7 ++-- .../script/NashornScriptTemplateTests.java | 32 ++++++++++++++++--- .../web/servlet/view/script/jruby/render.rb | 3 +- .../web/servlet/view/script/jython/render.py | 2 +- .../web/servlet/view/script/nashorn/render.js | 6 +++- src/asciidoc/web-view.adoc | 5 +-- 7 files changed, 46 insertions(+), 17 deletions(-) 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.