From 497415f9bbae7eda4855d11893666d8923733090 Mon Sep 17 00:00:00 2001 From: jhan0121 Date: Wed, 20 May 2026 18:40:18 +0900 Subject: [PATCH] Deprecate setDisallowedFields in DataBinder for removal Deprecate `setDisallowedFields()` and `getDisallowedFields()` in favor of the safer `setAllowedFields()` as an explicit opt-in. Closes gh-36802 Signed-off-by: Juhwan Lee --- .../ROOT/partials/web/web-data-binding-model-design.adoc | 4 ++-- .../java/org/springframework/validation/DataBinder.java | 5 ++++- .../org/springframework/validation/DataBinderTests.java | 4 ++++ .../web/bind/support/WebRequestDataBinderTests.java | 3 +++ .../annotation/InitBinderDataBinderFactoryTests.java | 8 ++++++++ .../method/annotation/InitBinderBindingContextTests.java | 8 ++++++++ 6 files changed, 29 insertions(+), 3 deletions(-) diff --git a/framework-docs/modules/ROOT/partials/web/web-data-binding-model-design.adoc b/framework-docs/modules/ROOT/partials/web/web-data-binding-model-design.adoc index 09476b10bb76..059126a36917 100644 --- a/framework-docs/modules/ROOT/partials/web/web-data-binding-model-design.adoc +++ b/framework-docs/modules/ROOT/partials/web/web-data-binding-model-design.adoc @@ -28,8 +28,8 @@ For example: } ---- -NOTE: It is also possible to configure `disallowedFields`, but that's fragile, and -due to be https://github.com/spring-projects/spring-framework/issues/36802[deprecated] in Spring Framework 7.1. +NOTE: It is also possible to configure `disallowedFields`, but that's fragile and +https://github.com/spring-projects/spring-framework/issues/36802[deprecated as of Spring Framework 7.1]. It is easy to overlook fields or introduce additional fields over time that should also be excluded. By default, `DataBinder` applies both constructor and setter binding. diff --git a/spring-context/src/main/java/org/springframework/validation/DataBinder.java b/spring-context/src/main/java/org/springframework/validation/DataBinder.java index bd804bfe6479..e89704c21568 100644 --- a/spring-context/src/main/java/org/springframework/validation/DataBinder.java +++ b/spring-context/src/main/java/org/springframework/validation/DataBinder.java @@ -508,7 +508,6 @@ public boolean isIgnoreInvalidFields() { * account. *

