From 4f60b98bca8f3e6a62e5e76c20b0bcfd97cc20e5 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 31 Jan 2014 22:39:20 +0100 Subject: [PATCH] Consistent iteration over actualValue in Velocity and FreeMarker macros This requires consistent exposure of an actualValue in BindStatus, even if no BindingResult available. Issue: SPR-10837 --- .../web/servlet/support/BindStatus.java | 10 ++++-- .../web/servlet/view/velocity/spring.vm | 36 ++++++++----------- .../view/freemarker/FreeMarkerMacroTests.java | 25 +++++++------ .../web/servlet/view/freemarker/test.ftl | 2 +- .../view/velocity/VelocityMacroTests.java | 18 +++++----- .../web/servlet/view/velocity/test.vm | 2 +- 6 files changed, 45 insertions(+), 48 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/BindStatus.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/BindStatus.java index 8d3f0ccb3a..4fd4058ef1 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/BindStatus.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/BindStatus.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -90,7 +90,7 @@ public class BindStatus { this.htmlEscape = htmlEscape; // determine name of the object and property - String beanName = null; + String beanName; int dotPos = path.indexOf('.'); if (dotPos == -1) { // property not set, only the object itself @@ -124,6 +124,9 @@ public class BindStatus { this.actualValue = this.bindingResult.getRawFieldValue(this.expression); this.editor = this.bindingResult.findEditor(this.expression, null); } + else { + this.actualValue = this.value; + } } } else { @@ -143,8 +146,9 @@ public class BindStatus { } if (this.expression != null && !"*".equals(this.expression) && !this.expression.endsWith("*")) { BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(target); - this.valueType = bw.getPropertyType(this.expression); this.value = bw.getPropertyValue(this.expression); + this.valueType = bw.getPropertyType(this.expression); + this.actualValue = this.value; } this.errorCodes = new String[0]; this.errorMessages = new String[0]; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/spring.vm b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/spring.vm index 7126ab3cd9..9c1af58841 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/spring.vm +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/spring.vm @@ -107,7 +107,7 @@ * * @param path the name of the field to bind to * @param attributes any additional attributes for the element (such as class - * or CSS styles or size + * or CSS styles or size) * *# #macro( springFormInput $path $attributes ) @@ -124,7 +124,7 @@ * * @param path the name of the field to bind to * @param attributes any additional attributes for the element (such as class - * or CSS styles or size + * or CSS styles or size) * *# #macro( springFormPasswordInput $path $attributes ) @@ -140,7 +140,7 @@ * * @param path the name of the field to bind to * @param attributes any additional attributes for the element (such as class - * or CSS styles or size + * or CSS styles or size) * *# #macro( springFormHiddenInput $path $attributes ) @@ -156,7 +156,7 @@ * * @param path the name of the field to bind to * @param attributes any additional attributes for the element (such as class - * or CSS styles or size + * or CSS styles or size) * *# #macro( springFormTextarea $path $attributes ) @@ -178,16 +178,14 @@ * @param path the name of the field to bind to * @param options a map (value=label) of all the available options * @param attributes any additional attributes for the element (such as class - * or CSS styles or size + * or CSS styles or size) *# #macro( springFormSingleSelect $path $options $attributes ) #springBind($path) @@ -202,17 +200,15 @@ * @param path the name of the field to bind to * @param options a map (value=label) of all the available options * @param attributes any additional attributes for the element (such as class - * or CSS styles or size + * or CSS styles or size) *# #macro( springFormMultiSelect $path $options $attributes ) #springBind($path) ' + * separate each option. Typically ' ' or '
'. * @param attributes any additional attributes for the element (such as class - * or CSS styles or size + * or CSS styles or size) *# #macro( springFormCheckboxes $path $options $separator $attributes ) #springBind($path) #foreach($option in $options.keySet()) ", getMacroOutput("FORM9")); @@ -272,8 +270,8 @@ public class FreeMarkerMacroTests { assertTrue("Wrong output: " + output, output.contains("")); } - private String getMacroOutput(String name) throws Exception { + private String getMacroOutput(String name) throws Exception { String macro = fetchMacro(name); assertNotNull(macro); @@ -296,6 +294,7 @@ public class FreeMarkerMacroTests { fred.setJedi(true); darren.setSpouse(fred); darren.setJedi(true); + darren.setStringArray(new String[] {"John", "Fred"}); request.setAttribute("command", darren); Map names = new HashMap(); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/test.ftl b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/test.ftl index b1e0156186..b6fb4caf4e 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/test.ftl +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/test.ftl @@ -61,7 +61,7 @@ FORM7 <@spring.formRadioButtons "command.name", nameOptionMap, " ", ""/> FORM8 -<@spring.formCheckboxes "command.spouses", nameOptionMap, " ", ""/> +<@spring.formCheckboxes "command.stringArray", nameOptionMap, " ", ""/> FORM9 <@spring.formPasswordInput "command.name", ""/> diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityMacroTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityMacroTests.java index 04c8497df3..d79048789f 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityMacroTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityMacroTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package org.springframework.web.servlet.view.velocity; import java.util.HashMap; import java.util.Map; - import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; @@ -27,10 +26,10 @@ import org.apache.velocity.Template; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; -import org.springframework.tests.sample.beans.TestBean; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.mock.web.test.MockServletContext; +import org.springframework.tests.sample.beans.TestBean; import org.springframework.util.StringUtils; import org.springframework.web.context.support.StaticWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; @@ -94,7 +93,7 @@ public class VelocityMacroTests extends TestCase { vv.setApplicationContext(wac); vv.setExposeSpringMacroHelpers(true); - Map model = new HashMap(); + Map model = new HashMap(); model.put("tb", new TestBean("juergen", 99)); vv.render(model, request, response); } @@ -112,7 +111,7 @@ public class VelocityMacroTests extends TestCase { vv.setApplicationContext(wac); vv.setExposeSpringMacroHelpers(true); - Map model = new HashMap(); + Map model = new HashMap(); model.put(VelocityView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE, helperTool); try { @@ -126,11 +125,11 @@ public class VelocityMacroTests extends TestCase { public void testAllMacros() throws Exception { DummyMacroRequestContext rc = new DummyMacroRequestContext(request); - Map msgMap = new HashMap(); + Map msgMap = new HashMap(); msgMap.put("hello", "Howdy"); msgMap.put("world", "Mundo"); rc.setMessageMap(msgMap); - Map themeMsgMap = new HashMap(); + Map themeMsgMap = new HashMap(); themeMsgMap.put("hello", "Howdy!"); themeMsgMap.put("world", "Mundo!"); rc.setThemeMessageMap(themeMsgMap); @@ -138,9 +137,10 @@ public class VelocityMacroTests extends TestCase { TestBean tb = new TestBean("Darren", 99); tb.setJedi(true); + tb.setStringArray(new String[] {"John", "Fred"}); request.setAttribute("command", tb); - HashMap names = new HashMap(); + Map names = new HashMap(); names.put("Darren", "Darren Davison"); names.put("John", "John Doe"); names.put("Fred", "Fred Bloggs"); @@ -149,7 +149,7 @@ public class VelocityMacroTests extends TestCase { vc.setPreferFileSystemAccess(false); VelocityEngine ve = vc.createVelocityEngine(); - Map model = new HashMap(); + Map model = new HashMap(); model.put("command", tb); model.put("springMacroRequestContext", rc); model.put("nameOptionMap", names); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/test.vm b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/test.vm index 401b74134a..e125e5efed 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/test.vm +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/test.vm @@ -45,7 +45,7 @@ FORM7 #springFormRadioButtons("command.name" $nameOptionMap " " "") FORM8 -#springFormCheckboxes("command.spouses" $nameOptionMap " " "") +#springFormCheckboxes("command.stringArray" $nameOptionMap " " "") FORM9 #springFormPasswordInput("command.name" "")