From 1af7575bded873006014792ac853ee492b0eb857 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 23 May 2012 18:42:10 -0400 Subject: [PATCH] Merge rather than add URI vars to data binding values As of Spring 3.1 URI variables can be used for data binding purposes in addition to request parameters (including query string and form params) In some cases URI variables and request params can overlap (e.g. form contains a child entity with an entityId as hidden form input while the URI contains the entityId of the parent entity) and that can lead to surprises if the application already exists. This change ensures that request parameters are used first and URI vars are added only if they don't overlap. Ideally however an application should not use the same uri variable name as the name of a request parameter where they don't refer to the same value. Issue: SPR-9349 Backport-Issue: SPR-9432 Backport-Commit: 4027b389031273955ffe343732eac50b8b5c0d25 --- .../ExtendedServletRequestDataBinder.java | 23 +++++++++++++++---- ...ExtendedServletRequestDataBinderTests.java | 12 +++++----- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinder.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinder.java index dd1cd4479da..51c021abd75 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinder.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -17,6 +17,8 @@ package org.springframework.web.servlet.mvc.method.annotation; import java.util.Map; +import java.util.Map.Entry; + import javax.servlet.ServletRequest; import org.springframework.beans.MutablePropertyValues; @@ -54,13 +56,24 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder { } /** - * Add URI template variables to the property values used for data binding. + * Merge URI variables into the property values to use for data binding. */ - @Override + @Override @SuppressWarnings("unchecked") protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) { String attr = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; - mpvs.addPropertyValues((Map) request.getAttribute(attr)); - } + Map uriVars = (Map) request.getAttribute(attr); + if (uriVars != null) { + for (Entry entry : uriVars.entrySet()) { + if (mpvs.contains(entry.getKey())) { + logger.warn("Skipping URI variable '" + entry.getKey() + + "' since the request contains a bind value with the same name."); + } + else { + mpvs.addPropertyValue(entry.getKey(), entry.getValue()); + } + } + } + } } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinderTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinderTests.java index f65e034af71..3412d6bd71d 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinderTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinderTests.java @@ -37,19 +37,19 @@ import org.springframework.web.servlet.HandlerMapping; public class ExtendedServletRequestDataBinderTests { private MockHttpServletRequest request; - + @Before public void setup() { this.request = new MockHttpServletRequest(); } - + @Test public void createBinder() throws Exception { Map uriTemplateVars = new HashMap(); uriTemplateVars.put("name", "nameValue"); uriTemplateVars.put("age", "25"); request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars); - + TestBean target = new TestBean(); WebDataBinder binder = new ExtendedServletRequestDataBinder(target, ""); ((ServletRequestDataBinder) binder).bind(request); @@ -61,18 +61,18 @@ public class ExtendedServletRequestDataBinderTests { @Test public void uriTemplateVarAndRequestParam() throws Exception { request.addParameter("age", "35"); - + Map uriTemplateVars = new HashMap(); uriTemplateVars.put("name", "nameValue"); uriTemplateVars.put("age", "25"); request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars); - + TestBean target = new TestBean(); WebDataBinder binder = new ExtendedServletRequestDataBinder(target, ""); ((ServletRequestDataBinder) binder).bind(request); assertEquals("nameValue", target.getName()); - assertEquals(25, target.getAge()); + assertEquals(35, target.getAge()); } @Test