More sophisticated matching can be implemented by overriding the * {@link #isAllowed} method. - *

Alternatively, specify a list of disallowed field patterns. *

Used for binding to fields with {@link #bind(PropertyValues)}, and not * applicable to constructor binding via {@link #construct}, * which uses only the values it needs. @@ -551,7 +550,9 @@ public void setAllowedFields(String @Nullable ... allowedFields) { * @param disallowedFields array of disallowed field patterns * @see #setAllowedFields * @see #isAllowed(String) + * @deprecated as of 7.1, in favor of {@link #setAllowedFields}. */ + @Deprecated(since = "7.1", forRemoval = true) public void setDisallowedFields(String @Nullable ... disallowedFields) { if (disallowedFields == null) { this.disallowedFields = null; @@ -569,7 +570,9 @@ public void setDisallowedFields(String @Nullable ... disallowedFields) { * Return the field patterns that should not be allowed for binding. * @return array of disallowed field patterns * @see #setDisallowedFields(String...) + * @deprecated as of 7.1, in favor of {@link #getAllowedFields()}. */ + @Deprecated(since = "7.1", forRemoval = true) public String @Nullable [] getDisallowedFields() { return this.disallowedFields; } diff --git a/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java b/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java index 54160ad3e6f6..bb821e3f4fc6 100644 --- a/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java +++ b/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java @@ -715,6 +715,7 @@ void bindingWithAllowedFields() throws BindException { } @Test + @SuppressWarnings("removal") void bindingWithDisallowedFields() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod); @@ -734,6 +735,7 @@ void bindingWithDisallowedFields() throws BindException { } @Test + @SuppressWarnings("removal") void bindingWithAllowedAndDisallowedFields() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod); @@ -752,6 +754,7 @@ void bindingWithAllowedAndDisallowedFields() throws BindException { } @Test + @SuppressWarnings("removal") void bindingWithOverlappingAllowedAndDisallowedFields() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod); @@ -797,6 +800,7 @@ void bindingWithAllowedFieldsUsingAsterisks() throws BindException { } @Test + @SuppressWarnings("removal") void bindingWithAllowedAndDisallowedMapFields() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod); diff --git a/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java b/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java index fb3a6ef3c3d9..782db2b5b2e2 100644 --- a/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java +++ b/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java @@ -329,6 +329,7 @@ void shouldNotTriggerBindingWhenFieldIsNotAllowed() { } @Test + @SuppressWarnings("removal") void shouldNotTriggerBindingWhenFieldIsDisallowed() { TestBean tb = new TestBean(); @@ -363,6 +364,7 @@ void shouldNotTriggerBindingWhenFieldIsNotAllowedWithEmptyArrayIndex() { @ParameterizedTest @ValueSource(strings = { "stringArray*", "stringArray[]" }) + @SuppressWarnings("removal") void shouldNotTriggerBindingWhenFieldIsDisallowedWithEmptyArrayIndex(String disallowedField) { TestBean tb = new TestBean(); @@ -398,6 +400,7 @@ void shouldNotTriggerAutoGrowWhenFieldIsNotAllowed() { @ParameterizedTest @ValueSource(strings = { "someMap*", "someMap[*]", "someMap[key1]" }) + @SuppressWarnings("removal") void shouldNotTriggerAutoGrowWhenFieldIsDisallowed(String disallowedField) { TestBean tb = new TestBean(); tb.setSomeMap(null); diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/InitBinderDataBinderFactoryTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/InitBinderDataBinderFactoryTests.java index 71c99e550b88..5da5be63455a 100644 --- a/spring-web/src/test/java/org/springframework/web/method/annotation/InitBinderDataBinderFactoryTests.java +++ b/spring-web/src/test/java/org/springframework/web/method/annotation/InitBinderDataBinderFactoryTests.java @@ -56,6 +56,7 @@ class InitBinderDataBinderFactoryTests { @Test + @SuppressWarnings("removal") void createBinder() throws Exception { WebDataBinderFactory factory = createFactory("initBinder", WebDataBinder.class); WebDataBinder dataBinder = factory.createBinder(this.webRequest, null, null); @@ -76,6 +77,7 @@ void createBinderWithGlobalInitialization() throws Exception { } @Test + @SuppressWarnings("removal") void createBinderWithAttrName() throws Exception { WebDataBinderFactory factory = createFactory("initBinderWithAttributeName", WebDataBinder.class); WebDataBinder dataBinder = factory.createBinder(this.webRequest, null, "foo"); @@ -85,6 +87,7 @@ void createBinderWithAttrName() throws Exception { } @Test + @SuppressWarnings("removal") void createBinderWithAttrNameNoMatch() throws Exception { WebDataBinderFactory factory = createFactory("initBinderWithAttributeName", WebDataBinder.class); WebDataBinder dataBinder = factory.createBinder(this.webRequest, null, "invalidName"); @@ -93,6 +96,7 @@ void createBinderWithAttrNameNoMatch() throws Exception { } @Test + @SuppressWarnings("removal") void createBinderNullAttrName() throws Exception { WebDataBinderFactory factory = createFactory("initBinderWithAttributeName", WebDataBinder.class); WebDataBinder dataBinder = factory.createBinder(this.webRequest, null, null); @@ -108,6 +112,7 @@ void returnValueNotExpected() throws Exception { } @Test + @SuppressWarnings("removal") void createBinderTypeConversion() throws Exception { this.webRequest.getNativeRequest(MockHttpServletRequest.class).setParameter("requestParam", "22"); this.argumentResolvers.addResolver(new RequestParamMethodArgumentResolver(null, false)); @@ -138,11 +143,13 @@ private WebDataBinderFactory createFactory(String methodName, Class... parame private static class InitBinderHandler { @InitBinder + @SuppressWarnings("removal") public void initBinder(WebDataBinder dataBinder) { dataBinder.setDisallowedFields("id"); } @InitBinder(value="foo") + @SuppressWarnings("removal") public void initBinderWithAttributeName(WebDataBinder dataBinder) { dataBinder.setDisallowedFields("id"); } @@ -153,6 +160,7 @@ public String initBinderReturnValue(WebDataBinder dataBinder) { } @InitBinder + @SuppressWarnings("removal") public void initBinderTypeConversion(WebDataBinder dataBinder, @RequestParam int requestParam) { dataBinder.setDisallowedFields("requestParam-" + requestParam); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/InitBinderBindingContextTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/InitBinderBindingContextTests.java index 70f1f7c03825..4e1d4259aa28 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/InitBinderBindingContextTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/InitBinderBindingContextTests.java @@ -62,6 +62,7 @@ class InitBinderBindingContextTests { @Test + @SuppressWarnings("removal") void createBinder() throws Exception { MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); BindingContext context = createBindingContext("initBinder", WebDataBinder.class); @@ -84,6 +85,7 @@ void createBinderWithGlobalInitialization() throws Exception { } @Test + @SuppressWarnings("removal") void createBinderWithAttrName() throws Exception { MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); BindingContext context = createBindingContext("initBinderWithAttributeName", WebDataBinder.class); @@ -94,6 +96,7 @@ void createBinderWithAttrName() throws Exception { } @Test + @SuppressWarnings("removal") void createBinderWithAttrNameNoMatch() throws Exception { MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); BindingContext context = createBindingContext("initBinderWithAttributeName", WebDataBinder.class); @@ -103,6 +106,7 @@ void createBinderWithAttrNameNoMatch() throws Exception { } @Test + @SuppressWarnings("removal") void createBinderNullAttrName() throws Exception { MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); BindingContext context = createBindingContext("initBinderWithAttributeName", WebDataBinder.class); @@ -119,6 +123,7 @@ void returnValueNotExpected() throws Exception { } @Test + @SuppressWarnings("removal") void createBinderTypeConversion() throws Exception { MockServerHttpRequest request = MockServerHttpRequest.get("/path?requestParam=22").build(); MockServerWebExchange exchange = MockServerWebExchange.from(request); @@ -260,11 +265,13 @@ private BindingContext createBindingContext(String methodName, Class... param private static class InitBinderHandler { @InitBinder + @SuppressWarnings("removal") public void initBinder(WebDataBinder dataBinder) { dataBinder.setDisallowedFields("id"); } @InitBinder(value="foo") + @SuppressWarnings("removal") public void initBinderWithAttributeName(WebDataBinder dataBinder) { dataBinder.setDisallowedFields("id"); } @@ -275,6 +282,7 @@ public String initBinderReturnValue(WebDataBinder dataBinder) { } @InitBinder + @SuppressWarnings("removal") public void initBinderTypeConversion(WebDataBinder dataBinder, @RequestParam int requestParam) { dataBinder.setDisallowedFields("requestParam-" + requestParam); }