Skip to content

Commit f3b7e9f

Browse files
committed
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
1 parent ff02ad4 commit f3b7e9f

File tree

7 files changed

+46
-17
lines changed

7 files changed

+46
-17
lines changed

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,12 @@ public String getRenderObject() {
157157

158158
/**
159159
* Set the render function name (mandatory).
160-
* This function will be called with the following parameters:
160+
*
161+
* <p>This function will be called with the following parameters:
161162
* <ol>
162-
* <li>{@code template}: the view template content (String)</li>
163-
* <li>{@code model}: the view model (Map)</li>
163+
* <li>{@code String template}: the template content</li>
164+
* <li>{@code Map model}: the view model</li>
165+
* <li>{@code String url}: the template url (since 4.2.2)</li>
164166
* </ol>
165167
*/
166168
public void setRenderFunction(String renderFunction) {

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,15 @@ protected void renderMergedOutputModel(Map<String, Object> model, HttpServletReq
323323
try {
324324
ScriptEngine engine = getEngine();
325325
Invocable invocable = (Invocable) engine;
326-
String template = getTemplate(getUrl());
326+
String url = getUrl();
327+
String template = getTemplate(url);
327328
Object html;
328329
if (this.renderObject != null) {
329330
Object thiz = engine.eval(this.renderObject);
330-
html = invocable.invokeMethod(thiz, this.renderFunction, template, model);
331+
html = invocable.invokeMethod(thiz, this.renderFunction, template, model, url);
331332
}
332333
else {
333-
html = invocable.invokeFunction(this.renderFunction, template, model);
334+
html = invocable.invokeFunction(this.renderFunction, template, model, url);
334335
}
335336
response.getWriter().write(String.valueOf(html));
336337
}

spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/NashornScriptTemplateTests.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,31 @@ public void renderTemplate() throws Exception {
5656
Map<String, Object> model = new HashMap<>();
5757
model.put("title", "Layout example");
5858
model.put("body", "This is the body");
59-
MockHttpServletResponse response = renderViewWithModel("org/springframework/web/servlet/view/script/nashorn/template.html", model);
59+
MockHttpServletResponse response = renderViewWithModel("org/springframework/web/servlet/view/script/nashorn/template.html",
60+
model, ScriptTemplatingConfiguration.class);
6061
assertEquals("<html><head><title>Layout example</title></head><body><p>This is the body</p></body></html>",
6162
response.getContentAsString());
6263
}
6364

64-
private MockHttpServletResponse renderViewWithModel(String viewUrl, Map<String, Object> model) throws Exception {
65-
ScriptTemplateView view = createViewWithUrl(viewUrl);
65+
@Test // SPR-13453
66+
public void renderTemplateWithUrl() throws Exception {
67+
MockHttpServletResponse response = renderViewWithModel("org/springframework/web/servlet/view/script/nashorn/template.html",
68+
null, ScriptTemplatingWithUrlConfiguration.class);
69+
assertEquals("<html><head><title>Check url parameter</title></head><body><p>org/springframework/web/servlet/view/script/nashorn/template.html</p></body></html>",
70+
response.getContentAsString());
71+
}
72+
73+
private MockHttpServletResponse renderViewWithModel(String viewUrl, Map<String, Object> model, Class<?> configuration) throws Exception {
74+
ScriptTemplateView view = createViewWithUrl(viewUrl, configuration);
6675
MockHttpServletResponse response = new MockHttpServletResponse();
6776
MockHttpServletRequest request = new MockHttpServletRequest();
6877
view.renderMergedOutputModel(model, request, response);
6978
return response;
7079
}
7180

72-
private ScriptTemplateView createViewWithUrl(String viewUrl) throws Exception {
81+
private ScriptTemplateView createViewWithUrl(String viewUrl, Class<?> configuration) throws Exception {
7382
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
74-
ctx.register(ScriptTemplatingConfiguration.class);
83+
ctx.register(configuration);
7584
ctx.refresh();
7685

7786
ScriptTemplateView view = new ScriptTemplateView();
@@ -94,4 +103,17 @@ public ScriptTemplateConfigurer nashornConfigurer() {
94103
}
95104
}
96105

106+
@Configuration
107+
static class ScriptTemplatingWithUrlConfiguration {
108+
109+
@Bean
110+
public ScriptTemplateConfigurer nashornConfigurer() {
111+
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
112+
configurer.setEngineName("nashorn");
113+
configurer.setScripts("org/springframework/web/servlet/view/script/nashorn/render.js");
114+
configurer.setRenderFunction("renderWithUrl");
115+
return configurer;
116+
}
117+
}
118+
97119
}

spring-webmvc/src/test/resources/org/springframework/web/servlet/view/script/jruby/render.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
require 'java'
44

55
# Renders an ERB template against a hashmap of variables.
6-
# template should be a Java InputStream
7-
def render(template, variables)
6+
def render(template, variables, url)
87
context = OpenStruct.new(variables).instance_eval do
98
variables.each do |k, v|
109
instance_variable_set(k, v) if k[0] == '@'
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from string import Template
22

3-
def render(template, model):
3+
def render(template, model, url):
44
s = Template(template)
55
return s.substitute(model)
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
function render(template, model) {
22
return template.replace("{{title}}", model.title).replace("{{body}}", model.body);
3-
}
3+
}
4+
5+
function renderWithUrl(template, model, url) {
6+
return template.replace("{{title}}", "Check url parameter").replace("{{body}}", url);
7+
}

src/asciidoc/web-view.adoc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,8 +1589,9 @@ And the Mustache template is:
15891589

15901590
The render function is called with the following parameters:
15911591

1592-
* template: the view template content (String)
1593-
* model: the view model (Map)
1592+
* `String template`: the template content
1593+
* `Map model`: the view model
1594+
* `String url`: the template url (since 4.2.2)
15941595

15951596
`Mustache.render()` is natively compatible with this signature, so you can call it directly.
15961597

0 commit comments

Comments
 (0)