From 764eedef78f59901d2878e185e439e88ea1823ce Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Tue, 16 Jul 2024 14:46:48 -0400
Subject: [PATCH 01/33] Start work on moving to Spring 6+ and Spring Boot 3+
---
.editorconfig | 4 +
.../buildlogic/java-conventions.gradle.kts | 21 +--
docs/build.gradle.kts | 2 +-
.../WebMvcDocsJavaConfigIntegrationTest.java | 3 +-
.../WebMvcDocsXmlConfigIntegrationTest.java | 3 +-
integration-tests/build.gradle.kts | 10 +-
.../test/web/bind/CookieParameterBean.java | 3 +-
.../web/bind/CookieParameterController.java | 3 +-
.../test/web/bind/FormParameterBean.java | 4 +-
.../web/bind/FormParameterController.java | 4 +-
.../test/web/bind/HeaderParameterBean.java | 2 +-
.../web/bind/HeaderParameterController.java | 2 +-
.../test/web/bind/PathParameterBean.java | 2 +-
.../web/bind/PathParameterController.java | 2 +-
.../spring/test/web/bind/RequestBodyBean.java | 3 +-
.../test/web/bind/RequestBodyController.java | 2 +-
.../test/web/bind/RequestContextBean.java | 2 +-
.../test/web/bind/RequestParameterBean.java | 4 +-
.../web/bind/RequestParameterController.java | 4 +-
.../test/web/bind/SessionParameterBean.java | 3 +-
.../web/bind/SessionParameterController.java | 3 +-
.../test/CookieParameterIntegrationTest.java | 3 +-
.../DirectFieldAccessIntegrationTest.java | 3 +-
libs.versions.toml | 16 ++-
.../build.gradle.kts | 2 +-
.../web/bind/annotation/CookieParameter.java | 2 +-
.../web/bind/annotation/RequestContext.java | 4 +-
.../web/bind/support/MapValueResolver.java | 20 +++
.../spring/web/bind/support/package-info.java | 4 +
.../build.gradle.kts | 2 +-
.../BeanParameterMethodArgumentResolver.java | 40 ++----
...anParameterMethodArgumentResolverTest.java | 2 +-
.../build.gradle.kts | 4 +-
.../BeanParameterMethodArgumentResolver.java | 56 +++-----
...ookieParameterRequestPropertyResolver.java | 7 +-
...RequestContextRequestPropertyResolver.java | 8 +-
...stParameterMapRequestPropertyResolver.java | 6 +-
...questParameterRequestPropertyResolver.java | 3 +-
...anParameterMethodArgumentResolverTest.java | 124 ++----------------
.../servlet/mvc/bind/MockWebDataBinder.java | 75 +++++++++++
.../mvc/bind/MockWebDataBinderFactory.java | 55 ++++++++
...eParameterRequestPropertyResolverTest.java | 4 +-
...rowingMockMultipartHttpServletRequest.java | 4 +-
...rameterMapRequestPropertyResolverTest.java | 4 +-
...mParameterRequestPropertyResolverTest.java | 2 +-
...estContextRequestPropertyResolverTest.java | 6 +-
...rameterMapRequestPropertyResolverTest.java | 2 +-
...tParameterRequestPropertyResolverTest.java | 2 +-
48 files changed, 272 insertions(+), 274 deletions(-)
create mode 100644 spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java
create mode 100644 spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/package-info.java
create mode 100644 spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java
create mode 100644 spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java
diff --git a/.editorconfig b/.editorconfig
index 31325f8..83142a7 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -9,6 +9,10 @@ indent_size = 4
indent_style = space
insert_final_newline = true
+[*.java]
+ij_java_class_count_to_use_import_on_demand = 999
+ij_java_names_count_to_use_import_on_demand = 999
+
[*.{bat,cmd}]
end_of_line = crlf
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
index fbc4ecd..c928c35 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
@@ -13,10 +13,6 @@ java {
}
}
-tasks.named("compileJava").configure {
- options.release.set(8)
-}
-
testing {
suites {
named("test").configure {
@@ -34,25 +30,20 @@ tasks.named("jar").configure {
}
}
-val springVersion: String = versionCatalog.findVersion("spring").orElseThrow().toString()
-val springBootVersion: String = versionCatalog.findVersion("springBoot").orElseThrow().toString()
-
val javadocLinks = arrayOf(
- "https://docs.oracle.com/javase/8/docs/api/",
- "https://docs.oracle.com/javaee/7/api/",
- "https://docs.spring.io/spring-framework/docs/$springVersion/javadoc-api/",
- "https://docs.spring.io/spring-boot/docs/$springBootVersion/api/"
+ "https://docs.oracle.com/en/java/javase/17/docs/api",
+ "https://jakarta.ee/specifications/platform/11/apidocs/",
+ "https://docs.spring.io/spring-framework/docs/current/javadoc-api/",
+ "https://docs.spring.io/spring-boot/api/java/"
)
tasks.named("javadoc").configure {
options {
this as StandardJavadocDocletOptions
- source = "8"
+ source = "17"
links(*javadocLinks)
addStringOption("Xdoclint:none", "-quiet")
- if (java.toolchain.languageVersion.get().asInt() >= 9) {
- addBooleanOption("html5", true)
- }
+ addBooleanOption("html5", true)
}
}
diff --git a/docs/build.gradle.kts b/docs/build.gradle.kts
index 82b5cb0..15451ce 100644
--- a/docs/build.gradle.kts
+++ b/docs/build.gradle.kts
@@ -12,7 +12,7 @@ configurations {
dependencies {
implementation(project(":spring-webmvc-annotated-data-binder"))
implementation(project(":spring-webflux-annotated-data-binder"))
- implementation(libs.javaxServletApi) // Version defined in Spring BOM file
+ implementation(libs.jakartaServletApi) // Version defined in Spring BOM file
add("asciidoctorExt", libs.springAsciidoctorExtBlockSwitch)
diff --git a/docs/src/test/java/com/mattbertolini/spring/web/bind/docs/webmvc/WebMvcDocsJavaConfigIntegrationTest.java b/docs/src/test/java/com/mattbertolini/spring/web/bind/docs/webmvc/WebMvcDocsJavaConfigIntegrationTest.java
index 3db99b9..df6f140 100644
--- a/docs/src/test/java/com/mattbertolini/spring/web/bind/docs/webmvc/WebMvcDocsJavaConfigIntegrationTest.java
+++ b/docs/src/test/java/com/mattbertolini/spring/web/bind/docs/webmvc/WebMvcDocsJavaConfigIntegrationTest.java
@@ -16,6 +16,7 @@
package com.mattbertolini.spring.web.bind.docs.webmvc;
+import jakarta.servlet.http.Cookie;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
@@ -24,8 +25,6 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-import javax.servlet.http.Cookie;
-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
diff --git a/docs/src/test/java/com/mattbertolini/spring/web/bind/docs/webmvc/WebMvcDocsXmlConfigIntegrationTest.java b/docs/src/test/java/com/mattbertolini/spring/web/bind/docs/webmvc/WebMvcDocsXmlConfigIntegrationTest.java
index 8b85535..e1c91ca 100644
--- a/docs/src/test/java/com/mattbertolini/spring/web/bind/docs/webmvc/WebMvcDocsXmlConfigIntegrationTest.java
+++ b/docs/src/test/java/com/mattbertolini/spring/web/bind/docs/webmvc/WebMvcDocsXmlConfigIntegrationTest.java
@@ -16,6 +16,7 @@
package com.mattbertolini.spring.web.bind.docs.webmvc;
+import jakarta.servlet.http.Cookie;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
@@ -24,8 +25,6 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-import javax.servlet.http.Cookie;
-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
diff --git a/integration-tests/build.gradle.kts b/integration-tests/build.gradle.kts
index 5ee51e9..faeea26 100644
--- a/integration-tests/build.gradle.kts
+++ b/integration-tests/build.gradle.kts
@@ -5,10 +5,12 @@ plugins {
dependencies {
implementation(project(":spring-webmvc-annotated-data-binder"))
implementation(project(":spring-webflux-annotated-data-binder"))
- implementation(libs.javaxServletApi)
+ implementation(libs.jakartaServletApi)
implementation(libs.hibernateValidator)
- implementation(libs.glassfishJavaxEl) // Needed by Hibernate Validator
+ implementation(libs.glassfishJakartaEl) // Needed by Hibernate Validator
implementation(libs.jacksonDatabind)
+ implementation(libs.jakartaWebsocketApi)
+ implementation(libs.jakartaWebsocketClientApi)
testImplementation(libs.junitJupiterApi)
testImplementation(libs.assertJCore)
@@ -16,10 +18,6 @@ dependencies {
testCompileOnly(libs.hamcrest) // Needed for Spring mock MVC matchers
}
-tasks.named("compileJava").configure {
- options.release.set(17)
-}
-
tasks.named("jacocoTestReport").configure {
reports {
html.required.set(false)
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/CookieParameterBean.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/CookieParameterBean.java
index 34c9f4f..16fb669 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/CookieParameterBean.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/CookieParameterBean.java
@@ -18,8 +18,7 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import com.mattbertolini.spring.web.bind.annotation.CookieParameter;
-
-import javax.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotEmpty;
public class CookieParameterBean {
@CookieParameter("annotated_field")
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/CookieParameterController.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/CookieParameterController.java
index 572997f..bc68286 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/CookieParameterController.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/CookieParameterController.java
@@ -18,13 +18,12 @@
import com.mattbertolini.spring.test.web.bind.records.CookieParameterRecord;
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
+import jakarta.validation.Valid;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
-import javax.validation.Valid;
-
@RestController
public class CookieParameterController {
@GetMapping(value = "/annotatedField", produces = MediaType.TEXT_PLAIN_VALUE)
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/FormParameterBean.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/FormParameterBean.java
index 686f479..9989e41 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/FormParameterBean.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/FormParameterBean.java
@@ -18,12 +18,12 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import com.mattbertolini.spring.web.bind.annotation.FormParameter;
+import jakarta.servlet.http.Part;
+import jakarta.validation.constraints.NotEmpty;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.http.Part;
-import javax.validation.constraints.NotEmpty;
import java.util.Map;
public class FormParameterBean {
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/FormParameterController.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/FormParameterController.java
index da5d072..c4141fc 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/FormParameterController.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/FormParameterController.java
@@ -18,6 +18,8 @@
import com.mattbertolini.spring.test.web.bind.records.FormParameterRecord;
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
+import jakarta.servlet.http.Part;
+import jakarta.validation.Valid;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.MediaType;
@@ -30,8 +32,6 @@
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;
-import javax.servlet.http.Part;
-import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/HeaderParameterBean.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/HeaderParameterBean.java
index 30aa8e0..e2fea6c 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/HeaderParameterBean.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/HeaderParameterBean.java
@@ -18,10 +18,10 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import com.mattbertolini.spring.web.bind.annotation.HeaderParameter;
+import jakarta.validation.constraints.NotEmpty;
import org.springframework.http.HttpHeaders;
import org.springframework.util.MultiValueMap;
-import javax.validation.constraints.NotEmpty;
import java.util.Map;
public class HeaderParameterBean {
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/HeaderParameterController.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/HeaderParameterController.java
index 4ce66a5..09f708b 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/HeaderParameterController.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/HeaderParameterController.java
@@ -18,6 +18,7 @@
import com.mattbertolini.spring.test.web.bind.records.HeaderParameterRecord;
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
+import jakarta.validation.Valid;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
@@ -25,7 +26,6 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
-import javax.validation.Valid;
import java.util.Map;
@RestController
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterBean.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterBean.java
index 8c33df5..d035c99 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterBean.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterBean.java
@@ -18,8 +18,8 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import com.mattbertolini.spring.web.bind.annotation.PathParameter;
+import jakarta.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotEmpty;
import java.util.Map;
public class PathParameterBean {
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterController.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterController.java
index 473bde8..0d4c3cb 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterController.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterController.java
@@ -18,12 +18,12 @@
import com.mattbertolini.spring.test.web.bind.records.PathParameterRecord;
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
+import jakarta.validation.Valid;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
-import javax.validation.Valid;
import java.util.Map;
@SuppressWarnings("MVCPathVariableInspection")
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestBodyBean.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestBodyBean.java
index 9d59242..1cf0f01 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestBodyBean.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestBodyBean.java
@@ -18,12 +18,11 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import com.mattbertolini.spring.web.bind.annotation.RequestBody;
+import jakarta.validation.constraints.NotNull;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.MultiValueMap;
import reactor.core.publisher.Flux;
-import javax.validation.constraints.NotNull;
-
public class RequestBodyBean {
@SuppressWarnings("unused")
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestBodyController.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestBodyController.java
index 5b53c11..8c3dffc 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestBodyController.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestBodyController.java
@@ -18,6 +18,7 @@
import com.mattbertolini.spring.test.web.bind.records.RequestBodyRecord;
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
+import jakarta.validation.Valid;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.Assert;
@@ -27,7 +28,6 @@
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
-import javax.validation.Valid;
import java.util.concurrent.atomic.AtomicInteger;
@RestController
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestContextBean.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestContextBean.java
index d23a638..b2c6fec 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestContextBean.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestContextBean.java
@@ -17,12 +17,12 @@
package com.mattbertolini.spring.test.web.bind;
import com.mattbertolini.spring.web.bind.annotation.RequestContext;
+import jakarta.servlet.http.HttpSession;
import org.springframework.http.HttpMethod;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebSession;
-import javax.servlet.http.HttpSession;
import java.time.ZoneId;
import java.util.Locale;
import java.util.TimeZone;
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestParameterBean.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestParameterBean.java
index 73f239e..066908c 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestParameterBean.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestParameterBean.java
@@ -18,11 +18,11 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
+import jakarta.servlet.http.Part;
+import jakarta.validation.constraints.NotEmpty;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.http.Part;
-import javax.validation.constraints.NotEmpty;
import java.util.Map;
public class RequestParameterBean {
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestParameterController.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestParameterController.java
index 7edb153..dc206be 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestParameterController.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/RequestParameterController.java
@@ -18,6 +18,8 @@
import com.mattbertolini.spring.test.web.bind.records.RequestParameterRecord;
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
+import jakarta.servlet.http.Part;
+import jakarta.validation.Valid;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
@@ -27,8 +29,6 @@
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.http.Part;
-import javax.validation.Valid;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/SessionParameterBean.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/SessionParameterBean.java
index 01b7f1b..18c0ef6 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/SessionParameterBean.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/SessionParameterBean.java
@@ -18,8 +18,7 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import com.mattbertolini.spring.web.bind.annotation.SessionParameter;
-
-import javax.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotEmpty;
public class SessionParameterBean {
@SessionParameter("annotated_field")
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/SessionParameterController.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/SessionParameterController.java
index 14d57ff..858bddf 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/SessionParameterController.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/SessionParameterController.java
@@ -18,13 +18,12 @@
import com.mattbertolini.spring.test.web.bind.records.SessionParameterRecord;
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
+import jakarta.validation.Valid;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
-import javax.validation.Valid;
-
@RestController
public class SessionParameterController {
@GetMapping(value = "/annotatedField", produces = MediaType.TEXT_PLAIN_VALUE)
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/web/servlet/mvc/test/CookieParameterIntegrationTest.java b/integration-tests/src/test/java/com/mattbertolini/spring/web/servlet/mvc/test/CookieParameterIntegrationTest.java
index 17aac83..0ae09de 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/web/servlet/mvc/test/CookieParameterIntegrationTest.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/web/servlet/mvc/test/CookieParameterIntegrationTest.java
@@ -18,6 +18,7 @@
import com.mattbertolini.spring.test.web.bind.CookieParameterController;
import com.mattbertolini.spring.web.servlet.mvc.bind.config.BinderConfiguration;
+import jakarta.servlet.http.Cookie;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Bean;
@@ -30,8 +31,6 @@
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import javax.servlet.http.Cookie;
-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/web/servlet/mvc/test/DirectFieldAccessIntegrationTest.java b/integration-tests/src/test/java/com/mattbertolini/spring/web/servlet/mvc/test/DirectFieldAccessIntegrationTest.java
index 2af7b3c..7460fb6 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/web/servlet/mvc/test/DirectFieldAccessIntegrationTest.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/web/servlet/mvc/test/DirectFieldAccessIntegrationTest.java
@@ -18,6 +18,7 @@
import com.mattbertolini.spring.test.web.bind.DirectFieldAccessController;
import com.mattbertolini.spring.web.servlet.mvc.bind.config.BinderConfiguration;
+import jakarta.servlet.http.Cookie;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Bean;
@@ -34,8 +35,6 @@
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
-import javax.servlet.http.Cookie;
-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
diff --git a/libs.versions.toml b/libs.versions.toml
index e91f1b7..00540e2 100644
--- a/libs.versions.toml
+++ b/libs.versions.toml
@@ -1,12 +1,14 @@
[versions]
-spring = "5.3.28" # Used in java-conventions.gradle.kts
-springBoot = "2.7.13" # Used in java-conventions.gradle.kts
+spring = "6.1.10" # Used in java-conventions.gradle.kts
+springBoot = "3.3.1" # Used in java-conventions.gradle.kts
junit = "5.9.3" # Used in java-conventions.gradle.kts
jacoco = "0.8.10" # Used in java-conventions.gradle.kts
[libraries]
-javaxServletApi = { module = "javax.servlet:javax.servlet-api", version = "4.0.1" }
-javaxValidationApi = { module = "javax.validation:validation-api", version = "2.0.1.Final" }
+jakartaServletApi = { module = "jakarta.servlet:jakarta.servlet-api", version = "6.0.0" }
+jakartaValidationApi = { module = "jakarta.validation:jakarta.validation-api", version = "3.1.0" }
+jakartaWebsocketApi = { module = "jakarta.websocket:jakarta.websocket-api", version = "2.2.0" }
+jakartaWebsocketClientApi = { module = "jakarta.websocket:jakarta.websocket-client-api", version = "2.2.0" }
findbugsJsr305 = { module = "com.google.code.findbugs:jsr305", version = "3.0.2" }
@@ -22,9 +24,9 @@ springBootTest = { module = "org.springframework.boot:spring-boot-test", version
springAsciidoctorExtBlockSwitch = { module = "io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch", version = "0.6.1" }
-glassfishJavaxEl = { module = "org.glassfish:javax.el", version = "3.0.1-b12" } # Needed by Hibernate Validator
-hibernateValidator = { module = "org.hibernate.validator:hibernate-validator", version = "6.0.21.Final" }
-jacksonDatabind = { module = "com.fasterxml.jackson.core:jackson-databind", version = "2.12.7.1" }
+glassfishJakartaEl = { module = "org.glassfish:jakarta.el", version = "4.0.2" } # Needed by Hibernate Validator
+hibernateValidator = { module = "org.hibernate.validator:hibernate-validator", version = "8.0.1.Final" }
+jacksonDatabind = { module = "com.fasterxml.jackson.core:jackson-databind", version = "2.17.2" }
junitJupiterApi = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
assertJCore = { module = "org.assertj:assertj-core", version = "3.24.2" }
diff --git a/spring-annotated-data-binder-core/build.gradle.kts b/spring-annotated-data-binder-core/build.gradle.kts
index 8a644b6..9c88fce 100644
--- a/spring-annotated-data-binder-core/build.gradle.kts
+++ b/spring-annotated-data-binder-core/build.gradle.kts
@@ -8,7 +8,7 @@ dependencies {
api(libs.springBeans)
api(libs.springWeb)
compileOnly(libs.findbugsJsr305) // To Prevent warnings on missing enum constants
- compileOnly(libs.javaxServletApi) // So Javadoc doesn't give warnings about missing links
+ compileOnly(libs.jakartaServletApi) // So Javadoc doesn't give warnings about missing links
testImplementation(libs.junitJupiterApi)
testImplementation(libs.assertJCore)
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/CookieParameter.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/CookieParameter.java
index f140ac1..dc954c2 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/CookieParameter.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/CookieParameter.java
@@ -40,7 +40,7 @@
*
*
* If you need access to all attributes of a cookie (e.g. expiration date, domain, etc) you can bind to cookie
- * objects. In Spring MVC you and bind directly to a {@link javax.servlet.http.Cookie}:
+ * objects. In Spring MVC you and bind directly to a {@link jakarta.servlet.http.Cookie}:
*
{@code
* @CookieParameter("cookie_name")
* private Cookie cookie;
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/RequestContext.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/RequestContext.java
index c77a55e..d1f350b 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/RequestContext.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/RequestContext.java
@@ -33,8 +33,8 @@
* In Spring MVC the following additional objects are available:
*
* {@link org.springframework.web.context.request.WebRequest} - The Spring WebRequest.
- * {@link javax.servlet.http.HttpServletRequest} - The underlying Servlet request.
- * {@link javax.servlet.http.HttpSession} - The Servlet session object.
+ * {@link jakarta.servlet.http.HttpServletRequest} - The underlying Servlet request.
+ * {@link jakarta.servlet.http.HttpSession} - The Servlet session object.
*
* In Spring WebFlux the following additional objects are available:
*
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java
new file mode 100644
index 0000000..30fb14b
--- /dev/null
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java
@@ -0,0 +1,20 @@
+package com.mattbertolini.spring.web.bind.support;
+
+import org.springframework.lang.Nullable;
+import org.springframework.validation.DataBinder;
+
+import java.util.Map;
+import java.util.Set;
+
+public record MapValueResolver(Map values) implements DataBinder.ValueResolver {
+ @Override
+ @Nullable
+ public Object resolveValue(String name, Class> type) {
+ return values.get(name);
+ }
+
+ @Override
+ public Set getNames() {
+ return Set.copyOf(values.keySet());
+ }
+}
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/package-info.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/package-info.java
new file mode 100644
index 0000000..7debe91
--- /dev/null
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/package-info.java
@@ -0,0 +1,4 @@
+@NonNullApi
+package com.mattbertolini.spring.web.bind.support;
+
+import org.springframework.lang.NonNullApi;
diff --git a/spring-webflux-annotated-data-binder/build.gradle.kts b/spring-webflux-annotated-data-binder/build.gradle.kts
index d8a8c28..8848608 100644
--- a/spring-webflux-annotated-data-binder/build.gradle.kts
+++ b/spring-webflux-annotated-data-binder/build.gradle.kts
@@ -12,7 +12,7 @@ dependencies {
testImplementation(libs.assertJCore)
testImplementation(libs.mockitoCore)
testImplementation(libs.springTest)
- testImplementation(libs.javaxValidationApi) // Used to test validation annotations
+ testImplementation(libs.jakartaValidationApi) // Used to test validation annotations
testCompileOnly(libs.findbugsJsr305) // To Prevent warnings on missing enum constants
}
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolver.java
index 9a7cbea..73597b5 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2022 the original author or authors.
+ * Copyright 2024 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.
@@ -21,17 +21,15 @@
import com.mattbertolini.spring.web.bind.introspect.AnnotatedRequestBeanIntrospector;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import com.mattbertolini.spring.web.bind.introspect.ResolvedPropertyData;
+import com.mattbertolini.spring.web.bind.support.MapValueResolver;
import com.mattbertolini.spring.web.reactive.bind.resolver.RequestPropertyResolver;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.MethodParameter;
-import org.springframework.core.ReactiveAdapter;
import org.springframework.core.ReactiveAdapterRegistry;
-import org.springframework.core.ResolvableType;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.web.bind.support.WebExchangeDataBinder;
-import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.result.method.annotation.ModelAttributeMethodArgumentResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
@@ -44,9 +42,6 @@
import java.util.Objects;
public class BeanParameterMethodArgumentResolver extends ModelAttributeMethodArgumentResolver {
- private static final String INTROSPECTOR_RESOLVABLE_TYPE = BeanParameterMethodArgumentResolver.class.getName()
- + ".INTROSPECTOR_RESOLVABLE_TYPE";
-
private final AnnotatedRequestBeanIntrospector introspector;
public BeanParameterMethodArgumentResolver(
@@ -63,17 +58,13 @@ public boolean supportsParameter(@NonNull MethodParameter parameter) {
@Override
@NonNull
- public Mono resolveArgument(@NonNull MethodParameter parameter, @NonNull BindingContext context, ServerWebExchange exchange) {
- try {
- ResolvableType type = ResolvableType.forMethodParameter(parameter);
- Class> resolvedType = type.resolve();
- ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);
- ResolvableType valueType = (adapter != null ? type.getGeneric() : type);
- exchange.getAttributes().put(INTROSPECTOR_RESOLVABLE_TYPE, valueType);
- return super.resolveArgument(parameter, context, exchange);
- } finally {
- exchange.getAttributes().remove(INTROSPECTOR_RESOLVABLE_TYPE);
- }
+ protected Mono constructAttribute(WebExchangeDataBinder binder, @NonNull ServerWebExchange exchange) {
+ Assert.state(binder.getTargetType() != null, "WebExchangeDataBinder must have a target type");
+ Collection propertyData = introspector.getResolversFor(Objects.requireNonNull(binder.getTargetType().getRawClass()));
+ return getValuesToBind(propertyData, exchange)
+ .map(MapValueResolver::new)
+ .doOnNext(binder::construct)
+ .then();
}
@Override
@@ -87,19 +78,6 @@ protected Mono bindRequestParameters(@NonNull WebExchangeDataBinder binder
.then();
}
- @Override
- @NonNull
- public Mono> getValuesToBind(@NonNull WebExchangeDataBinder binder, ServerWebExchange exchange) {
- ResolvableType resolvableType = exchange.getAttribute(INTROSPECTOR_RESOLVABLE_TYPE);
- if (resolvableType == null) {
- return super.getValuesToBind(binder, exchange);
- }
- Class> type = resolvableType.resolve();
- Assert.notNull(type, "The resolved type must not be null");
- Collection propertyData = introspector.getResolversFor(type);
- return getValuesToBind(propertyData, exchange);
- }
-
@NonNull
private Mono> getValuesToBind(@NonNull Collection propertyData, @NonNull ServerWebExchange exchange) {
return Flux.fromIterable(propertyData).flatMap(data -> {
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
index 6753a09..60bd2c8 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
@@ -22,6 +22,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import com.mattbertolini.spring.web.bind.introspect.ResolvedPropertyData;
import com.mattbertolini.spring.web.reactive.bind.resolver.RequestPropertyResolver;
+import jakarta.validation.Valid;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.PropertyValue;
@@ -42,7 +43,6 @@
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
-import javax.validation.Valid;
import java.beans.PropertyDescriptor;
import java.util.Arrays;
import java.util.List;
diff --git a/spring-webmvc-annotated-data-binder/build.gradle.kts b/spring-webmvc-annotated-data-binder/build.gradle.kts
index b837cd8..b565033 100644
--- a/spring-webmvc-annotated-data-binder/build.gradle.kts
+++ b/spring-webmvc-annotated-data-binder/build.gradle.kts
@@ -6,14 +6,14 @@ plugins {
dependencies {
api(project(":spring-annotated-data-binder-core"))
api(libs.springWebmvc)
- implementation(libs.javaxServletApi)
+ implementation(libs.jakartaServletApi)
compileOnly(libs.findbugsJsr305) // To Prevent warnings on missing enum constants
testImplementation(libs.junitJupiterApi)
testImplementation(libs.assertJCore)
testImplementation(libs.mockitoCore)
testImplementation(libs.springTest)
- testImplementation(libs.javaxValidationApi) // Used to test validation annotations
+ testImplementation(libs.jakartaValidationApi) // Used to test validation annotations
testCompileOnly(libs.findbugsJsr305) // To Prevent warnings on missing enum constants
}
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java
index 337c95d..071208f 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2022 the original author or authors.
+ * Copyright 2024 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.
@@ -20,26 +20,23 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import com.mattbertolini.spring.web.bind.introspect.AnnotatedRequestBeanIntrospector;
import com.mattbertolini.spring.web.bind.introspect.ResolvedPropertyData;
+import com.mattbertolini.spring.web.bind.support.MapValueResolver;
import com.mattbertolini.spring.web.servlet.mvc.bind.resolver.RequestPropertyResolver;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.MutablePropertyValues;
-import org.springframework.beans.PropertyValues;
import org.springframework.core.MethodParameter;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.annotation.ModelAttributeMethodProcessor;
import java.util.Collection;
+import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
public class BeanParameterMethodArgumentResolver extends ModelAttributeMethodProcessor {
- private static final String INTROSPECTOR_TARGET_CLASS = BeanParameterMethodArgumentResolver.class +
- ".INTROSPECTOR_TARGET_CLASS";
-
private final AnnotatedRequestBeanIntrospector introspector;
public BeanParameterMethodArgumentResolver(@NonNull AnnotatedRequestBeanIntrospector introspector) {
@@ -57,16 +54,23 @@ public boolean supportsReturnType(@NonNull MethodParameter returnType) {
return false;
}
+ @Override
+ protected void constructAttribute(WebDataBinder binder, @NonNull NativeWebRequest request) {
+ Assert.state(binder.getTargetType() != null, "WebDataBinder must have a target type");
+ Map valuesToBind = getValuesToBind(Objects.requireNonNull(binder.getTargetType().getRawClass()), request);
+ binder.construct(new MapValueResolver(valuesToBind));
+ }
+
@Override
protected void bindRequestParameters(@NonNull WebDataBinder binder, @NonNull NativeWebRequest request) {
Assert.state(binder.getTarget() != null, "WebDataBinder must have a target object");
- PropertyValues propertyValues = makePropertyValues(binder.getTarget().getClass(), request);
- binder.bind(propertyValues);
+ Map valuesToBind = getValuesToBind(binder.getTarget().getClass(), request);
+ binder.bind(new MutablePropertyValues(valuesToBind));
}
@NonNull
- private PropertyValues makePropertyValues(@NonNull Class> targetType, @NonNull NativeWebRequest request) {
- MutablePropertyValues propertyValues = new MutablePropertyValues();
+ private Map getValuesToBind(@NonNull Class> targetType, @NonNull NativeWebRequest request) {
+ Map values = new HashMap<>();
Collection propertyData = introspector.getResolversFor(targetType);
for (ResolvedPropertyData data : propertyData) {
RequestPropertyResolver resolver = (RequestPropertyResolver) data.getResolver();
@@ -74,38 +78,12 @@ private PropertyValues makePropertyValues(@NonNull Class> targetType, @NonNull
Object value = resolver.resolve(data.getBindingProperty(), request);
if (value != null) {
String propertyName = data.getPropertyName();
- propertyValues.add(propertyName, value);
+ values.put(propertyName, value);
}
} catch (Exception e) {
throw new RequestPropertyBindingException("Unable to resolve property. " + e.getMessage(), e);
}
}
- return propertyValues;
- }
-
- @Override
- @NonNull
- protected Object createAttribute(@NonNull String attributeName, MethodParameter parameter, @NonNull WebDataBinderFactory binderFactory, NativeWebRequest webRequest) throws Exception {
- try {
- MethodParameter nestedParameter = parameter.nestedIfOptional();
- Class> clazz = nestedParameter.getNestedParameterType();
- webRequest.setAttribute(INTROSPECTOR_TARGET_CLASS, clazz, RequestAttributes.SCOPE_REQUEST);
- return super.createAttribute(attributeName, parameter, binderFactory, webRequest);
- } finally {
- webRequest.removeAttribute(INTROSPECTOR_TARGET_CLASS, RequestAttributes.SCOPE_REQUEST);
- }
- }
-
- @Override
- public Object resolveConstructorArgument(@NonNull String paramName,@NonNull Class> paramType, NativeWebRequest request) throws Exception {
- Class> clazz = (Class>) request.getAttribute(INTROSPECTOR_TARGET_CLASS, RequestAttributes.SCOPE_REQUEST);
- if (clazz == null) {
- return super.resolveConstructorArgument(paramName, paramType, request);
- }
-
- final Map resolvers = introspector.getResolverMapFor(clazz);
- final ResolvedPropertyData resolvedPropertyData = resolvers.get(paramName);
- final RequestPropertyResolver resolver = (RequestPropertyResolver) resolvedPropertyData.getResolver();
- return resolver.resolve(resolvedPropertyData.getBindingProperty(), request);
+ return values;
}
}
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java
index cab8d4d..4e10e36 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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,14 +18,13 @@
import com.mattbertolini.spring.web.bind.annotation.CookieParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.util.WebUtils;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-
public class CookieParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
public boolean supports(@NonNull BindingProperty bindingProperty) {
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolver.java
index dab9a90..a45064a 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolver.java
@@ -18,15 +18,15 @@
import com.mattbertolini.spring.web.bind.annotation.RequestContext;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpSession;
import org.springframework.http.HttpMethod;
import org.springframework.lang.NonNull;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.support.RequestContextUtils;
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
import java.time.ZoneId;
import java.util.Locale;
import java.util.TimeZone;
@@ -64,7 +64,7 @@ public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeW
// Not creating a session here.
return servletRequest.getSession(false);
} else if (HttpMethod.class.isAssignableFrom(type)) {
- return HttpMethod.resolve(servletRequest.getMethod());
+ return HttpMethod.valueOf(servletRequest.getMethod());
} else if (Locale.class.isAssignableFrom(type)) {
return RequestContextUtils.getLocale(servletRequest);
} else if(TimeZone.class.isAssignableFrom(type)) {
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java
index 345cf29..d30a651 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java
@@ -19,6 +19,9 @@
import com.mattbertolini.spring.web.bind.PropertyResolutionException;
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.Part;
import org.springframework.core.ResolvableType;
import org.springframework.lang.NonNull;
import org.springframework.util.LinkedMultiValueMap;
@@ -29,9 +32,6 @@
import org.springframework.web.multipart.MultipartRequest;
import org.springframework.web.multipart.support.MultipartResolutionDelegate;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.Part;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java
index 868efb3..b6de384 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java
@@ -20,14 +20,13 @@
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import com.mattbertolini.spring.web.bind.resolver.AbstractNamedRequestPropertyResolver;
+import jakarta.servlet.http.HttpServletRequest;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.multipart.support.MultipartResolutionDelegate;
-import javax.servlet.http.HttpServletRequest;
-
public class RequestParameterRequestPropertyResolver extends AbstractNamedRequestPropertyResolver
implements RequestPropertyResolver {
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java
index 19c7e53..d3b8d13 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -22,25 +22,22 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import com.mattbertolini.spring.web.bind.introspect.ResolvedPropertyData;
import com.mattbertolini.spring.web.servlet.mvc.bind.resolver.RequestPropertyResolver;
+import jakarta.validation.Valid;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.core.MethodParameter;
-import org.springframework.format.support.FormattingConversionServiceFactoryBean;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
-import javax.validation.Valid;
import java.beans.PropertyDescriptor;
import java.util.Arrays;
import java.util.List;
@@ -49,9 +46,6 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.catchThrowableOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -62,7 +56,7 @@ class BeanParameterMethodArgumentResolverTest {
private ServletWebRequest request;
private ModelAndViewContainer mavContainer;
private AnnotatedRequestBeanIntrospector introspector;
- private WebDataBinderFactory webDataBinderFactory;
+ private MockWebDataBinderFactory webDataBinderFactory;
@BeforeEach
void setUp() {
@@ -70,7 +64,7 @@ void setUp() {
request = new ServletWebRequest(servletRequest);
mavContainer = new ModelAndViewContainer();
introspector = mock(AnnotatedRequestBeanIntrospector.class);
- webDataBinderFactory = mock(WebDataBinderFactory.class);
+ webDataBinderFactory = new MockWebDataBinderFactory();
resolver = new BeanParameterMethodArgumentResolver(introspector);
}
@@ -120,8 +114,6 @@ void supportsParameterReturnsFalseWhenAnnotationIsMissing() throws Exception {
@Test
void resolveArgumentReturnsTheTargetObject() throws Exception {
MethodParameter methodParameter = createMethodParameter("anAnnotatedMethod", ABeanClass.class);
- ABeanClass target = new ABeanClass();
- when(webDataBinderFactory.createBinder(eq(request), any(ABeanClass.class), anyString())).thenReturn(new StubWebDataBinder(target));
Object actual = resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory);
assertThat(actual).isNotNull();
assertThat(actual.getClass()).isEqualTo(ABeanClass.class);
@@ -130,8 +122,6 @@ void resolveArgumentReturnsTheTargetObject() throws Exception {
@Test
void resolveArgumentUnwrapTheTargetObjectFromOptional() throws Exception {
MethodParameter methodParameter = createMethodParameter("optionalTypeAnnotated", Optional.class);
- Object target = new ABeanClass();
- when(webDataBinderFactory.createBinder(eq(request), any(Optional.class), anyString())).thenReturn(new StubWebDataBinder(target));
Object actual = resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory);
assertThat(actual).isNotNull();
assertThat(actual.getClass()).isEqualTo(Optional.class);
@@ -143,8 +133,8 @@ void resolveArgumentUnwrapTheTargetObjectFromOptional() throws Exception {
@Test
void resolveArgumentCallsBinderBind() throws Exception {
MethodParameter methodParameter = createMethodParameter("anAnnotatedMethod", ABeanClass.class);
- StubWebDataBinder dataBinder = new StubWebDataBinder(new ABeanClass());
- resolver.resolveArgument(methodParameter, mavContainer, request, (webRequest, target, objectName) -> dataBinder);
+ resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory);
+ MockWebDataBinder dataBinder = webDataBinderFactory.getBinder();
assertThat(dataBinder.isBindInvoked()).isTrue();
}
@@ -157,13 +147,10 @@ void resolvesPropertyValues() throws Exception {
MethodParameter methodParameter = createMethodParameter("anAnnotatedMethod", ABeanClass.class);
- StubWebDataBinder dataBinder = new StubWebDataBinder(new ABeanClass());
- when(webDataBinderFactory.createBinder(eq(request), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
when(introspector.getResolversFor(ABeanClass.class)).thenReturn(propertyData);
resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory);
- PropertyValues propertyValues = dataBinder.getPropertyValues();
+ PropertyValues propertyValues = webDataBinderFactory.getBinder().getPropertyValues();
assertThat(propertyValues.contains("propertyOne")).isTrue();
assertThat(propertyValues.contains("propertyTwo")).isTrue();
@@ -184,13 +171,10 @@ void resolvesOnlyFoundPropertyValues() throws Exception {
MethodParameter methodParameter = createMethodParameter("anAnnotatedMethod", ABeanClass.class);
- StubWebDataBinder dataBinder = new StubWebDataBinder(new ABeanClass());
- when(webDataBinderFactory.createBinder(eq(request), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
when(introspector.getResolversFor(ABeanClass.class)).thenReturn(propertyData);
resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory);
- PropertyValues propertyValues = dataBinder.getPropertyValues();
+ PropertyValues propertyValues = webDataBinderFactory.getBinder().getPropertyValues();
assertThat(propertyValues.contains("propertyOne")).isFalse();
assertThat(propertyValues.contains("propertyTwo")).isTrue();
@@ -208,7 +192,6 @@ void throwsExceptionWhenResolverErrors() throws Exception {
MethodParameter methodParameter = createMethodParameter("anAnnotatedMethod", ABeanClass.class);
- when(webDataBinderFactory.createBinder(eq(request), any(ABeanClass.class), anyString())).thenReturn(new StubWebDataBinder(new ABeanClass()));
when(introspector.getResolversFor(ABeanClass.class)).thenReturn(propertyData);
assertThatThrownBy(() -> resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory))
.isInstanceOf(RequestPropertyBindingException.class);
@@ -217,36 +200,23 @@ void throwsExceptionWhenResolverErrors() throws Exception {
@Test
void validatesWhenValidAnnotationPresent() throws Exception {
MethodParameter methodParameter = createMethodParameter("aValidMethod", ABeanClass.class);
-
- StubWebDataBinder dataBinder = new StubWebDataBinder(new ABeanClass());
- when(webDataBinderFactory.createBinder(eq(request), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory);
-
- assertThat(dataBinder.isValidateInvoked()).isTrue();
+ assertThat(webDataBinderFactory.getBinder().isValidateInvoked()).isTrue();
}
@Test
void validatesWhenValidatedAnnotationPresent() throws Exception {
MethodParameter methodParameter = createMethodParameter("aValidatedMethod", ABeanClass.class);
-
- StubWebDataBinder dataBinder = new StubWebDataBinder(new ABeanClass());
- when(webDataBinderFactory.createBinder(eq(request), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory);
-
- assertThat(dataBinder.isValidateInvoked()).isTrue();
+ assertThat(webDataBinderFactory.getBinder().isValidateInvoked()).isTrue();
}
@Test
void validatesWithGroups() throws Exception {
MethodParameter methodParameter = createMethodParameter("validationGroups", ABeanClass.class);
- StubWebDataBinder dataBinder = new StubWebDataBinder(new ABeanClass());
- when(webDataBinderFactory.createBinder(eq(request), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory);
-
+ MockWebDataBinder dataBinder = webDataBinderFactory.getBinder();
assertThat(dataBinder.isValidateInvoked()).isTrue();
assertThat(dataBinder.getValidationHints()).contains(ValidationGroupOne.class, ValidationGroupTwo.class);
}
@@ -258,9 +228,7 @@ void validationThrowsBindException() throws Exception {
BindingResult bindingResult = mock(BindingResult.class);
when(bindingResult.hasErrors()).thenReturn(true);
- StubWebDataBinder dataBinder = new StubWebDataBinder(new ABeanClass());
- dataBinder.setBindingResult(bindingResult);
- when(webDataBinderFactory.createBinder(eq(request), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
+ webDataBinderFactory.setBindingResult(bindingResult);
BindException exception = catchThrowableOfType(() -> resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory), BindException.class);
assertThat(exception.getBindingResult()).isEqualTo(bindingResult);
@@ -273,79 +241,15 @@ void validationHasErrorsWithBindingResultMethodParameter() throws Exception {
BindingResult bindingResult = mock(BindingResult.class);
when(bindingResult.hasErrors()).thenReturn(true);
- StubWebDataBinder dataBinder = new StubWebDataBinder(new ABeanClass());
- dataBinder.setBindingResult(bindingResult);
- when(webDataBinderFactory.createBinder(eq(request), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
+ webDataBinderFactory.setBindingResult(bindingResult);
resolver.resolveArgument(methodParameter, mavContainer, request, webDataBinderFactory);
-
- assertThat(dataBinder.getBindingResult()).isEqualTo(bindingResult);
+ assertThat(webDataBinderFactory.getBinder().getBindingResult()).isEqualTo(bindingResult);
}
private MethodParameter createMethodParameter(String anAnnotatedMethod, Class>... parameterTypes) throws NoSuchMethodException {
return new MethodParameter(FakeHandlerMethod.class.getMethod(anAnnotatedMethod, parameterTypes), 0);
}
- private static class StubWebDataBinder extends WebDataBinder {
- private boolean bindInvoked = false;
- private boolean validateInvoked = true;
- private PropertyValues pvs;
- private List validationHints;
- private BindingResult bindingResult;
-
- public StubWebDataBinder(Object target) {
- super(target);
- FormattingConversionServiceFactoryBean conversionServiceFactoryBean = new FormattingConversionServiceFactoryBean();
- conversionServiceFactoryBean.afterPropertiesSet();
- setConversionService(conversionServiceFactoryBean.getObject());
- }
-
- @Override
- public void bind(PropertyValues pvs) {
- this.pvs = pvs;
- bindInvoked = true;
- }
-
- @Override
- public void validate() {
- validateInvoked = true;
- }
-
- @Override
- public void validate(Object... validationHints) {
- this.validationHints = Arrays.asList(validationHints);
- validateInvoked = true;
- }
-
- @Override
- public BindingResult getBindingResult() {
- if (bindingResult == null) {
- return super.getBindingResult();
- }
- return bindingResult;
- }
-
- public void setBindingResult(BindingResult bindingResult) {
- this.bindingResult = bindingResult;
- }
-
- public boolean isBindInvoked() {
- return bindInvoked;
- }
-
- public boolean isValidateInvoked() {
- return validateInvoked;
- }
-
- public List getValidationHints() {
- return validationHints;
- }
-
- public PropertyValues getPropertyValues() {
- return pvs;
- }
- }
-
private static class MockRequestPropertyResolver implements RequestPropertyResolver {
private final Object value;
private final RuntimeException exception;
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java
new file mode 100644
index 0000000..3217523
--- /dev/null
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java
@@ -0,0 +1,75 @@
+package com.mattbertolini.spring.web.servlet.mvc.bind;
+
+import org.springframework.beans.PropertyValues;
+import org.springframework.lang.Nullable;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.WebDataBinder;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class MockWebDataBinder extends WebDataBinder {
+ private boolean bindInvoked = false;
+ private boolean validateInvoked = true;
+ private PropertyValues pvs;
+ private List validationHints;
+ private BindingResult bindingResult;
+
+ public MockWebDataBinder(@Nullable Object target) {
+ super(target);
+ }
+
+ public MockWebDataBinder(@Nullable Object target, String objectName) {
+ super(target, objectName);
+ }
+
+ @Override
+ public void construct(ValueResolver valueResolver) {
+ super.construct(valueResolver); // TODO
+ }
+
+ @Override
+ public void bind(PropertyValues pvs) {
+ this.pvs = pvs;
+ bindInvoked = true;
+ }
+
+ @Override
+ public void validate() {
+ validateInvoked = true;
+ }
+
+ @Override
+ public void validate(Object... validationHints) {
+ this.validationHints = Arrays.asList(validationHints);
+ validateInvoked = true;
+ }
+
+ @Override
+ public BindingResult getBindingResult() {
+ if (bindingResult == null) {
+ return super.getBindingResult();
+ }
+ return bindingResult;
+ }
+
+ public void setBindingResult(BindingResult bindingResult) {
+ this.bindingResult = bindingResult;
+ }
+
+ public boolean isBindInvoked() {
+ return bindInvoked;
+ }
+
+ public boolean isValidateInvoked() {
+ return validateInvoked;
+ }
+
+ public List getValidationHints() {
+ return validationHints;
+ }
+
+ public PropertyValues getPropertyValues() {
+ return pvs;
+ }
+}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java
new file mode 100644
index 0000000..eee8741
--- /dev/null
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java
@@ -0,0 +1,55 @@
+package com.mattbertolini.spring.web.servlet.mvc.bind;
+
+import org.springframework.core.ResolvableType;
+import org.springframework.format.support.FormattingConversionServiceFactoryBean;
+import org.springframework.lang.Nullable;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.support.WebDataBinderFactory;
+import org.springframework.web.context.request.NativeWebRequest;
+
+public class MockWebDataBinderFactory implements WebDataBinderFactory {
+ private MockWebDataBinder binder;
+ private BindingResult bindingResult;
+
+ @Override
+ public WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object target, String objectName, ResolvableType targetType) throws Exception {
+ binder = new MockWebDataBinder(target, objectName);
+ if (target == null) {
+ binder.setTargetType(targetType);
+ }
+
+ if (bindingResult != null) {
+ binder.setBindingResult(bindingResult);
+ }
+
+ FormattingConversionServiceFactoryBean conversionServiceFactoryBean = new FormattingConversionServiceFactoryBean();
+ conversionServiceFactoryBean.afterPropertiesSet();
+ binder.setConversionService(conversionServiceFactoryBean.getObject());
+
+ return binder;
+ }
+
+ @Override
+ public WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object target, String objectName) throws Exception {
+ binder = new MockWebDataBinder(target, objectName);
+
+ if (bindingResult != null) {
+ binder.setBindingResult(bindingResult);
+ }
+
+ FormattingConversionServiceFactoryBean conversionServiceFactoryBean = new FormattingConversionServiceFactoryBean();
+ conversionServiceFactoryBean.afterPropertiesSet();
+ binder.setConversionService(conversionServiceFactoryBean.getObject());
+
+ return binder;
+ }
+
+ public void setBindingResult(BindingResult bindingResult) {
+ this.bindingResult = bindingResult;
+ }
+
+ public MockWebDataBinder getBinder() {
+ return binder;
+ }
+}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java
index d58b62b..80abe2a 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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,13 +18,13 @@
import com.mattbertolini.spring.web.bind.annotation.CookieParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
+import jakarta.servlet.http.Cookie;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
-import javax.servlet.http.Cookie;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/ExceptionThrowingMockMultipartHttpServletRequest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/ExceptionThrowingMockMultipartHttpServletRequest.java
index 41a07d1..6bc0a83 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/ExceptionThrowingMockMultipartHttpServletRequest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/ExceptionThrowingMockMultipartHttpServletRequest.java
@@ -1,10 +1,10 @@
package com.mattbertolini.spring.web.servlet.mvc.bind.resolver;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.Part;
import org.springframework.mock.web.MockMultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.ServletException;
-import javax.servlet.http.Part;
import java.io.IOException;
import java.util.Collection;
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterMapRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterMapRequestPropertyResolverTest.java
index 3c84ca6..b87facf 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterMapRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterMapRequestPropertyResolverTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2021 the original author or authors.
+ * Copyright 2024 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.
@@ -19,6 +19,7 @@
import com.mattbertolini.spring.web.bind.PropertyResolutionException;
import com.mattbertolini.spring.web.bind.annotation.FormParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
+import jakarta.servlet.http.Part;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
@@ -30,7 +31,6 @@
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.http.Part;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.nio.charset.StandardCharsets;
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolverTest.java
index b2da2ae..aa0845a 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolverTest.java
@@ -19,6 +19,7 @@
import com.mattbertolini.spring.web.bind.PropertyResolutionException;
import com.mattbertolini.spring.web.bind.annotation.FormParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
+import jakarta.servlet.http.Part;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
@@ -29,7 +30,6 @@
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.http.Part;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.nio.charset.StandardCharsets;
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolverTest.java
index 16ffbb3..7b6f168 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolverTest.java
@@ -18,6 +18,9 @@
import com.mattbertolini.spring.web.bind.annotation.RequestContext;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpSession;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod;
@@ -29,9 +32,6 @@
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.i18n.FixedLocaleResolver;
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.time.ZoneId;
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolverTest.java
index 09029a1..0c28dc7 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolverTest.java
@@ -19,6 +19,7 @@
import com.mattbertolini.spring.web.bind.PropertyResolutionException;
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
+import jakarta.servlet.http.Part;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
@@ -30,7 +31,6 @@
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.http.Part;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.nio.charset.StandardCharsets;
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolverTest.java
index 37c195e..869e469 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolverTest.java
@@ -19,6 +19,7 @@
import com.mattbertolini.spring.web.bind.PropertyResolutionException;
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
+import jakarta.servlet.http.Part;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
@@ -29,7 +30,6 @@
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.http.Part;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.nio.charset.StandardCharsets;
From 2359ab09404d72ab1f7804deda1c699dbeb1a37b Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Tue, 16 Jul 2024 16:47:42 -0400
Subject: [PATCH 02/33] More updates for JDK 17 and Spring Boot 3.x
---
.../bind/config/BinderConfiguration.java | 9 +-
...anParameterMethodArgumentResolverTest.java | 113 +++---------------
.../web/reactive/bind/MockBindingContext.java | 64 ++++++++++
.../bind/MockWebExchangeDataBinder.java | 73 +++++++++++
.../mvc/bind/config/BinderConfiguration.java | 6 +-
.../build.gradle.kts | 2 +
.../WebFluxBinderAutoConfiguration.java | 6 +-
.../main/resources/META-INF/spring.factories | 2 -
...ot.autoconfigure.AutoConfiguration.imports | 1 +
.../WebMvcBinderAutoConfiguration.java | 6 +-
.../main/resources/META-INF/spring.factories | 2 -
...ot.autoconfigure.AutoConfiguration.imports | 1 +
12 files changed, 167 insertions(+), 118 deletions(-)
create mode 100644 spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockBindingContext.java
create mode 100644 spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java
delete mode 100644 webflux-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring.factories
create mode 100644 webflux-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
delete mode 100644 webmvc-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring.factories
create mode 100644 webmvc-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java
index 95df482..9345bab 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -42,7 +42,7 @@
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
import java.util.Collections;
-import java.util.LinkedHashSet;
+import java.util.HashSet;
import java.util.Set;
/**
@@ -67,7 +67,7 @@ public BinderConfiguration() {
* @param propertyResolverRegistry The resolver registry to use.
*/
public BinderConfiguration(@NonNull PropertyResolverRegistry propertyResolverRegistry) {
- packagesToScan = new LinkedHashSet<>();
+ packagesToScan = new HashSet<>();
this.propertyResolverRegistry = propertyResolverRegistry;
}
@@ -137,11 +137,10 @@ public Set getPackagesToScan() {
@Override
public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) {
- if (!(bean instanceof RequestMappingHandlerAdapter)) {
+ if (!(bean instanceof RequestMappingHandlerAdapter adapter)) {
return bean;
}
- RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean;
ArgumentResolverConfigurer resolverConfigurer = adapter.getArgumentResolverConfigurer();
if (resolverConfigurer != null) {
ReactiveAdapterRegistry reactiveAdapterRegistry = adapter.getReactiveAdapterRegistry();
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
index 60bd2c8..6e051b6 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
@@ -24,22 +24,19 @@
import com.mattbertolini.spring.web.reactive.bind.resolver.RequestPropertyResolver;
import jakarta.validation.Valid;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
-import org.springframework.format.support.FormattingConversionServiceFactoryBean;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
-import org.springframework.validation.support.BindingAwareConcurrentModel;
import org.springframework.web.bind.support.WebExchangeBindException;
-import org.springframework.web.bind.support.WebExchangeDataBinder;
-import org.springframework.web.reactive.BindingContext;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@@ -51,9 +48,6 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.catchThrowableOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -62,15 +56,14 @@ class BeanParameterMethodArgumentResolverTest {
private ServerWebExchange exchange;
private AnnotatedRequestBeanIntrospector introspector;
- private BindingContext bindingContext;
+ private MockBindingContext bindingContext;
@BeforeEach
void setUp() {
MockServerHttpRequest request = MockServerHttpRequest.get("/irrelevant").build();
exchange = MockServerWebExchange.from(request);
introspector = mock(AnnotatedRequestBeanIntrospector.class);
- bindingContext = mock(BindingContext.class);
- when(bindingContext.getModel()).thenReturn(new BindingAwareConcurrentModel());
+ bindingContext = new MockBindingContext();
ReactiveAdapterRegistry registry = new ReactiveAdapterRegistry();
resolver = new BeanParameterMethodArgumentResolver(registry, introspector);
}
@@ -105,14 +98,11 @@ void resolvesPropertyValues() throws Exception {
MethodParameter methodParameter = createMethodParameter("anAnnotatedMethod", ABeanClass.class);
- StubWebExchangeDataBinder dataBinder = new StubWebExchangeDataBinder(new ABeanClass());
- when(bindingContext.createDataBinder(eq(exchange), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
when(introspector.getResolversFor(ABeanClass.class)).thenReturn(propertyData);
Mono objectMono = resolver.resolveArgument(methodParameter, bindingContext, exchange);
objectMono.block();
- PropertyValues propertyValues = dataBinder.getPropertyValues();
+ PropertyValues propertyValues = bindingContext.getDataBinder().getPropertyValues();
assertThat(propertyValues.contains("propertyOne")).isTrue();
assertThat(propertyValues.contains("propertyTwo")).isTrue();
@@ -133,14 +123,11 @@ void resolvesOnlyFoundPropertyValues() throws Exception {
MethodParameter methodParameter = createMethodParameter("anAnnotatedMethod", ABeanClass.class);
- StubWebExchangeDataBinder dataBinder = new StubWebExchangeDataBinder(new ABeanClass());
- when(bindingContext.createDataBinder(eq(exchange), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
when(introspector.getResolversFor(ABeanClass.class)).thenReturn(propertyData);
Mono objectMono = resolver.resolveArgument(methodParameter, bindingContext, exchange);
objectMono.block();
- PropertyValues propertyValues = dataBinder.getPropertyValues();
+ PropertyValues propertyValues = bindingContext.getDataBinder().getPropertyValues();
assertThat(propertyValues.contains("propertyOne")).isFalse();
assertThat(propertyValues.contains("propertyTwo")).isTrue();
@@ -173,7 +160,6 @@ void throwsExceptionWhenResolverErrors() throws Exception {
MethodParameter methodParameter = createMethodParameter("anAnnotatedMethod", ABeanClass.class);
- when(bindingContext.createDataBinder(eq(exchange), any(ABeanClass.class), anyString())).thenReturn(new StubWebExchangeDataBinder(new ABeanClass()));
when(introspector.getResolversFor(ABeanClass.class)).thenReturn(propertyData);
Mono objectMono = resolver.resolveArgument(methodParameter, bindingContext, exchange);
assertThatThrownBy(objectMono::block).isInstanceOf(RequestPropertyBindingException.class);
@@ -183,38 +169,30 @@ void throwsExceptionWhenResolverErrors() throws Exception {
void validatesWhenValidAnnotationPresent() throws Exception {
MethodParameter methodParameter = createMethodParameter("aValidMethod", ABeanClass.class);
- StubWebExchangeDataBinder dataBinder = new StubWebExchangeDataBinder(new ABeanClass());
- when(bindingContext.createDataBinder(eq(exchange), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
Mono objectMono = resolver.resolveArgument(methodParameter, bindingContext, exchange);
objectMono.block();
- assertThat(dataBinder.isValidateInvoked()).isTrue();
+ assertThat(bindingContext.getDataBinder().isValidateInvoked()).isTrue();
}
@Test
void validatesWhenValidatedAnnotationPresent() throws Exception {
MethodParameter methodParameter = createMethodParameter("aValidatedMethod", ABeanClass.class);
- StubWebExchangeDataBinder dataBinder = new StubWebExchangeDataBinder(new ABeanClass());
- when(bindingContext.createDataBinder(eq(exchange), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
Mono objectMono = resolver.resolveArgument(methodParameter, bindingContext, exchange);
objectMono.block();
- assertThat(dataBinder.isValidateInvoked()).isTrue();
+ assertThat(bindingContext.getDataBinder().isValidateInvoked()).isTrue();
}
@Test
void validatesWithGroups() throws Exception {
MethodParameter methodParameter = createMethodParameter("validationGroups", ABeanClass.class);
- StubWebExchangeDataBinder dataBinder = new StubWebExchangeDataBinder(new ABeanClass());
- when(bindingContext.createDataBinder(eq(exchange), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
-
Mono objectMono = resolver.resolveArgument(methodParameter, bindingContext, exchange);
objectMono.block();
+ MockWebExchangeDataBinder dataBinder = bindingContext.getDataBinder();
assertThat(dataBinder.isValidateInvoked()).isTrue();
assertThat(dataBinder.getValidationHints()).contains(ValidationGroupOne.class, ValidationGroupTwo.class);
}
@@ -226,9 +204,7 @@ void validationThrowsBindException() throws Exception {
BindingResult bindingResult = mock(BindingResult.class);
when(bindingResult.hasErrors()).thenReturn(true);
- StubWebExchangeDataBinder dataBinder = new StubWebExchangeDataBinder(new ABeanClass());
- dataBinder.setBindingResult(bindingResult);
- when(bindingContext.createDataBinder(eq(exchange), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
+ bindingContext.setBindingResult(bindingResult);
Mono objectMono = resolver.resolveArgument(methodParameter, bindingContext, exchange);
WebExchangeBindException exception = catchThrowableOfType(objectMono::block, WebExchangeBindException.class);
@@ -236,86 +212,25 @@ void validationThrowsBindException() throws Exception {
}
@Test
+ @Disabled // TODO: Fix this
void validationHasErrorsWithBindingResultMethodParameter() throws Exception {
MethodParameter methodParameter = createMethodParameter("withBindingResult", ABeanClass.class, BindingResult.class);
- BindingResult bindingResult = mock(BindingResult.class);
- when(bindingResult.hasErrors()).thenReturn(true);
+// BindingResult bindingResult = mock(BindingResult.class);
+// when(bindingResult.hasErrors()).thenReturn(true);
- StubWebExchangeDataBinder dataBinder = new StubWebExchangeDataBinder(new ABeanClass());
- dataBinder.setBindingResult(bindingResult);
- when(bindingContext.createDataBinder(eq(exchange), any(ABeanClass.class), anyString())).thenReturn(dataBinder);
+// bindingContext.setBindingResult(bindingResult);
Mono objectMono = resolver.resolveArgument(methodParameter, bindingContext, exchange);
objectMono.block();
- assertThat(dataBinder.getBindingResult()).isEqualTo(bindingResult);
+ assertThat(bindingContext.getDataBinder().getBindingResult().hasErrors()).isTrue();
}
private MethodParameter createMethodParameter(String anAnnotatedMethod, Class>... parameterTypes) throws NoSuchMethodException {
return new MethodParameter(FakeHandlerMethod.class.getMethod(anAnnotatedMethod, parameterTypes), 0);
}
- private static class StubWebExchangeDataBinder extends WebExchangeDataBinder {
- private boolean bindInvoked = false;
- private boolean validateInvoked = true;
- private PropertyValues pvs;
- private List validationHints;
- private BindingResult bindingResult;
-
- public StubWebExchangeDataBinder(Object target) {
- super(target);
- FormattingConversionServiceFactoryBean conversionServiceFactoryBean = new FormattingConversionServiceFactoryBean();
- conversionServiceFactoryBean.afterPropertiesSet();
- setConversionService(conversionServiceFactoryBean.getObject());
- }
-
- @Override
- public void bind(PropertyValues pvs) {
- this.pvs = pvs;
- bindInvoked = true;
- }
-
- @Override
- public void validate() {
- validateInvoked = true;
- }
-
- @Override
- public void validate(Object... validationHints) {
- this.validationHints = Arrays.asList(validationHints);
- validateInvoked = true;
- }
-
- @Override
- public BindingResult getBindingResult() {
- if (bindingResult == null) {
- return super.getBindingResult();
- }
- return bindingResult;
- }
-
- public void setBindingResult(BindingResult bindingResult) {
- this.bindingResult = bindingResult;
- }
-
- public boolean isBindInvoked() {
- return bindInvoked;
- }
-
- public boolean isValidateInvoked() {
- return validateInvoked;
- }
-
- public List getValidationHints() {
- return validationHints;
- }
-
- public PropertyValues getPropertyValues() {
- return pvs;
- }
- }
-
private static class MockRequestPropertyResolver implements RequestPropertyResolver {
private final Object value;
private final RuntimeException exception;
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockBindingContext.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockBindingContext.java
new file mode 100644
index 0000000..d55ed65
--- /dev/null
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockBindingContext.java
@@ -0,0 +1,64 @@
+package com.mattbertolini.spring.web.reactive.bind;
+
+import org.springframework.core.ResolvableType;
+import org.springframework.format.support.FormattingConversionServiceFactoryBean;
+import org.springframework.lang.Nullable;
+import org.springframework.ui.Model;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.support.BindingAwareConcurrentModel;
+import org.springframework.web.bind.support.WebExchangeDataBinder;
+import org.springframework.web.reactive.BindingContext;
+import org.springframework.web.server.ServerWebExchange;
+
+public class MockBindingContext extends BindingContext {
+ private final BindingAwareConcurrentModel model = new BindingAwareConcurrentModel();
+ private MockWebExchangeDataBinder dataBinder;
+ private BindingResult bindingResult;
+
+ @Override
+ public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange, Object target, String name) {
+ dataBinder = new MockWebExchangeDataBinder(target);
+
+ if (bindingResult != null) {
+ dataBinder.setBindingResult(bindingResult);
+ }
+
+ FormattingConversionServiceFactoryBean conversionServiceFactoryBean = new FormattingConversionServiceFactoryBean();
+ conversionServiceFactoryBean.afterPropertiesSet();
+ dataBinder.setConversionService(conversionServiceFactoryBean.getObject());
+
+ return dataBinder;
+ }
+
+ @Override
+ public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange, @Nullable Object target, String name, ResolvableType targetType) {
+ dataBinder = new MockWebExchangeDataBinder(target);
+
+ if (target == null) {
+ dataBinder.setTargetType(targetType);
+ }
+
+ if (bindingResult != null) {
+ dataBinder.setBindingResult(bindingResult);
+ }
+
+ FormattingConversionServiceFactoryBean conversionServiceFactoryBean = new FormattingConversionServiceFactoryBean();
+ conversionServiceFactoryBean.afterPropertiesSet();
+ dataBinder.setConversionService(conversionServiceFactoryBean.getObject());
+
+ return dataBinder;
+ }
+
+ @Override
+ public Model getModel() {
+ return model;
+ }
+
+ public MockWebExchangeDataBinder getDataBinder() {
+ return dataBinder;
+ }
+
+ public void setBindingResult(BindingResult bindingResult) {
+ this.bindingResult = bindingResult;
+ }
+}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java
new file mode 100644
index 0000000..293a137
--- /dev/null
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java
@@ -0,0 +1,73 @@
+package com.mattbertolini.spring.web.reactive.bind;
+
+import org.springframework.beans.PropertyValues;
+import org.springframework.lang.Nullable;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.support.WebExchangeDataBinder;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class MockWebExchangeDataBinder extends WebExchangeDataBinder {
+ private boolean bindInvoked = false;
+ private boolean validateInvoked = true;
+ private PropertyValues pvs;
+ private List validationHints;
+ private BindingResult bindingResult;
+
+ public MockWebExchangeDataBinder(@Nullable Object target) {
+ super(target);
+ }
+
+ @Override
+ public Mono construct(ServerWebExchange exchange) {
+ return super.construct(exchange); // TODO
+ }
+
+ @Override
+ public void bind(PropertyValues pvs) {
+ this.pvs = pvs;
+ bindInvoked = true;
+ }
+
+ @Override
+ public void validate() {
+ validateInvoked = true;
+ }
+
+ @Override
+ public void validate(Object... validationHints) {
+ this.validationHints = Arrays.asList(validationHints);
+ validateInvoked = true;
+ }
+
+ @Override
+ public BindingResult getBindingResult() {
+ if (bindingResult == null) {
+ return super.getBindingResult();
+ }
+ return bindingResult;
+ }
+
+ public void setBindingResult(BindingResult bindingResult) {
+ this.bindingResult = bindingResult;
+ }
+
+ public boolean isBindInvoked() {
+ return bindInvoked;
+ }
+
+ public boolean isValidateInvoked() {
+ return validateInvoked;
+ }
+
+ public List getValidationHints() {
+ return validationHints;
+ }
+
+ public PropertyValues getPropertyValues() {
+ return pvs;
+ }
+}
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/BinderConfiguration.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/BinderConfiguration.java
index d66604c..e331223 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/BinderConfiguration.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/BinderConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -91,12 +91,10 @@ public Set getPackagesToScan() {
@Override
public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) {
- if (!(bean instanceof RequestMappingHandlerAdapter)) {
+ if (!(bean instanceof RequestMappingHandlerAdapter adapter)) {
return bean;
}
- RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean;
-
PropertyResolverRegistry resolverRegistry = createPropertyResolverRegistry(adapter);
AnnotatedRequestBeanIntrospector introspector = createIntrospector(resolverRegistry);
BeanParameterMethodArgumentResolver resolver = createResolver(introspector);
diff --git a/webflux-annotated-data-binder-spring-boot-starter/build.gradle.kts b/webflux-annotated-data-binder-spring-boot-starter/build.gradle.kts
index 7e112b4..42110ac 100644
--- a/webflux-annotated-data-binder-spring-boot-starter/build.gradle.kts
+++ b/webflux-annotated-data-binder-spring-boot-starter/build.gradle.kts
@@ -10,6 +10,8 @@ dependencies {
testImplementation(libs.junitJupiterApi)
testImplementation(libs.assertJCore)
testImplementation(libs.springBootTest)
+ testImplementation(libs.jakartaWebsocketClientApi)
+ testImplementation(libs.jakartaWebsocketApi)
}
tasks.named("jar").configure {
diff --git a/webflux-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/reactive/bind/autoconfigure/WebFluxBinderAutoConfiguration.java b/webflux-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/reactive/bind/autoconfigure/WebFluxBinderAutoConfiguration.java
index 5c6799f..ca58901 100644
--- a/webflux-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/reactive/bind/autoconfigure/WebFluxBinderAutoConfiguration.java
+++ b/webflux-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/reactive/bind/autoconfigure/WebFluxBinderAutoConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2021 the original author or authors.
+ * Copyright 2024 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.
@@ -22,11 +22,11 @@
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import java.util.LinkedHashSet;
@@ -34,7 +34,7 @@
import java.util.List;
import java.util.Set;
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@ConditionalOnMissingBean(BinderConfiguration.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
diff --git a/webflux-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring.factories b/webflux-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 25e6444..0000000
--- a/webflux-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- com.mattbertolini.spring.web.reactive.bind.autoconfigure.WebFluxBinderAutoConfiguration
\ No newline at end of file
diff --git a/webflux-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/webflux-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..fe8d94e
--- /dev/null
+++ b/webflux-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.mattbertolini.spring.web.reactive.bind.autoconfigure.WebFluxBinderAutoConfiguration
diff --git a/webmvc-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/autoconfigure/WebMvcBinderAutoConfiguration.java b/webmvc-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/autoconfigure/WebMvcBinderAutoConfiguration.java
index 1fed7ac..a4be734 100644
--- a/webmvc-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/autoconfigure/WebMvcBinderAutoConfiguration.java
+++ b/webmvc-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/autoconfigure/WebMvcBinderAutoConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2021 the original author or authors.
+ * Copyright 2024 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.
@@ -22,11 +22,11 @@
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import java.util.LinkedHashSet;
@@ -34,7 +34,7 @@
import java.util.List;
import java.util.Set;
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@ConditionalOnMissingBean(BinderConfiguration.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
diff --git a/webmvc-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring.factories b/webmvc-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 4246bcc..0000000
--- a/webmvc-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- com.mattbertolini.spring.web.servlet.mvc.bind.autoconfigure.WebMvcBinderAutoConfiguration
\ No newline at end of file
diff --git a/webmvc-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/webmvc-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..975fc27
--- /dev/null
+++ b/webmvc-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.mattbertolini.spring.web.servlet.mvc.bind.autoconfigure.WebMvcBinderAutoConfiguration
From 6464da4ab2644807033c57c8668fc68e81548616 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Tue, 16 Jul 2024 18:10:19 -0400
Subject: [PATCH 03/33] Green build
---
docs/build.gradle.kts | 2 ++
.../resolver/RequestPropertyResolverBase.java | 4 +--
.../bind/config/BinderConfiguration.java | 2 +-
.../RequestBodyRequestPropertyResolver.java | 3 +-
...anParameterMethodArgumentResolverTest.java | 13 ++++----
.../BeanParameterMethodArgumentResolver.java | 32 +++++++++++++------
.../web/servlet/mvc/bind/package-info.java | 4 +++
...ookieParameterRequestPropertyResolver.java | 7 ++--
...stParameterMapRequestPropertyResolver.java | 4 ++-
...questParameterRequestPropertyResolver.java | 7 ++--
.../resolver/RequestPropertyResolver.java | 2 +-
...ssionParameterRequestPropertyResolver.java | 8 +++--
.../mvc/bind/resolver/package-info.java | 4 +++
13 files changed, 60 insertions(+), 32 deletions(-)
create mode 100644 spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/package-info.java
create mode 100644 spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/package-info.java
diff --git a/docs/build.gradle.kts b/docs/build.gradle.kts
index 15451ce..b318e2b 100644
--- a/docs/build.gradle.kts
+++ b/docs/build.gradle.kts
@@ -21,6 +21,8 @@ dependencies {
testImplementation(libs.mockitoCore)
testImplementation(libs.springTest)
testCompileOnly(libs.hamcrest) // Needed for Spring mock MVC matchers
+ testImplementation(libs.jakartaWebsocketApi)
+ testImplementation(libs.jakartaWebsocketClientApi)
}
tasks.named("asciidoctor").configure {
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/RequestPropertyResolverBase.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/RequestPropertyResolverBase.java
index 2dc977b..7543f4b 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/RequestPropertyResolverBase.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/RequestPropertyResolverBase.java
@@ -28,8 +28,8 @@
* @param The response type to use.
*/
public interface RequestPropertyResolverBase {
- boolean supports(@NonNull BindingProperty bindingProperty);
+ boolean supports(BindingProperty bindingProperty);
@Nullable
- R resolve(@NonNull BindingProperty bindingProperty, @NonNull T request);
+ R resolve(BindingProperty bindingProperty, T request);
}
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java
index 9345bab..ff58e52 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java
@@ -116,7 +116,7 @@ public BinderConfiguration addResolvers(Set resolvers)
}
/**
- * Add all of the resolvers from the given registry into this registry.
+ * Add all the resolvers from the given registry into this registry.
*
* @param propertyResolverRegistry The registry to add resolvers from. Required.
* @return This instance of the configuration.
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestBodyRequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestBodyRequestPropertyResolver.java
index dbf7617..b71c32d 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestBodyRequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestBodyRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -45,7 +45,6 @@ public boolean supports(@NonNull BindingProperty bindingProperty) {
return bindingProperty.hasAnnotation(RequestBody.class);
}
-
@NonNull
@Override
public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange request) {
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
index 6e051b6..3578a75 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
@@ -24,7 +24,6 @@
import com.mattbertolini.spring.web.reactive.bind.resolver.RequestPropertyResolver;
import jakarta.validation.Valid;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
@@ -212,19 +211,21 @@ void validationThrowsBindException() throws Exception {
}
@Test
- @Disabled // TODO: Fix this
void validationHasErrorsWithBindingResultMethodParameter() throws Exception {
MethodParameter methodParameter = createMethodParameter("withBindingResult", ABeanClass.class, BindingResult.class);
-// BindingResult bindingResult = mock(BindingResult.class);
-// when(bindingResult.hasErrors()).thenReturn(true);
+ BindingResult bindingResult = mock(BindingResult.class);
+ when(bindingResult.hasErrors())
+ .thenReturn(false)
+ .thenReturn(false)
+ .thenReturn(true);
-// bindingContext.setBindingResult(bindingResult);
+ bindingContext.setBindingResult(bindingResult);
Mono objectMono = resolver.resolveArgument(methodParameter, bindingContext, exchange);
objectMono.block();
- assertThat(bindingContext.getDataBinder().getBindingResult().hasErrors()).isTrue();
+ assertThat(bindingContext.getDataBinder().getBindingResult()).isEqualTo(bindingResult);
}
private MethodParameter createMethodParameter(String anAnnotatedMethod, Class>... parameterTypes) throws NoSuchMethodException {
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java
index 071208f..01c3557 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java
@@ -25,10 +25,10 @@
import org.springframework.beans.BeanUtils;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.MethodParameter;
-import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.annotation.ModelAttributeMethodProcessor;
import java.util.Collection;
@@ -37,39 +37,51 @@
import java.util.Objects;
public class BeanParameterMethodArgumentResolver extends ModelAttributeMethodProcessor {
+ private static final String BIND_VALUES_ATTRIBUTE_KEY = BeanParameterMethodArgumentResolver.class.getName() + ".bindValues";
private final AnnotatedRequestBeanIntrospector introspector;
- public BeanParameterMethodArgumentResolver(@NonNull AnnotatedRequestBeanIntrospector introspector) {
+ public BeanParameterMethodArgumentResolver(AnnotatedRequestBeanIntrospector introspector) {
super(false);
this.introspector = introspector;
}
@Override
- public boolean supportsParameter(@NonNull MethodParameter parameter) {
+ public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(BeanParameter.class) && !BeanUtils.isSimpleProperty(parameter.getParameterType());
}
@Override
- public boolean supportsReturnType(@NonNull MethodParameter returnType) {
+ public boolean supportsReturnType(MethodParameter returnType) {
return false;
}
@Override
- protected void constructAttribute(WebDataBinder binder, @NonNull NativeWebRequest request) {
+ protected void constructAttribute(WebDataBinder binder, NativeWebRequest request) {
Assert.state(binder.getTargetType() != null, "WebDataBinder must have a target type");
- Map valuesToBind = getValuesToBind(Objects.requireNonNull(binder.getTargetType().getRawClass()), request);
+ Map valuesToBind = memoizedGetValuesToBind(Objects.requireNonNull(binder.getTargetType().getRawClass()), request);
binder.construct(new MapValueResolver(valuesToBind));
}
@Override
- protected void bindRequestParameters(@NonNull WebDataBinder binder, @NonNull NativeWebRequest request) {
+ protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
Assert.state(binder.getTarget() != null, "WebDataBinder must have a target object");
- Map valuesToBind = getValuesToBind(binder.getTarget().getClass(), request);
+ Map valuesToBind = memoizedGetValuesToBind(binder.getTarget().getClass(), request);
binder.bind(new MutablePropertyValues(valuesToBind));
+ request.removeAttribute(BIND_VALUES_ATTRIBUTE_KEY, RequestAttributes.SCOPE_REQUEST);
}
- @NonNull
- private Map getValuesToBind(@NonNull Class> targetType, @NonNull NativeWebRequest request) {
+ @SuppressWarnings("unchecked")
+ private Map memoizedGetValuesToBind(Class> targetType, NativeWebRequest request) {
+ Map memoizedValues = (Map) request.getAttribute(BIND_VALUES_ATTRIBUTE_KEY, NativeWebRequest.SCOPE_REQUEST);
+ if (memoizedValues != null) {
+ return memoizedValues;
+ }
+ Map valuesToBind = getValuesToBind(targetType, request);
+ request.setAttribute(BIND_VALUES_ATTRIBUTE_KEY, valuesToBind, NativeWebRequest.SCOPE_REQUEST);
+ return valuesToBind;
+ }
+
+ private Map getValuesToBind(Class> targetType, NativeWebRequest request) {
Map values = new HashMap<>();
Collection propertyData = introspector.getResolversFor(targetType);
for (ResolvedPropertyData data : propertyData) {
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/package-info.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/package-info.java
new file mode 100644
index 0000000..a382391
--- /dev/null
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/package-info.java
@@ -0,0 +1,4 @@
+@NonNullApi
+package com.mattbertolini.spring.web.servlet.mvc.bind;
+
+import org.springframework.lang.NonNullApi;
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java
index 4e10e36..12fa0fe 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java
@@ -20,19 +20,20 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
-import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.util.WebUtils;
public class CookieParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
return bindingProperty.hasAnnotation(CookieParameter.class);
}
@Override
- public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeWebRequest request) {
+ @Nullable
+ public Object resolve(BindingProperty bindingProperty, NativeWebRequest request) {
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
Assert.state(servletRequest != null, "A HttpServletRequest is required for this resolver and none found.");
CookieParameter annotation = bindingProperty.getAnnotation(CookieParameter.class);
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java
index d30a651..240201d 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2021 the original author or authors.
+ * Copyright 2024 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.
@@ -24,6 +24,7 @@
import jakarta.servlet.http.Part;
import org.springframework.core.ResolvableType;
import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
@@ -48,6 +49,7 @@ public boolean supports(@NonNull BindingProperty bindingProperty) {
}
@Override
+ @Nullable
public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeWebRequest request) {
ResolvableType resolvableType = ResolvableType.forMethodParameter(bindingProperty.getMethodParameter());
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java
index b6de384..bb096cc 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java
@@ -22,6 +22,7 @@
import com.mattbertolini.spring.web.bind.resolver.AbstractNamedRequestPropertyResolver;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.NativeWebRequest;
@@ -31,12 +32,13 @@ public class RequestParameterRequestPropertyResolver extends AbstractNamedReques
implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
RequestParameter annotation = bindingProperty.getAnnotation(RequestParameter.class);
return annotation != null && StringUtils.hasText(annotation.value());
}
@Override
+ @Nullable
protected Object resolveWithName(@NonNull BindingProperty bindingProperty, String name, @NonNull NativeWebRequest request) {
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
if (servletRequest != null) {
@@ -54,8 +56,7 @@ protected Object resolveWithName(@NonNull BindingProperty bindingProperty, Strin
}
@Override
- @NonNull
- protected String getName(@NonNull BindingProperty bindingProperty) {
+ protected String getName(BindingProperty bindingProperty) {
RequestParameter annotation = bindingProperty.getAnnotation(RequestParameter.class);
Assert.state(annotation != null, "No RequestParameter annotation found on type");
return annotation.value();
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestPropertyResolver.java
index 7aedadd..66efb13 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolver.java
index c7aeb15..7f3c7f4 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -19,18 +19,20 @@
import com.mattbertolini.spring.web.bind.annotation.SessionParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
public class SessionParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
return bindingProperty.hasAnnotation(SessionParameter.class);
}
@Override
- public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeWebRequest request) {
+ @Nullable
+ public Object resolve(BindingProperty bindingProperty, NativeWebRequest request) {
SessionParameter annotation = bindingProperty.getAnnotation(SessionParameter.class);
Assert.state(annotation != null, "No SessionParameter annotation found on type");
return request.getAttribute(annotation.value(), RequestAttributes.SCOPE_SESSION);
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/package-info.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/package-info.java
new file mode 100644
index 0000000..3319042
--- /dev/null
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/package-info.java
@@ -0,0 +1,4 @@
+@NonNullApi
+package com.mattbertolini.spring.web.servlet.mvc.bind.resolver;
+
+import org.springframework.lang.NonNullApi;
From 5d7ab27ded1997e470de714c9fd27cb7d0e8245f Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Wed, 17 Jul 2024 08:39:48 -0400
Subject: [PATCH 04/33] Start enforcing nullable annotations via NullAway
---
buildSrc/build.gradle.kts | 5 ++++
.../buildlogic/error-prone.gradle.kts | 30 +++++++++++++++++++
.../buildlogic/java-conventions.gradle.kts | 1 +
libs.versions.toml | 7 +++++
.../AbstractPropertyResolverRegistry.java | 6 ++--
.../web/bind/PropertyResolutionException.java | 2 +-
.../bind/RequestPropertyBindingException.java | 2 +-
.../web/bind/annotation/package-info.java | 6 ++++
.../AnnotatedRequestBeanIntrospector.java | 10 ++-----
.../web/bind/introspect/BindingProperty.java | 16 ++++------
.../web/bind/introspect/package-info.java | 6 ++++
.../spring/web/bind/package-info.java | 6 ++++
.../AbstractNamedRequestPropertyResolver.java | 13 ++++----
.../resolver/RequestPropertyResolverBase.java | 2 +-
.../web/bind/resolver/package-info.java | 6 ++++
.../web/bind/support/MapValueResolver.java | 22 ++++++++++++++
.../spring/web/bind/support/package-info.java | 2 ++
.../introspect/ResolvedPropertyDataTest.java | 13 +++++---
.../web/bind/introspect/scan/IgnoredBean.java | 3 ++
.../web/bind/introspect/scan/ScannedBean.java | 3 ++
.../scan/subbackage/SubpackageBean.java | 3 ++
.../BeanParameterMethodArgumentResolver.java | 14 ++++-----
.../bind/config/BinderConfiguration.java | 9 +++---
.../reactive/bind/config/package-info.java | 6 ++++
.../web/reactive/bind/package-info.java | 6 ++++
...ookieParameterRequestPropertyResolver.java | 11 +++----
...rmParameterMapRequestPropertyResolver.java | 6 ++--
.../FormParameterRequestPropertyResolver.java | 10 +++----
...erParameterMapRequestPropertyResolver.java | 4 +--
...eaderParameterRequestPropertyResolver.java | 8 +++--
.../PathParameterRequestPropertyResolver.java | 6 ++--
...questParameterRequestPropertyResolver.java | 7 +++--
.../resolver/RequestPropertyResolver.java | 4 +--
...ssionParameterRequestPropertyResolver.java | 14 ++++-----
.../reactive/bind/resolver/package-info.java | 6 ++++
.../mvc/bind/PropertyResolverRegistry.java | 2 +-
.../mvc/bind/config/BinderConfiguration.java | 5 ++--
.../servlet/mvc/bind/config/package-info.java | 6 ++++
.../web/servlet/mvc/bind/package-info.java | 2 ++
...ookieParameterRequestPropertyResolver.java | 4 ++-
.../FormParameterRequestPropertyResolver.java | 13 ++++----
...eaderParameterRequestPropertyResolver.java | 16 ++++++----
.../PathParameterRequestPropertyResolver.java | 13 ++++----
...RequestContextRequestPropertyResolver.java | 9 +++---
...stParameterMapRequestPropertyResolver.java | 6 ++--
...questParameterRequestPropertyResolver.java | 8 +++--
...ssionParameterRequestPropertyResolver.java | 6 ++--
.../mvc/bind/resolver/package-info.java | 2 ++
48 files changed, 252 insertions(+), 115 deletions(-)
create mode 100644 buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/error-prone.gradle.kts
create mode 100644 spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/package-info.java
create mode 100644 spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/package-info.java
create mode 100644 spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/package-info.java
create mode 100644 spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/package-info.java
create mode 100644 spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/package-info.java
create mode 100644 spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/package-info.java
create mode 100644 spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/package-info.java
create mode 100644 spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/package-info.java
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 876c922..1316170 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -3,5 +3,10 @@ plugins {
}
repositories {
+ gradlePluginPortal()
mavenCentral()
}
+
+dependencies {
+ implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.0.1")
+}
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/error-prone.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/error-prone.gradle.kts
new file mode 100644
index 0000000..6fa68c7
--- /dev/null
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/error-prone.gradle.kts
@@ -0,0 +1,30 @@
+package com.mattbertolini.buildlogic
+
+import net.ltgt.gradle.errorprone.CheckSeverity
+import net.ltgt.gradle.errorprone.errorprone
+
+plugins {
+ id("net.ltgt.errorprone")
+}
+
+val libsCatalog = versionCatalogs.named("libs")
+val errorProneCore = libsCatalog.findLibrary("errorProneCore").orElseThrow()
+val errorProneAnnotations = libsCatalog.findLibrary("errorProneAnnotations").orElseThrow();
+val nullAway = libsCatalog.findLibrary("nullAway").orElseThrow()
+val nullAwayAnnotations = libsCatalog.findLibrary("nullAwayAnnotations").orElseThrow()
+
+dependencies {
+ errorprone(errorProneCore)
+ errorprone(nullAway)
+ add("compileOnly", errorProneAnnotations)
+ add("compileOnly", nullAwayAnnotations)
+}
+
+tasks.withType().configureEach {
+ options.isFork = true
+ options.errorprone {
+ disableWarningsInGeneratedCode.set(true)
+ check("NullAway", CheckSeverity.ERROR)
+ option("NullAway:AnnotatedPackages", "com.mattbertolini")
+ }
+}
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
index c928c35..5e8ee91 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
@@ -3,6 +3,7 @@ package com.mattbertolini.buildlogic
plugins {
java
jacoco
+ id("com.mattbertolini.buildlogic.error-prone")
}
val versionCatalog = versionCatalogs.named("libs")
diff --git a/libs.versions.toml b/libs.versions.toml
index 00540e2..f8047b9 100644
--- a/libs.versions.toml
+++ b/libs.versions.toml
@@ -3,6 +3,8 @@ spring = "6.1.10" # Used in java-conventions.gradle.kts
springBoot = "3.3.1" # Used in java-conventions.gradle.kts
junit = "5.9.3" # Used in java-conventions.gradle.kts
jacoco = "0.8.10" # Used in java-conventions.gradle.kts
+errorProne = "2.29.0"
+nullAway = "0.11.0"
[libraries]
jakartaServletApi = { module = "jakarta.servlet:jakarta.servlet-api", version = "6.0.0" }
@@ -34,6 +36,11 @@ mockitoCore = { module = "org.mockito:mockito-core", version = "5.3.1" }
equalsVerifier = { module = "nl.jqno.equalsverifier:equalsverifier", version = "3.14.2" }
hamcrest = { module = "org.hamcrest:hamcrest", version = "2.2" }
+errorProneCore = { module = "com.google.errorprone:error_prone_core", version.ref = "errorProne" }
+errorProneAnnotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorProne"}
+nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
+nullAwayAnnotations = { module = "com.uber.nullaway:nullaway-annotations", version.ref = "nullAway" }
+
[plugins]
asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version = "3.3.2" }
sonarqube = { id = "org.sonarqube", version = "5.0.0.4638" }
\ No newline at end of file
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/AbstractPropertyResolverRegistry.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/AbstractPropertyResolverRegistry.java
index c466838..46e1f64 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/AbstractPropertyResolverRegistry.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/AbstractPropertyResolverRegistry.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2021 the original author or authors.
+ * Copyright 2024 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 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import com.mattbertolini.spring.web.bind.resolver.RequestPropertyResolverBase;
-import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import java.util.Collections;
@@ -38,7 +37,7 @@ protected AbstractPropertyResolverRegistry() {
}
@Nullable
- public T findResolverFor(@NonNull BindingProperty bindingProperty) {
+ public T findResolverFor(BindingProperty bindingProperty) {
for (T resolver : propertyResolvers) {
if (resolver.supports(bindingProperty)) {
return resolver;
@@ -77,7 +76,6 @@ public void addResolvers(AbstractPropertyResolverRegistry registry) {
/**
* Returns an unmodifiable collection of the resolvers.
*/
- @NonNull
public Set getPropertyResolvers() {
return Collections.unmodifiableSet(propertyResolvers);
}
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/PropertyResolutionException.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/PropertyResolutionException.java
index 614bfae..74880d9 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/PropertyResolutionException.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/PropertyResolutionException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/RequestPropertyBindingException.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/RequestPropertyBindingException.java
index a5c553e..95a8af2 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/RequestPropertyBindingException.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/RequestPropertyBindingException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/package-info.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/package-info.java
new file mode 100644
index 0000000..084b600
--- /dev/null
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/package-info.java
@@ -0,0 +1,6 @@
+@NonNullApi
+@NonNullFields
+package com.mattbertolini.spring.web.bind.annotation;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/AnnotatedRequestBeanIntrospector.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/AnnotatedRequestBeanIntrospector.java
index 501ef87..2230333 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/AnnotatedRequestBeanIntrospector.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/AnnotatedRequestBeanIntrospector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2022 the original author or authors.
+ * Copyright 2024 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.
@@ -16,8 +16,6 @@
package com.mattbertolini.spring.web.bind.introspect;
-import org.springframework.lang.NonNull;
-
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
@@ -32,8 +30,7 @@ public interface AnnotatedRequestBeanIntrospector {
* @return A map of resolved property data. This map is never null but may be empty.
* @throws CircularReferenceException If a circular reference is found while traversing the object graph.
*/
- @NonNull
- Map getResolverMapFor(@NonNull Class> targetType);
+ Map getResolverMapFor(Class> targetType);
/**
* Creates a list of resolved property data for the given target class. This method traverses the object graph for
@@ -43,8 +40,7 @@ public interface AnnotatedRequestBeanIntrospector {
* @return A list of resolved property data. This list is never null but may be empty.
* @throws CircularReferenceException If a circular reference is found while traversing the object graph.
*/
- @NonNull
- default Collection getResolversFor(@NonNull Class> targetType) {
+ default Collection getResolversFor(Class> targetType) {
Map propertyData = getResolverMapFor(targetType);
return Collections.unmodifiableCollection(propertyData.values());
}
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/BindingProperty.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/BindingProperty.java
index 357e637..6c132d1 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/BindingProperty.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/BindingProperty.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -19,7 +19,6 @@
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.Property;
import org.springframework.core.convert.TypeDescriptor;
-import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import java.beans.PropertyDescriptor;
@@ -35,7 +34,7 @@ public final class BindingProperty {
private final TypeDescriptor typeDescriptor;
private final MethodParameter methodParameter;
- private BindingProperty(@NonNull TypeDescriptor typeDescriptor, @NonNull MethodParameter methodParameter) {
+ private BindingProperty(TypeDescriptor typeDescriptor, MethodParameter methodParameter) {
this.typeDescriptor = typeDescriptor;
this.methodParameter = methodParameter;
}
@@ -45,7 +44,6 @@ public T getAnnotation(Class annotationType) {
return typeDescriptor.getAnnotation(annotationType);
}
- @NonNull
public MethodParameter getMethodParameter() {
return methodParameter;
}
@@ -69,8 +67,7 @@ public boolean hasAnnotation(Class extends Annotation> annotationType) {
* @param propertyDescriptor The Java Beans PropertyDescriptor to create a BindingProperty for.
* @return A new BindingProperty object.
*/
- @NonNull
- public static BindingProperty forPropertyDescriptor(@NonNull PropertyDescriptor propertyDescriptor) {
+ public static BindingProperty forPropertyDescriptor(PropertyDescriptor propertyDescriptor) {
Property property = new Property(
propertyDescriptor.getPropertyType(),
propertyDescriptor.getReadMethod(),
@@ -86,8 +83,7 @@ public static BindingProperty forPropertyDescriptor(@NonNull PropertyDescriptor
* This method is more or less the same as found in {@link Property} but those are not exposed publicly so I
* needed to replicate it.
*/
- @NonNull
- private static MethodParameter resolveMethodParameter(@NonNull Property property) {
+ private static MethodParameter resolveMethodParameter(Property property) {
MethodParameter readMethodParameter = resolveReadMethodParameter(property);
MethodParameter writeMethodParameter = resolveWriteMethodParameter(property);
if (writeMethodParameter == null) {
@@ -107,7 +103,7 @@ private static MethodParameter resolveMethodParameter(@NonNull Property property
}
@Nullable
- private static MethodParameter resolveReadMethodParameter(@NonNull Property property) {
+ private static MethodParameter resolveReadMethodParameter(Property property) {
if (property.getReadMethod() == null) {
return null;
}
@@ -115,7 +111,7 @@ private static MethodParameter resolveReadMethodParameter(@NonNull Property prop
}
@Nullable
- private static MethodParameter resolveWriteMethodParameter(@NonNull Property property) {
+ private static MethodParameter resolveWriteMethodParameter(Property property) {
if (property.getWriteMethod() == null) {
return null;
}
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/package-info.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/package-info.java
new file mode 100644
index 0000000..4555f99
--- /dev/null
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/package-info.java
@@ -0,0 +1,6 @@
+@NonNullApi
+@NonNullFields
+package com.mattbertolini.spring.web.bind.introspect;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/package-info.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/package-info.java
new file mode 100644
index 0000000..adbe5e8
--- /dev/null
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/package-info.java
@@ -0,0 +1,6 @@
+@NonNullApi
+@NonNullFields
+package com.mattbertolini.spring.web.bind;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/AbstractNamedRequestPropertyResolver.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/AbstractNamedRequestPropertyResolver.java
index f66d9cd..a5f1c9a 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/AbstractNamedRequestPropertyResolver.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/AbstractNamedRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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,17 +17,18 @@
package com.mattbertolini.spring.web.bind.resolver;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
-import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
public abstract class AbstractNamedRequestPropertyResolver implements RequestPropertyResolverBase {
- @NonNull
- protected abstract String getName(@NonNull BindingProperty bindingProperty);
+ protected abstract String getName(BindingProperty bindingProperty);
@Override
- public final R resolve(@NonNull BindingProperty bindingProperty, @NonNull T request) {
+ @Nullable
+ public final R resolve(BindingProperty bindingProperty, T request) {
String name = getName(bindingProperty);
return resolveWithName(bindingProperty, name, request);
}
- protected abstract R resolveWithName(@NonNull BindingProperty bindingProperty, String name, @NonNull T request);
+ @Nullable
+ protected abstract R resolveWithName(BindingProperty bindingProperty, String name, T request);
}
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/RequestPropertyResolverBase.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/RequestPropertyResolverBase.java
index 7543f4b..1f6b301 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/RequestPropertyResolverBase.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/RequestPropertyResolverBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/package-info.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/package-info.java
new file mode 100644
index 0000000..9668813
--- /dev/null
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/package-info.java
@@ -0,0 +1,6 @@
+@NonNullApi
+@NonNullFields
+package com.mattbertolini.spring.web.bind.resolver;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java
index 30fb14b..51e649e 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java
@@ -1,8 +1,25 @@
+/*
+ * Copyright 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.mattbertolini.spring.web.bind.support;
import org.springframework.lang.Nullable;
import org.springframework.validation.DataBinder;
+import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -17,4 +34,9 @@ public Object resolveValue(String name, Class> type) {
public Set getNames() {
return Set.copyOf(values.keySet());
}
+
+ @Override
+ public Map values() {
+ return Collections.unmodifiableMap(values);
+ }
}
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/package-info.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/package-info.java
index 7debe91..bf23899 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/package-info.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/package-info.java
@@ -1,4 +1,6 @@
@NonNullApi
+@NonNullFields
package com.mattbertolini.spring.web.bind.support;
import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/ResolvedPropertyDataTest.java b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/ResolvedPropertyDataTest.java
index 78a7f32..04f3c5f 100644
--- a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/ResolvedPropertyDataTest.java
+++ b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/ResolvedPropertyDataTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -21,7 +21,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.convert.TypeDescriptor;
-import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import java.beans.PropertyDescriptor;
@@ -69,22 +69,26 @@ void equalsContract() throws Exception {
private static class StubResolver implements RequestPropertyResolverBase {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
return false;
}
@Override
- public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull Object request) {
+ @Nullable
+ public Object resolve(BindingProperty bindingProperty, Object request) {
return null;
}
}
@SuppressWarnings("unused")
private static class TestingClass {
+ @Nullable
private String property;
+ @Nullable
private String another;
+ @Nullable
public String getProperty() {
return property;
}
@@ -93,6 +97,7 @@ public void setProperty(String property) {
this.property = property;
}
+ @Nullable
public String getAnother() {
return another;
}
diff --git a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/IgnoredBean.java b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/IgnoredBean.java
index 13fc9d6..45928cb 100644
--- a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/IgnoredBean.java
+++ b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/IgnoredBean.java
@@ -17,11 +17,14 @@
package com.mattbertolini.spring.web.bind.introspect.scan;
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
+import org.springframework.lang.Nullable;
public class IgnoredBean {
@RequestParameter("property")
+ @Nullable
private String property;
+ @Nullable
public String getProperty() {
return property;
}
diff --git a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/ScannedBean.java b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/ScannedBean.java
index e7092f2..b816ba3 100644
--- a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/ScannedBean.java
+++ b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/ScannedBean.java
@@ -18,12 +18,15 @@
import com.mattbertolini.spring.web.bind.annotation.RequestBean;
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
+import org.springframework.lang.Nullable;
@RequestBean
public class ScannedBean {
@RequestParameter("property")
+ @Nullable
private String property;
+ @Nullable
public String getProperty() {
return property;
}
diff --git a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/subbackage/SubpackageBean.java b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/subbackage/SubpackageBean.java
index 5b958a7..213030c 100644
--- a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/subbackage/SubpackageBean.java
+++ b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/subbackage/SubpackageBean.java
@@ -18,12 +18,15 @@
import com.mattbertolini.spring.web.bind.annotation.FormParameter;
import com.mattbertolini.spring.web.bind.annotation.RequestBean;
+import org.springframework.lang.Nullable;
@RequestBean
public class SubpackageBean {
@FormParameter("subpackage_property")
+ @Nullable
private String subpackageProperty;
+ @Nullable
public String getSubpackageProperty() {
return subpackageProperty;
}
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolver.java
index 73597b5..7c35fae 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolver.java
@@ -45,20 +45,19 @@ public class BeanParameterMethodArgumentResolver extends ModelAttributeMethodArg
private final AnnotatedRequestBeanIntrospector introspector;
public BeanParameterMethodArgumentResolver(
- @NonNull ReactiveAdapterRegistry adapterRegistry,
- @NonNull AnnotatedRequestBeanIntrospector introspector) {
+ ReactiveAdapterRegistry adapterRegistry,
+ AnnotatedRequestBeanIntrospector introspector) {
super(adapterRegistry, false);
this.introspector = introspector;
}
@Override
- public boolean supportsParameter(@NonNull MethodParameter parameter) {
+ public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(BeanParameter.class) && !BeanUtils.isSimpleProperty(parameter.getParameterType());
}
@Override
- @NonNull
- protected Mono constructAttribute(WebExchangeDataBinder binder, @NonNull ServerWebExchange exchange) {
+ protected Mono constructAttribute(WebExchangeDataBinder binder, ServerWebExchange exchange) {
Assert.state(binder.getTargetType() != null, "WebExchangeDataBinder must have a target type");
Collection propertyData = introspector.getResolversFor(Objects.requireNonNull(binder.getTargetType().getRawClass()));
return getValuesToBind(propertyData, exchange)
@@ -69,7 +68,7 @@ protected Mono constructAttribute(WebExchangeDataBinder binder, @NonNull S
@Override
@NonNull
- protected Mono bindRequestParameters(@NonNull WebExchangeDataBinder binder, @NonNull ServerWebExchange exchange) {
+ protected Mono bindRequestParameters(WebExchangeDataBinder binder, ServerWebExchange exchange) {
Assert.state(binder.getTarget() != null, "WebExchangeDataBinder must have a target object");
Collection propertyData = introspector.getResolversFor(binder.getTarget().getClass());
return getValuesToBind(propertyData, exchange)
@@ -78,8 +77,7 @@ protected Mono bindRequestParameters(@NonNull WebExchangeDataBinder binder
.then();
}
- @NonNull
- private Mono> getValuesToBind(@NonNull Collection propertyData, @NonNull ServerWebExchange exchange) {
+ private Mono> getValuesToBind(Collection propertyData, ServerWebExchange exchange) {
return Flux.fromIterable(propertyData).flatMap(data -> {
BindingProperty bindingProperty = data.getBindingProperty();
RequestPropertyResolver resolver = (RequestPropertyResolver) data.getResolver();
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java
index ff58e52..2e10d34 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/BinderConfiguration.java
@@ -37,7 +37,7 @@
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.ReactiveAdapterRegistry;
-import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
@@ -66,7 +66,7 @@ public BinderConfiguration() {
*
* @param propertyResolverRegistry The resolver registry to use.
*/
- public BinderConfiguration(@NonNull PropertyResolverRegistry propertyResolverRegistry) {
+ public BinderConfiguration(PropertyResolverRegistry propertyResolverRegistry) {
packagesToScan = new HashSet<>();
this.propertyResolverRegistry = propertyResolverRegistry;
}
@@ -136,7 +136,8 @@ public Set getPackagesToScan() {
}
@Override
- public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) {
+ @Nullable
+ public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (!(bean instanceof RequestMappingHandlerAdapter adapter)) {
return bean;
}
@@ -156,7 +157,7 @@ public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull Str
}
return adapter;
}
-
+
private PropertyResolverRegistry createPropertyResolverRegistry(RequestMappingHandlerAdapter adapter, ReactiveAdapterRegistry reactiveAdapterRegistry) {
PropertyResolverRegistry registry = new PropertyResolverRegistry();
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/package-info.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/package-info.java
new file mode 100644
index 0000000..9085987
--- /dev/null
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/package-info.java
@@ -0,0 +1,6 @@
+@NonNullApi
+@NonNullFields
+package com.mattbertolini.spring.web.reactive.bind.config;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/package-info.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/package-info.java
new file mode 100644
index 0000000..f3a18ef
--- /dev/null
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/package-info.java
@@ -0,0 +1,6 @@
+@NonNullApi
+@NonNullFields
+package com.mattbertolini.spring.web.reactive.bind;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolver.java
index dd2b40d..a1478ca 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -20,23 +20,24 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.springframework.http.HttpCookie;
import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import java.util.Objects;
+
public class CookieParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
return bindingProperty.hasAnnotation(CookieParameter.class);
}
@NonNull
@Override
- public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange exchange) {
+ public Mono resolve(BindingProperty bindingProperty, ServerWebExchange exchange) {
MultiValueMap cookies = exchange.getRequest().getCookies();
CookieParameter annotation = bindingProperty.getAnnotation(CookieParameter.class);
- Assert.state(annotation != null, "No CookieParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No CookieParameter annotation found on type");
HttpCookie cookie = cookies.getFirst(annotation.value());
if (HttpCookie.class.isAssignableFrom(bindingProperty.getType())) {
return Mono.justOrEmpty(cookie);
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterMapRequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterMapRequestPropertyResolver.java
index ac94982..0e3dd38 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterMapRequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterMapRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -29,7 +29,7 @@
public class FormParameterMapRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
FormParameter annotation = bindingProperty.getAnnotation(FormParameter.class);
return annotation != null && !StringUtils.hasText(annotation.value()) &&
Map.class.isAssignableFrom(bindingProperty.getType());
@@ -37,7 +37,7 @@ public boolean supports(@NonNull BindingProperty bindingProperty) {
@Override
@NonNull
- public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange exchange) {
+ public Mono resolve(BindingProperty bindingProperty, ServerWebExchange exchange) {
if (MultiValueMap.class.isAssignableFrom(bindingProperty.getType())) {
return exchange.getFormData().map(Function.identity());
}
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolver.java
index 749da08..4cd3ddf 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2021 the original author or authors.
+ * Copyright 2024 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.
@@ -21,26 +21,26 @@
import org.springframework.http.codec.multipart.FormFieldPart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.List;
+import java.util.Objects;
import java.util.stream.Collectors;
public class FormParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
FormParameter annotation = bindingProperty.getAnnotation(FormParameter.class);
return annotation != null && StringUtils.hasText(annotation.value());
}
@NonNull
@Override
- public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange exchange) {
+ public Mono resolve(BindingProperty bindingProperty, ServerWebExchange exchange) {
FormParameter annotation = bindingProperty.getAnnotation(FormParameter.class);
- Assert.state(annotation != null, "No FormParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No FormParameter annotation found on type");
return exchange.getMultipartData()
.filter(multipartData -> multipartData.getFirst(annotation.value()) != null)
.map(multipartData -> multipartData.get(annotation.value()))
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterMapRequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterMapRequestPropertyResolver.java
index 42f3c47..1561e76 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterMapRequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterMapRequestPropertyResolver.java
@@ -28,7 +28,7 @@
public class HeaderParameterMapRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
HeaderParameter annotation = bindingProperty.getAnnotation(HeaderParameter.class);
return annotation != null && !StringUtils.hasText(annotation.value()) &&
Map.class.isAssignableFrom(bindingProperty.getType());
@@ -36,7 +36,7 @@ public boolean supports(@NonNull BindingProperty bindingProperty) {
@Override
@NonNull
- public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange exchange) {
+ public Mono resolve(BindingProperty bindingProperty, ServerWebExchange exchange) {
// HttpHeaders class extends from MultiValueMap
if (MultiValueMap.class.isAssignableFrom(bindingProperty.getType())) {
return Mono.just(exchange.getRequest().getHeaders());
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolver.java
index 4d80411..b2a5960 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -25,6 +25,8 @@
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import java.util.Objects;
+
public class HeaderParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
public boolean supports(@NonNull BindingProperty bindingProperty) {
@@ -34,10 +36,10 @@ public boolean supports(@NonNull BindingProperty bindingProperty) {
@Override
@NonNull
- public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange request) {
+ public Mono resolve(BindingProperty bindingProperty, ServerWebExchange request) {
HttpHeaders headers = request.getRequest().getHeaders();
HeaderParameter annotation = bindingProperty.getAnnotation(HeaderParameter.class);
- Assert.state(annotation != null, "No HeaderParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No HeaderParameter annotation found on type");
return Mono.justOrEmpty(headers.get(annotation.value()));
}
}
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolver.java
index fc8ff2e..5728a6e 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -19,7 +19,6 @@
import com.mattbertolini.spring.web.bind.annotation.PathParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.server.ServerWebExchange;
@@ -27,6 +26,7 @@
import java.util.Collections;
import java.util.Map;
+import java.util.Objects;
public class PathParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
@@ -39,7 +39,7 @@ public boolean supports(@NonNull BindingProperty bindingProperty) {
@Override
public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange exchange) {
PathParameter annotation = bindingProperty.getAnnotation(PathParameter.class);
- Assert.state(annotation != null, "No PathParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No PathParameter annotation found on type");
Map pathVariables = exchange.getAttributeOrDefault(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, Collections.emptyMap());
return Mono.justOrEmpty(pathVariables.get(annotation.value()));
}
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolver.java
index d56bca2..5691b69 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -19,12 +19,13 @@
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import java.util.Objects;
+
public class RequestParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
public boolean supports(@NonNull BindingProperty bindingProperty) {
@@ -36,7 +37,7 @@ public boolean supports(@NonNull BindingProperty bindingProperty) {
@Override
public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange serverWebExchange) {
RequestParameter annotation = bindingProperty.getAnnotation(RequestParameter.class);
- Assert.state(annotation != null, "No RequestParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No RequestParameter annotation found on type");
MultiValueMap queryParams = serverWebExchange.getRequest().getQueryParams();
return Mono.justOrEmpty(queryParams.get(annotation.value()));
}
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestPropertyResolver.java
index ad9e7a3..d3ecd0e 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestPropertyResolver.java
@@ -27,6 +27,6 @@
*/
public interface RequestPropertyResolver extends RequestPropertyResolverBase> {
@Override
- @NonNull
- Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange request);
+ @NonNull // Explicitly setting NonNull as we are overriding a Nullable parent method
+ Mono resolve(BindingProperty bindingProperty, ServerWebExchange request);
}
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolver.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolver.java
index 0f97f5d..725eab3 100644
--- a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolver.java
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -19,24 +19,24 @@
import com.mattbertolini.spring.web.bind.annotation.SessionParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import java.util.Objects;
+
public class SessionParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
return bindingProperty.hasAnnotation(SessionParameter.class);
}
@NonNull
@Override
- public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange exchange) {
+ public Mono resolve(BindingProperty bindingProperty, ServerWebExchange exchange) {
SessionParameter annotation = bindingProperty.getAnnotation(SessionParameter.class);
- Assert.state(annotation != null, "No SessionParameter annotation found on type");
- //noinspection ReactiveStreamsNullableInLambdaInTransform
+ Objects.requireNonNull(annotation, "No SessionParameter annotation found on type");
return exchange.getSession()
.filter(session -> session.getAttribute(annotation.value()) != null)
- .map(session -> session.getAttribute(annotation.value()));
+ .mapNotNull(session -> session.getAttribute(annotation.value()));
}
}
diff --git a/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/package-info.java b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/package-info.java
new file mode 100644
index 0000000..1cfb3d1
--- /dev/null
+++ b/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/package-info.java
@@ -0,0 +1,6 @@
+@NonNullApi
+@NonNullFields
+package com.mattbertolini.spring.web.reactive.bind.resolver;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/PropertyResolverRegistry.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/PropertyResolverRegistry.java
index 88dc526..5f96ef0 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/PropertyResolverRegistry.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/PropertyResolverRegistry.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/BinderConfiguration.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/BinderConfiguration.java
index e331223..62c9416 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/BinderConfiguration.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/BinderConfiguration.java
@@ -36,7 +36,7 @@
import com.mattbertolini.spring.web.servlet.mvc.bind.resolver.SessionParameterRequestPropertyResolver;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
@@ -90,7 +90,8 @@ public Set getPackagesToScan() {
}
@Override
- public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) {
+ @Nullable
+ public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (!(bean instanceof RequestMappingHandlerAdapter adapter)) {
return bean;
}
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/package-info.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/package-info.java
new file mode 100644
index 0000000..08c1dff
--- /dev/null
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/package-info.java
@@ -0,0 +1,6 @@
+@NonNullApi
+@NonNullFields
+package com.mattbertolini.spring.web.servlet.mvc.bind.config;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/package-info.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/package-info.java
index a382391..c479976 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/package-info.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/package-info.java
@@ -1,4 +1,6 @@
@NonNullApi
+@NonNullFields
package com.mattbertolini.spring.web.servlet.mvc.bind;
import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java
index 12fa0fe..ddf7071 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolver.java
@@ -25,6 +25,8 @@
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.util.WebUtils;
+import java.util.Objects;
+
public class CookieParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
public boolean supports(BindingProperty bindingProperty) {
@@ -37,7 +39,7 @@ public Object resolve(BindingProperty bindingProperty, NativeWebRequest request)
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
Assert.state(servletRequest != null, "A HttpServletRequest is required for this resolver and none found.");
CookieParameter annotation = bindingProperty.getAnnotation(CookieParameter.class);
- Assert.state(annotation != null, "No CookieParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No CookieParameter annotation found on type");
Cookie cookie = WebUtils.getCookie(servletRequest, annotation.value());
if (cookie == null) {
return null;
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolver.java
index 10bd6cd..d95b75d 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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,22 +18,21 @@
import com.mattbertolini.spring.web.bind.annotation.FormParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
-import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
+import java.util.Objects;
+
public class FormParameterRequestPropertyResolver extends RequestParameterRequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
FormParameter annotation = bindingProperty.getAnnotation(FormParameter.class);
return annotation != null && StringUtils.hasText(annotation.value());
}
@Override
- @NonNull
- protected String getName(@NonNull BindingProperty bindingProperty) {
+ protected String getName(BindingProperty bindingProperty) {
FormParameter annotation = bindingProperty.getAnnotation(FormParameter.class);
- Assert.state(annotation != null, "No FormParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No FormParameter annotation found on type");
return annotation.value();
}
}
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterRequestPropertyResolver.java
index 7016e47..716dc49 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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,26 +18,30 @@
import com.mattbertolini.spring.web.bind.annotation.HeaderParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
-import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
+import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.NativeWebRequest;
+import java.util.Objects;
+
/**
+ * Resolve HTTP header values
+ *
* @see NativeWebRequest#getHeaderValues(String)
*/
public class HeaderParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
HeaderParameter annotation = bindingProperty.getAnnotation(HeaderParameter.class);
return annotation != null && StringUtils.hasText(annotation.value());
}
@Override
- public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeWebRequest request) {
+ @Nullable
+ public Object resolve(BindingProperty bindingProperty, NativeWebRequest request) {
HeaderParameter annotation = bindingProperty.getAnnotation(HeaderParameter.class);
- Assert.state(annotation != null, "No HeaderParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No HeaderParameter annotation found on type");
return request.getHeaderValues(annotation.value());
}
}
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/PathParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/PathParameterRequestPropertyResolver.java
index 9deef1d..fb6db43 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/PathParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/PathParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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,28 +18,29 @@
import com.mattbertolini.spring.web.bind.annotation.PathParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
-import org.springframework.lang.NonNull;
-import org.springframework.util.Assert;
+import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.servlet.HandlerMapping;
import java.util.Map;
+import java.util.Objects;
public class PathParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
PathParameter annotation = bindingProperty.getAnnotation(PathParameter.class);
return annotation != null && StringUtils.hasText(annotation.value());
}
@SuppressWarnings("unchecked")
@Override
- public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeWebRequest request) {
+ @Nullable
+ public Object resolve(BindingProperty bindingProperty, NativeWebRequest request) {
PathParameter annotation = bindingProperty.getAnnotation(PathParameter.class);
- Assert.state(annotation != null, "No PathParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No PathParameter annotation found on type");
Map uriTemplateVariables = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
if (uriTemplateVariables == null) {
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolver.java
index a45064a..5e121ec 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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.
@@ -22,7 +22,7 @@
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.http.HttpMethod;
-import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.support.RequestContextUtils;
@@ -33,7 +33,7 @@
public class RequestContextRequestPropertyResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
Class> type = bindingProperty.getType();
return bindingProperty.hasAnnotation(RequestContext.class) && (
WebRequest.class.isAssignableFrom(type) ||
@@ -47,7 +47,8 @@ public boolean supports(@NonNull BindingProperty bindingProperty) {
}
@Override
- public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeWebRequest request) {
+ @Nullable
+ public Object resolve(BindingProperty bindingProperty, NativeWebRequest request) {
Class> type = bindingProperty.getType();
if (WebRequest.class.isAssignableFrom(type)) {
return request;
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java
index 240201d..7c08f48 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterMapRequestPropertyResolver.java
@@ -34,10 +34,10 @@
import org.springframework.web.multipart.support.MultipartResolutionDelegate;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
-import java.util.LinkedList;
import java.util.Map;
public class RequestParameterMapRequestPropertyResolver implements RequestPropertyResolver {
@@ -67,7 +67,7 @@ public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeW
Map parameterMap = request.getParameterMap();
MultiValueMap ret = new LinkedMultiValueMap<>(parameterMap.size());
for (Map.Entry entry : parameterMap.entrySet()) {
- ret.put(entry.getKey(), new LinkedList<>(Arrays.asList(entry.getValue())));
+ ret.put(entry.getKey(), new ArrayList<>(Arrays.asList(entry.getValue())));
}
return ret;
}
@@ -107,7 +107,7 @@ public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeW
}
}
- private LinkedHashMap, ?> resolveServletRequestPartsToMap(NativeWebRequest request) {
+ private Map, ?> resolveServletRequestPartsToMap(NativeWebRequest request) {
try {
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
if (servletRequest != null && MultipartResolutionDelegate.isMultipartRequest(servletRequest)) {
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java
index bb096cc..eb78acb 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestParameterRequestPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2021 the original author or authors.
+ * Copyright 2024 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.
@@ -28,6 +28,8 @@
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.multipart.support.MultipartResolutionDelegate;
+import java.util.Objects;
+
public class RequestParameterRequestPropertyResolver extends AbstractNamedRequestPropertyResolver
implements RequestPropertyResolver {
@@ -39,7 +41,7 @@ public boolean supports(BindingProperty bindingProperty) {
@Override
@Nullable
- protected Object resolveWithName(@NonNull BindingProperty bindingProperty, String name, @NonNull NativeWebRequest request) {
+ protected Object resolveWithName(BindingProperty bindingProperty, String name, NativeWebRequest request) {
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
if (servletRequest != null) {
try {
@@ -58,7 +60,7 @@ protected Object resolveWithName(@NonNull BindingProperty bindingProperty, Strin
@Override
protected String getName(BindingProperty bindingProperty) {
RequestParameter annotation = bindingProperty.getAnnotation(RequestParameter.class);
- Assert.state(annotation != null, "No RequestParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No RequestParameter annotation found on type");
return annotation.value();
}
}
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolver.java
index 7f3c7f4..9d58123 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolver.java
@@ -18,12 +18,12 @@
import com.mattbertolini.spring.web.bind.annotation.SessionParameter;
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
-import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
-import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
+import java.util.Objects;
+
public class SessionParameterRequestPropertyResolver implements RequestPropertyResolver {
@Override
public boolean supports(BindingProperty bindingProperty) {
@@ -34,7 +34,7 @@ public boolean supports(BindingProperty bindingProperty) {
@Nullable
public Object resolve(BindingProperty bindingProperty, NativeWebRequest request) {
SessionParameter annotation = bindingProperty.getAnnotation(SessionParameter.class);
- Assert.state(annotation != null, "No SessionParameter annotation found on type");
+ Objects.requireNonNull(annotation, "No SessionParameter annotation found on type");
return request.getAttribute(annotation.value(), RequestAttributes.SCOPE_SESSION);
}
}
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/package-info.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/package-info.java
index 3319042..1bbe7ff 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/package-info.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/package-info.java
@@ -1,4 +1,6 @@
@NonNullApi
+@NonNullFields
package com.mattbertolini.spring.web.servlet.mvc.bind.resolver;
import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
From 4b365aa34adba8add87d322951f429dd50ee7595 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Wed, 17 Jul 2024 21:18:37 -0400
Subject: [PATCH 05/33] More NullAway support
---
.../buildlogic/error-prone.gradle.kts | 7 +++++--
docs/build.gradle.kts | 3 ++-
.../web/bind/docs/CustomRequestBean.java | 19 +++++++++++++++++++
.../spring/web/bind/docs/NestedBean.java | 3 +++
.../build.gradle.kts | 1 +
.../AbstractPropertyResolverRegistryTest.java | 3 +++
.../bind/introspect/BindingPropertyTest.java | 11 ++++++++++-
...tAnnotatedRequestBeanIntrospectorTest.java | 14 ++++++++++++--
...tractNamedRequestPropertyResolverTest.java | 3 +++
...anParameterMethodArgumentResolverTest.java | 11 +++++++++--
.../web/reactive/bind/MockBindingContext.java | 6 +++++-
.../bind/MockWebExchangeDataBinder.java | 1 +
...eParameterRequestPropertyResolverTest.java | 7 +++++++
...mParameterRequestPropertyResolverTest.java | 11 +++++++++++
...rameterMapRequestPropertyResolverTest.java | 13 +++++++++++++
...tParameterRequestPropertyResolverTest.java | 9 +++++++++
...nParameterRequestPropertyResolverTest.java | 5 +++++
.../servlet/mvc/bind/MockWebDataBinder.java | 1 +
.../WebFluxBinderAutoConfiguration.java | 3 ++-
.../WebMvcBinderAutoConfiguration.java | 3 ++-
20 files changed, 123 insertions(+), 11 deletions(-)
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/error-prone.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/error-prone.gradle.kts
index 6fa68c7..debf80f 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/error-prone.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/error-prone.gradle.kts
@@ -16,8 +16,11 @@ val nullAwayAnnotations = libsCatalog.findLibrary("nullAwayAnnotations").orElseT
dependencies {
errorprone(errorProneCore)
errorprone(nullAway)
- add("compileOnly", errorProneAnnotations)
- add("compileOnly", nullAwayAnnotations)
+}
+
+project.extensions.getByType().configureEach {
+ dependencies.add(compileOnlyConfigurationName, errorProneAnnotations)
+ dependencies.add(compileOnlyConfigurationName, nullAwayAnnotations)
}
tasks.withType().configureEach {
diff --git a/docs/build.gradle.kts b/docs/build.gradle.kts
index b318e2b..612632c 100644
--- a/docs/build.gradle.kts
+++ b/docs/build.gradle.kts
@@ -20,9 +20,10 @@ dependencies {
testImplementation(libs.assertJCore)
testImplementation(libs.mockitoCore)
testImplementation(libs.springTest)
- testCompileOnly(libs.hamcrest) // Needed for Spring mock MVC matchers
testImplementation(libs.jakartaWebsocketApi)
testImplementation(libs.jakartaWebsocketClientApi)
+ testCompileOnly(libs.hamcrest) // Needed for Spring mock MVC matchers
+ testCompileOnly(libs.findbugsJsr305)
}
tasks.named("asciidoctor").configure {
diff --git a/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/CustomRequestBean.java b/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/CustomRequestBean.java
index 014bbd6..5b84e05 100644
--- a/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/CustomRequestBean.java
+++ b/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/CustomRequestBean.java
@@ -25,6 +25,7 @@
import com.mattbertolini.spring.web.bind.annotation.RequestContext;
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
import com.mattbertolini.spring.web.bind.annotation.SessionParameter;
+import org.springframework.lang.Nullable;
import java.time.ZoneId;
import java.util.Locale;
@@ -37,6 +38,7 @@ public class CustomRequestBean {
// end::class[]
// Query parameters
+ @Nullable
// tag::queryParam[]
@RequestParameter("different_name")
private String queryParam;
@@ -44,6 +46,7 @@ public class CustomRequestBean {
// end::queryParam[]
// Form data
+ @Nullable
// tag::formParam[]
@FormParameter("form_data")
private String formData;
@@ -51,6 +54,7 @@ public class CustomRequestBean {
// end::formParam[]
// HTTP headers
+ @Nullable
// tag::headerParam[]
@HeaderParameter("X-Custom-Header")
private String headerValues;
@@ -58,6 +62,7 @@ public class CustomRequestBean {
// end::headerParam[]
// Spring MVC/WebFlux path variables
+ @Nullable
// tag::pathParam[]
@PathParameter("pathParam")
private Integer pathParam;
@@ -65,6 +70,7 @@ public class CustomRequestBean {
// end::pathParam[]
// HTTP cookie values
+ @Nullable
// tag::cookieParam[]
@CookieParameter("cookie_value")
private String cookieValue;
@@ -72,6 +78,7 @@ public class CustomRequestBean {
// end::cookieParam[]
// HTTP session attributes
+ @Nullable
// tag::sessionParam[]
@SessionParameter("sessionAttribute")
private String sessionAttribute;
@@ -79,16 +86,20 @@ public class CustomRequestBean {
// end::sessionParam[]
// Spring derived request scoped data like locale and time zone
+ @Nullable
@RequestContext
private Locale locale;
+ @Nullable
@RequestContext
private ZoneId timeZone;
// A nested Java bean with additional annotated properties
+ @Nullable
@BeanParameter
private NestedBean nestedBean;
+ @Nullable
// tag::queryParam[]
public String getQueryParam() {
return queryParam;
@@ -99,6 +110,7 @@ public void setQueryParam(String queryParam) {
}
// end::queryParam[]
+ @Nullable
// tag::formParam[]
public String getFormData() {
return formData;
@@ -109,6 +121,7 @@ public void setFormData(String formData) {
}
// end::formParam[]
+ @Nullable
// tag::headerParam[]
public String getHeaderValues() {
return headerValues;
@@ -119,6 +132,7 @@ public void setHeaderValues(String headerValues) {
}
// end::headerParam[]
+ @Nullable
// tag::pathParam[]
public Integer getPathParam() {
return pathParam;
@@ -129,6 +143,7 @@ public void setPathParam(Integer pathParam) {
}
// end::pathParam[]
+ @Nullable
// tag::cookieParam[]
public String getCookieValue() {
return cookieValue;
@@ -139,6 +154,7 @@ public void setCookieValue(String cookieValue) {
}
// end::cookieParam[]
+ @Nullable
// tag::sessionParam[]
public String getSessionAttribute() {
return sessionAttribute;
@@ -149,6 +165,7 @@ public void setSessionAttribute(String sessionAttribute) {
}
// end::sessionParam[]
+ @Nullable
public Locale getLocale() {
return locale;
}
@@ -157,6 +174,7 @@ public void setLocale(Locale locale) {
this.locale = locale;
}
+ @Nullable
public ZoneId getTimeZone() {
return timeZone;
}
@@ -165,6 +183,7 @@ public void setTimeZone(ZoneId timeZone) {
this.timeZone = timeZone;
}
+ @Nullable
public NestedBean getNestedBean() {
return nestedBean;
}
diff --git a/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/NestedBean.java b/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/NestedBean.java
index f56d300..2f76d52 100644
--- a/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/NestedBean.java
+++ b/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/NestedBean.java
@@ -17,11 +17,14 @@
package com.mattbertolini.spring.web.bind.docs;
import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
+import org.springframework.lang.Nullable;
public class NestedBean {
+ @Nullable
@RequestParameter("nested_request_param")
private String nestedRequestParameter;
+ @Nullable
public String getNestedRequestParameter() {
return nestedRequestParameter;
}
diff --git a/spring-annotated-data-binder-core/build.gradle.kts b/spring-annotated-data-binder-core/build.gradle.kts
index 9c88fce..df52b27 100644
--- a/spring-annotated-data-binder-core/build.gradle.kts
+++ b/spring-annotated-data-binder-core/build.gradle.kts
@@ -15,6 +15,7 @@ dependencies {
testImplementation(libs.mockitoCore)
testImplementation(libs.springTest)
testImplementation(libs.equalsVerifier)
+ testCompileOnly(libs.findbugsJsr305)
}
tasks.named("jar").configure {
diff --git a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/AbstractPropertyResolverRegistryTest.java b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/AbstractPropertyResolverRegistryTest.java
index 494e68e..75b0704 100644
--- a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/AbstractPropertyResolverRegistryTest.java
+++ b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/AbstractPropertyResolverRegistryTest.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.resolver.RequestPropertyResolverBase;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import java.beans.PropertyDescriptor;
import java.util.Collections;
@@ -100,8 +101,10 @@ private static class TestingRegistry extends AbstractPropertyResolverRegistry annotationType) {
}
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
return bindingProperty.hasAnnotation(annotationType);
}
@Override
- public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull Void request) {
+ @Nullable
+ public Object resolve(BindingProperty bindingProperty, Void request) {
// Don't need to worry about this method. No used in the introspector.
return null;
}
@@ -93,9 +95,11 @@ public FakeRegistry() {
@SuppressWarnings("unused")
private static class SimpleType {
+ @Nullable
@RequestParameter("data_param")
private String data;
+ @Nullable
public String getData() {
return data;
}
@@ -107,9 +111,11 @@ public void setData(String data) {
@SuppressWarnings("unused")
private static class OuterBean {
+ @Nullable
@BeanParameter
private InnerBean innerBean;
+ @Nullable
public InnerBean getInnerBean() {
return innerBean;
}
@@ -121,9 +127,11 @@ public void setInnerBean(InnerBean innerBean) {
@SuppressWarnings("unused")
private static class InnerBean {
+ @Nullable
@RequestParameter("inner_param")
private String inner;
+ @Nullable
public String getInner() {
return inner;
}
@@ -135,9 +143,11 @@ public void setInner(String inner) {
@SuppressWarnings("unused")
private static class CircularReference {
+ @Nullable
@BeanParameter
private CircularReference circularReference;
+ @Nullable
public CircularReference getCircularReference() {
return circularReference;
}
diff --git a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/resolver/AbstractNamedRequestPropertyResolverTest.java b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/resolver/AbstractNamedRequestPropertyResolverTest.java
index eef0b9a..94476ed 100644
--- a/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/resolver/AbstractNamedRequestPropertyResolverTest.java
+++ b/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/resolver/AbstractNamedRequestPropertyResolverTest.java
@@ -19,6 +19,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.junit.jupiter.api.Test;
import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import java.beans.PropertyDescriptor;
@@ -62,8 +63,10 @@ public boolean supports(@NonNull BindingProperty bindingProperty) {
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
private String property;
+ @Nullable
public String getProperty() {
return property;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
index 3578a75..aacee29 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
@@ -233,7 +233,9 @@ private MethodParameter createMethodParameter(String anAnnotatedMethod, Class>
}
private static class MockRequestPropertyResolver implements RequestPropertyResolver {
+ @Nullable
private final Object value;
+ @Nullable
private final RuntimeException exception;
private MockRequestPropertyResolver(@Nullable T value, @Nullable RuntimeException exception) {
@@ -242,14 +244,14 @@ private MockRequestPropertyResolver(@Nullable T value, @Nullable RuntimeExce
}
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
// Not used in this test
return true;
}
@NonNull
@Override
- public Mono resolve(@NonNull BindingProperty bindingProperty, @NonNull ServerWebExchange exchange) {
+ public Mono resolve(BindingProperty bindingProperty, ServerWebExchange exchange) {
if (exception != null) {
throw exception;
}
@@ -306,10 +308,13 @@ public void withBindingResult(@BeanParameter @Validated ABeanClass aBeanClass, B
}
private static class ABeanClass {
+ @Nullable
private String propertyOne;
+ @Nullable
private Integer propertyTwo;
+ @Nullable
public String getPropertyOne() {
return propertyOne;
}
@@ -318,6 +323,8 @@ public void setPropertyOne(String propertyOne) {
this.propertyOne = propertyOne;
}
+ @SuppressWarnings("unused")
+ @Nullable
public Integer getPropertyTwo() {
return propertyTwo;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockBindingContext.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockBindingContext.java
index d55ed65..eb75abf 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockBindingContext.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockBindingContext.java
@@ -1,5 +1,6 @@
package com.mattbertolini.spring.web.reactive.bind;
+import com.uber.nullaway.annotations.Initializer;
import org.springframework.core.ResolvableType;
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
import org.springframework.lang.Nullable;
@@ -13,10 +14,12 @@
public class MockBindingContext extends BindingContext {
private final BindingAwareConcurrentModel model = new BindingAwareConcurrentModel();
private MockWebExchangeDataBinder dataBinder;
+ @Nullable
private BindingResult bindingResult;
@Override
- public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange, Object target, String name) {
+ @Initializer
+ public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange, @Nullable Object target, String name) {
dataBinder = new MockWebExchangeDataBinder(target);
if (bindingResult != null) {
@@ -31,6 +34,7 @@ public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange, Object
}
@Override
+ @Initializer
public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange, @Nullable Object target, String name, ResolvableType targetType) {
dataBinder = new MockWebExchangeDataBinder(target);
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java
index 293a137..a682e6d 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java
@@ -15,6 +15,7 @@ public class MockWebExchangeDataBinder extends WebExchangeDataBinder {
private boolean validateInvoked = true;
private PropertyValues pvs;
private List validationHints;
+ @Nullable
private BindingResult bindingResult;
public MockWebExchangeDataBinder(@Nullable Object target) {
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolverTest.java
index 5e3a698..ade20f3 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolverTest.java
@@ -21,6 +21,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpCookie;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import reactor.core.publisher.Mono;
@@ -105,14 +106,18 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@CookieParameter("the_cookie")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
@CookieParameter("the_cookie")
private HttpCookie cookieObject;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -121,6 +126,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
@@ -129,6 +135,7 @@ public void setNotAnnotated(String notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public HttpCookie getCookieObject() {
return cookieObject;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolverTest.java
index d028bf8..68664b9 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolverTest.java
@@ -31,6 +31,7 @@
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.MultipartHttpMessageWriter;
import org.springframework.http.codec.multipart.Part;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.client.reactive.MockClientHttpRequest;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
@@ -215,20 +216,26 @@ private String partContentToString(Part part) {
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@FormParameter("testing")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
@FormParameter("multiple_values")
private List multipleValues;
+ @Nullable
@FormParameter
private String missingValue;
+ @Nullable
@FormParameter("file")
private Part multipartValue;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -237,6 +244,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
@@ -245,6 +253,7 @@ public void setNotAnnotated(String notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public List getMultipleValues() {
return multipleValues;
}
@@ -253,6 +262,7 @@ public void setMultipleValues(List multipleValues) {
this.multipleValues = multipleValues;
}
+ @Nullable
public String getMissingValue() {
return missingValue;
}
@@ -261,6 +271,7 @@ public void setMissingValue(String missingValue) {
this.missingValue = missingValue;
}
+ @Nullable
public Part getMultipartValue() {
return multipartValue;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterMapRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterMapRequestPropertyResolverTest.java
index cafd7c4..14c2497 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterMapRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterMapRequestPropertyResolverTest.java
@@ -21,6 +21,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.util.MultiValueMap;
@@ -121,23 +122,30 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@HeaderParameter
private Map annotated;
+ @Nullable
private Map notAnnotated;
+ @Nullable
@HeaderParameter
private MultiValueMap multivalue;
+ @Nullable
@HeaderParameter
private HttpHeaders httpHeaders;
+ @Nullable
@HeaderParameter("irrelevant")
private String withValue;
+ @Nullable
@HeaderParameter
private String notAMap;
+ @Nullable
public Map getAnnotated() {
return annotated;
}
@@ -146,6 +154,7 @@ public void setAnnotated(Map annotated) {
this.annotated = annotated;
}
+ @Nullable
public Map getNotAnnotated() {
return notAnnotated;
}
@@ -154,6 +163,7 @@ public void setNotAnnotated(Map notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public MultiValueMap getMultivalue() {
return multivalue;
}
@@ -162,6 +172,7 @@ public void setMultivalue(MultiValueMap multivalue) {
this.multivalue = multivalue;
}
+ @Nullable
public HttpHeaders getHttpHeaders() {
return httpHeaders;
}
@@ -170,6 +181,7 @@ public void setHttpHeaders(HttpHeaders httpHeaders) {
this.httpHeaders = httpHeaders;
}
+ @Nullable
public String getWithValue() {
return withValue;
}
@@ -178,6 +190,7 @@ public void setWithValue(String withValue) {
this.withValue = withValue;
}
+ @Nullable
public String getNotAMap() {
return notAMap;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolverTest.java
index 6335480..499106b 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolverTest.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import reactor.core.publisher.Mono;
@@ -112,17 +113,22 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@RequestParameter("testing")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
@RequestParameter
private String missingValue;
+ @Nullable
@RequestParameter("multiple_values")
private List multipleValues;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -131,6 +137,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
@@ -139,6 +146,7 @@ public void setNotAnnotated(String notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public String getMissingValue() {
return missingValue;
}
@@ -147,6 +155,7 @@ public void setMissingValue(String missingValue) {
this.missingValue = missingValue;
}
+ @Nullable
public List getMultipleValues() {
return multipleValues;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolverTest.java
index afcf83f..289af60 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolverTest.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.mock.web.server.MockWebSession;
@@ -102,11 +103,14 @@ private BindingProperty bindingProperty(String propertyName) throws Introspectio
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@SessionParameter("sessionKey")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -115,6 +119,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java
index 3217523..a152e97 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java
@@ -13,6 +13,7 @@ public class MockWebDataBinder extends WebDataBinder {
private boolean validateInvoked = true;
private PropertyValues pvs;
private List validationHints;
+ @Nullable
private BindingResult bindingResult;
public MockWebDataBinder(@Nullable Object target) {
diff --git a/webflux-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/reactive/bind/autoconfigure/WebFluxBinderAutoConfiguration.java b/webflux-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/reactive/bind/autoconfigure/WebFluxBinderAutoConfiguration.java
index ca58901..395bf9e 100644
--- a/webflux-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/reactive/bind/autoconfigure/WebFluxBinderAutoConfiguration.java
+++ b/webflux-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/reactive/bind/autoconfigure/WebFluxBinderAutoConfiguration.java
@@ -29,6 +29,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Role;
+import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -39,7 +40,7 @@
@ConditionalOnMissingBean(BinderConfiguration.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class WebFluxBinderAutoConfiguration {
- private final List packagesToScan = new LinkedList<>();
+ private final List packagesToScan = new ArrayList<>();
private final Set customResolvers = new LinkedHashSet<>();
private final Set propertyResolverRegistries = new LinkedHashSet<>();
diff --git a/webmvc-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/autoconfigure/WebMvcBinderAutoConfiguration.java b/webmvc-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/autoconfigure/WebMvcBinderAutoConfiguration.java
index a4be734..4dd2976 100644
--- a/webmvc-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/autoconfigure/WebMvcBinderAutoConfiguration.java
+++ b/webmvc-annotated-data-binder-spring-boot-starter/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/autoconfigure/WebMvcBinderAutoConfiguration.java
@@ -29,6 +29,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Role;
+import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -39,7 +40,7 @@
@ConditionalOnMissingBean(BinderConfiguration.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class WebMvcBinderAutoConfiguration {
- private final List packagesToScan = new LinkedList<>();
+ private final List packagesToScan = new ArrayList<>();
private final Set customResolvers = new LinkedHashSet<>();
private final Set propertyResolverRegistries = new LinkedHashSet<>();
From 44739b33e2daf6c4ac67ce410eb648ec0e78f86b Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Wed, 17 Jul 2024 21:20:32 -0400
Subject: [PATCH 06/33] Gradle polish
---
.../com/mattbertolini/buildlogic/java-conventions.gradle.kts | 2 +-
.../com/mattbertolini/buildlogic/java-library.gradle.kts | 3 +--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
index 5e8ee91..82c5122 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
@@ -61,4 +61,4 @@ tasks.named("jacocoTestReport").configure {
}
}
-tasks.test { finalizedBy(tasks.jacocoTestReport) }
+tasks.named("test").configure { finalizedBy(tasks.jacocoTestReport) }
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-library.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-library.gradle.kts
index 96acfd0..271e920 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-library.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-library.gradle.kts
@@ -2,6 +2,5 @@ package com.mattbertolini.buildlogic
plugins {
`java-library`
+ id("com.mattbertolini.buildlogic.java-conventions")
}
-
-apply(plugin = "com.mattbertolini.buildlogic.java-conventions")
From 4242f9186b84bd5260bb76138269fefc03af8070 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Wed, 17 Jul 2024 21:22:17 -0400
Subject: [PATCH 07/33] Gradle polish
---
.../com/mattbertolini/buildlogic/java-conventions.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
index 82c5122..0edb384 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
@@ -61,4 +61,4 @@ tasks.named("jacocoTestReport").configure {
}
}
-tasks.named("test").configure { finalizedBy(tasks.jacocoTestReport) }
+tasks.named("test").configure { finalizedBy(tasks.named("jacocoTestReport")) }
From 1d6c55fcb3e3c457e26d0416ef8ff2b464043f0c Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Wed, 17 Jul 2024 21:22:35 -0400
Subject: [PATCH 08/33] Gradle polish
---
.../com/mattbertolini/buildlogic/java-conventions.gradle.kts | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
index 0edb384..45e280a 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
@@ -61,4 +61,6 @@ tasks.named("jacocoTestReport").configure {
}
}
-tasks.named("test").configure { finalizedBy(tasks.named("jacocoTestReport")) }
+tasks.named("test").configure {
+ finalizedBy(tasks.named("jacocoTestReport"))
+}
From 9c5bd1f11bd0e04395dea27ea047d37bcad2b256 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Wed, 17 Jul 2024 21:29:53 -0400
Subject: [PATCH 09/33] Gradle polish
---
.../com/mattbertolini/buildlogic/java-conventions.gradle.kts | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
index 45e280a..a7953b1 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
@@ -6,8 +6,6 @@ plugins {
id("com.mattbertolini.buildlogic.error-prone")
}
-val versionCatalog = versionCatalogs.named("libs")
-
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(JavaVersion.VERSION_17.majorVersion))
@@ -48,8 +46,9 @@ tasks.named("javadoc").configure {
}
}
+val versionCatalog = versionCatalogs.named("libs")
val jacocoVersion: String = versionCatalog.findVersion("jacoco").orElseThrow().toString()
-configure {
+jacoco {
toolVersion = jacocoVersion
}
From 3569d9b176bb84e4cf01a62fcb3fc3f44ac45030 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Wed, 17 Jul 2024 21:31:02 -0400
Subject: [PATCH 10/33] Gradle polish
---
.../com/mattbertolini/buildlogic/java-conventions.gradle.kts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
index a7953b1..4230816 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
@@ -6,6 +6,8 @@ plugins {
id("com.mattbertolini.buildlogic.error-prone")
}
+val versionCatalog = versionCatalogs.named("libs")
+
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(JavaVersion.VERSION_17.majorVersion))
@@ -46,7 +48,6 @@ tasks.named("javadoc").configure {
}
}
-val versionCatalog = versionCatalogs.named("libs")
val jacocoVersion: String = versionCatalog.findVersion("jacoco").orElseThrow().toString()
jacoco {
toolVersion = jacocoVersion
From 7ada3ce041b643a4448e94ccc67dad3f00524fb6 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Wed, 17 Jul 2024 21:39:25 -0400
Subject: [PATCH 11/33] More NullAway support
---
.../web/servlet/mvc/bind/PropertyResolverRegistryTest.java | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/PropertyResolverRegistryTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/PropertyResolverRegistryTest.java
index bc4964b..c96ea78 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/PropertyResolverRegistryTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/PropertyResolverRegistryTest.java
@@ -5,6 +5,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
import org.springframework.web.context.request.NativeWebRequest;
import java.util.Collections;
@@ -46,12 +47,13 @@ void addsResolversFromRegistry() {
private static class FakeResolver implements RequestPropertyResolver {
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
return false;
}
@Override
- public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeWebRequest request) {
+ @Nullable
+ public Object resolve(BindingProperty bindingProperty, NativeWebRequest request) {
return null;
}
}
From d03ce0a4f56b87e86d08632bbe2262f8cb7991b0 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Thu, 18 Jul 2024 21:34:40 -0400
Subject: [PATCH 12/33] More NullAway support
---
build.gradle.kts | 2 --
.../buildlogic/java-conventions.gradle.kts | 1 +
.../bind/MockWebExchangeDataBinder.java | 4 ++++
...rameterMapRequestPropertyResolverTest.java | 11 +++++++++++
...rParameterRequestPropertyResolverTest.java | 9 +++++++++
...rameterMapRequestPropertyResolverTest.java | 9 +++++++++
...hParameterRequestPropertyResolverTest.java | 7 +++++++
...equestBodyRequestPropertyResolverTest.java | 6 +++++-
...estContextRequestPropertyResolverTest.java | 19 +++++++++++++++++++
...rameterMapRequestPropertyResolverTest.java | 11 +++++++++++
...anParameterMethodArgumentResolverTest.java | 11 +++++++++--
.../servlet/mvc/bind/MockWebDataBinder.java | 6 ++++++
...eParameterRequestPropertyResolverTest.java | 7 +++++++
13 files changed, 98 insertions(+), 5 deletions(-)
diff --git a/build.gradle.kts b/build.gradle.kts
index 7cfa1e7..2deccc7 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -6,8 +6,6 @@ plugins {
}
allprojects {
- apply(plugin = "com.mattbertolini.buildlogic.project-conventions")
-
group = "com.mattbertolini"
version = "0.7.0-SNAPSHOT"
}
diff --git a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
index 4230816..9724867 100644
--- a/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/com/mattbertolini/buildlogic/java-conventions.gradle.kts
@@ -3,6 +3,7 @@ package com.mattbertolini.buildlogic
plugins {
java
jacoco
+ id("com.mattbertolini.buildlogic.project-conventions")
id("com.mattbertolini.buildlogic.error-prone")
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java
index a682e6d..0334793 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/MockWebExchangeDataBinder.java
@@ -1,5 +1,6 @@
package com.mattbertolini.spring.web.reactive.bind;
+import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.lang.Nullable;
import org.springframework.validation.BindingResult;
@@ -7,6 +8,7 @@
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -20,6 +22,8 @@ public class MockWebExchangeDataBinder extends WebExchangeDataBinder {
public MockWebExchangeDataBinder(@Nullable Object target) {
super(target);
+ pvs = new MutablePropertyValues();
+ validationHints = new ArrayList<>();
}
@Override
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterMapRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterMapRequestPropertyResolverTest.java
index 79864f2..b78388c 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterMapRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterMapRequestPropertyResolverTest.java
@@ -21,6 +21,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.util.MultiValueMap;
@@ -104,20 +105,26 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@FormParameter
private Map annotated;
+ @Nullable
private Map notAnnotated;
+ @Nullable
@FormParameter
private MultiValueMap multivalue;
+ @Nullable
@FormParameter("name")
private String withName;
+ @Nullable
@FormParameter
private String notAMap;
+ @Nullable
public Map getAnnotated() {
return annotated;
}
@@ -126,6 +133,7 @@ public void setAnnotated(Map annotated) {
this.annotated = annotated;
}
+ @Nullable
public Map getNotAnnotated() {
return notAnnotated;
}
@@ -134,6 +142,7 @@ public void setNotAnnotated(Map notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public MultiValueMap getMultivalue() {
return multivalue;
}
@@ -142,6 +151,7 @@ public void setMultivalue(MultiValueMap multivalue) {
this.multivalue = multivalue;
}
+ @Nullable
public String getWithName() {
return withName;
}
@@ -150,6 +160,7 @@ public void setWithName(String withName) {
this.withName = withName;
}
+ @Nullable
public String getNotAMap() {
return notAMap;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolverTest.java
index 062525a..8621a9e 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolverTest.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import reactor.core.publisher.Mono;
@@ -114,17 +115,22 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@HeaderParameter("X-HeaderName")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
@HeaderParameter
private String missingValue;
+ @Nullable
@HeaderParameter("X-Multiple")
private List multipleValues;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -133,6 +139,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
@@ -141,6 +148,7 @@ public void setNotAnnotated(String notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public String getMissingValue() {
return missingValue;
}
@@ -149,6 +157,7 @@ public void setMissingValue(String missingValue) {
this.missingValue = missingValue;
}
+ @Nullable
public List getMultipleValues() {
return multipleValues;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterMapRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterMapRequestPropertyResolverTest.java
index fcb14b1..82862f9 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterMapRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterMapRequestPropertyResolverTest.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.reactive.HandlerMapping;
@@ -103,17 +104,22 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@PathParameter
private Map annotated;
+ @Nullable
private Map notAnnotated;
+ @Nullable
@PathParameter("irrelevant")
private String withValue;
+ @Nullable
@PathParameter
private String notAMap;
+ @Nullable
public Map getAnnotated() {
return annotated;
}
@@ -122,6 +128,7 @@ public void setAnnotated(Map annotated) {
this.annotated = annotated;
}
+ @Nullable
public Map getNotAnnotated() {
return notAnnotated;
}
@@ -130,6 +137,7 @@ public void setNotAnnotated(Map notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public String getWithValue() {
return withValue;
}
@@ -138,6 +146,7 @@ public void setWithValue(String withValue) {
this.withValue = withValue;
}
+ @Nullable
public String getNotAMap() {
return notAMap;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolverTest.java
index 52d293d..28ae69b 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolverTest.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.reactive.HandlerMapping;
@@ -119,14 +120,18 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@PathParameter("pathParamName")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
@PathParameter
private String missingValue;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -135,6 +140,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
@@ -143,6 +149,7 @@ public void setNotAnnotated(String notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public String getMissingValue() {
return missingValue;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestBodyRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestBodyRequestPropertyResolverTest.java
index 32aede7..d6d339b 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestBodyRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestBodyRequestPropertyResolverTest.java
@@ -26,6 +26,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import reactor.core.publisher.Mono;
@@ -105,12 +106,14 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@RequestBody
private String annotated;
+ @Nullable
private String notAnnotated;
-
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -119,6 +122,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestContextRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestContextRequestPropertyResolverTest.java
index 00b17f2..2c9372b 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestContextRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestContextRequestPropertyResolverTest.java
@@ -23,6 +23,7 @@
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.mock.web.server.MockWebSession;
@@ -216,32 +217,42 @@ private static class NotKnown {}
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
private ServerWebExchange notAnnotated;
+ @Nullable
@RequestContext
private NotKnown notKnown;
+ @Nullable
@RequestContext
private ServerWebExchange serverWebExchange;
+ @Nullable
@RequestContext
private ServerHttpRequest serverHttpRequest;
+ @Nullable
@RequestContext
private WebSession webSession;
+ @Nullable
@RequestContext
private HttpMethod httpMethod;
+ @Nullable
@RequestContext
private Locale locale;
+ @Nullable
@RequestContext
private TimeZone timeZone;
+ @Nullable
@RequestContext
private ZoneId zoneId;
+ @Nullable
public ServerWebExchange getNotAnnotated() {
return notAnnotated;
}
@@ -250,6 +261,7 @@ public void setNotAnnotated(ServerWebExchange notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public NotKnown getNotKnown() {
return notKnown;
}
@@ -258,6 +270,7 @@ public void setNotKnown(NotKnown notKnown) {
this.notKnown = notKnown;
}
+ @Nullable
public ServerWebExchange getServerWebExchange() {
return serverWebExchange;
}
@@ -266,6 +279,7 @@ public void setServerWebExchange(ServerWebExchange serverWebExchange) {
this.serverWebExchange = serverWebExchange;
}
+ @Nullable
public ServerHttpRequest getServerHttpRequest() {
return serverHttpRequest;
}
@@ -274,6 +288,7 @@ public void setServerHttpRequest(ServerHttpRequest serverHttpRequest) {
this.serverHttpRequest = serverHttpRequest;
}
+ @Nullable
public WebSession getWebSession() {
return webSession;
}
@@ -282,6 +297,7 @@ public void setWebSession(WebSession webSession) {
this.webSession = webSession;
}
+ @Nullable
public HttpMethod getHttpMethod() {
return httpMethod;
}
@@ -290,6 +306,7 @@ public void setHttpMethod(HttpMethod httpMethod) {
this.httpMethod = httpMethod;
}
+ @Nullable
public Locale getLocale() {
return locale;
}
@@ -298,6 +315,7 @@ public void setLocale(Locale locale) {
this.locale = locale;
}
+ @Nullable
public TimeZone getTimeZone() {
return timeZone;
}
@@ -306,6 +324,7 @@ public void setTimeZone(TimeZone timeZone) {
this.timeZone = timeZone;
}
+ @Nullable
public ZoneId getZoneId() {
return zoneId;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterMapRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterMapRequestPropertyResolverTest.java
index 450576c..f27affb 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterMapRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterMapRequestPropertyResolverTest.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.util.MultiValueMap;
@@ -100,20 +101,26 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@RequestParameter
private Map annotated;
+ @Nullable
private Map notAnnotated;
+ @Nullable
@RequestParameter
private MultiValueMap multivalue;
+ @Nullable
@RequestParameter
private String notAMap;
+ @Nullable
@RequestParameter("irrelevant")
private Map valuePresent;
+ @Nullable
public Map getAnnotated() {
return annotated;
}
@@ -122,6 +129,7 @@ public void setAnnotated(Map annotated) {
this.annotated = annotated;
}
+ @Nullable
public Map getNotAnnotated() {
return notAnnotated;
}
@@ -130,6 +138,7 @@ public void setNotAnnotated(Map notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public MultiValueMap getMultivalue() {
return multivalue;
}
@@ -138,6 +147,7 @@ public void setMultivalue(MultiValueMap multivalue) {
this.multivalue = multivalue;
}
+ @Nullable
public String getNotAMap() {
return notAMap;
}
@@ -146,6 +156,7 @@ public void setNotAMap(String notAMap) {
this.notAMap = notAMap;
}
+ @Nullable
public Map getValuePresent() {
return valuePresent;
}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java
index d3b8d13..aef8d7c 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java
@@ -251,7 +251,9 @@ private MethodParameter createMethodParameter(String anAnnotatedMethod, Class>
}
private static class MockRequestPropertyResolver implements RequestPropertyResolver {
+ @Nullable
private final Object value;
+ @Nullable
private final RuntimeException exception;
private MockRequestPropertyResolver(@Nullable T value, @Nullable RuntimeException exception) {
@@ -260,13 +262,14 @@ private MockRequestPropertyResolver(@Nullable T value, @Nullable RuntimeExce
}
@Override
- public boolean supports(@NonNull BindingProperty bindingProperty) {
+ public boolean supports(BindingProperty bindingProperty) {
// Not used in this test
return true;
}
@Override
- public Object resolve(@NonNull BindingProperty bindingProperty, @NonNull NativeWebRequest request) {
+ @Nullable
+ public Object resolve(BindingProperty bindingProperty, NativeWebRequest request) {
if (exception != null) {
throw exception;
}
@@ -323,9 +326,12 @@ public void withBindingResult(@BeanParameter @Validated ABeanClass aBeanClass, B
}
private static class ABeanClass {
+ @Nullable
private String propertyOne;
+ @Nullable
private Integer propertyTwo;
+ @Nullable
public String getPropertyOne() {
return propertyOne;
}
@@ -334,6 +340,7 @@ public void setPropertyOne(String propertyOne) {
this.propertyOne = propertyOne;
}
+ @Nullable
public Integer getPropertyTwo() {
return propertyTwo;
}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java
index a152e97..d6fa6b0 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinder.java
@@ -1,10 +1,12 @@
package com.mattbertolini.spring.web.servlet.mvc.bind;
+import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.lang.Nullable;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -18,10 +20,14 @@ public class MockWebDataBinder extends WebDataBinder {
public MockWebDataBinder(@Nullable Object target) {
super(target);
+ pvs = new MutablePropertyValues();
+ validationHints = new ArrayList<>();
}
public MockWebDataBinder(@Nullable Object target, String objectName) {
super(target, objectName);
+ pvs = new MutablePropertyValues();
+ validationHints = new ArrayList<>();
}
@Override
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java
index 80abe2a..9932fae 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java
@@ -21,6 +21,7 @@
import jakarta.servlet.http.Cookie;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
@@ -107,14 +108,18 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@CookieParameter("the_cookie")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
@CookieParameter("the_cookie")
private Cookie cookieObject;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -123,6 +128,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
@@ -131,6 +137,7 @@ public void setNotAnnotated(String notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public Cookie getCookieObject() {
return cookieObject;
}
From 2b83942dd443988a3bf92804cb12f5594af3079a Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Thu, 18 Jul 2024 21:44:40 -0400
Subject: [PATCH 13/33] More NullAway support
---
.../CachedAnnotatedRequestBeanIntrospector.java | 7 ++-----
...ScanningAnnotatedRequestBeanIntrospector.java | 10 ++++------
.../DefaultAnnotatedRequestBeanIntrospector.java | 16 +++++++---------
.../bind/introspect/ResolvedPropertyData.java | 12 ++++--------
.../BeanParameterMethodArgumentResolverTest.java | 2 +-
.../BeanParameterMethodArgumentResolverTest.java | 1 +
.../mvc/bind/MockWebDataBinderFactory.java | 1 +
...aderParameterRequestPropertyResolverTest.java | 9 +++++++++
...sionParameterRequestPropertyResolverTest.java | 5 +++++
9 files changed, 34 insertions(+), 29 deletions(-)
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/CachedAnnotatedRequestBeanIntrospector.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/CachedAnnotatedRequestBeanIntrospector.java
index 6ac201e..537f6b8 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/CachedAnnotatedRequestBeanIntrospector.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/CachedAnnotatedRequestBeanIntrospector.java
@@ -16,8 +16,6 @@
package com.mattbertolini.spring.web.bind.introspect;
-import org.springframework.lang.NonNull;
-
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -26,14 +24,13 @@ public class CachedAnnotatedRequestBeanIntrospector implements AnnotatedRequestB
private final AnnotatedRequestBeanIntrospector delegate;
private final ConcurrentMap, Map> cache;
- public CachedAnnotatedRequestBeanIntrospector(@NonNull AnnotatedRequestBeanIntrospector delegate) {
+ public CachedAnnotatedRequestBeanIntrospector(AnnotatedRequestBeanIntrospector delegate) {
this.delegate = delegate;
cache = new ConcurrentHashMap<>();
}
@Override
- @NonNull
- public Map getResolverMapFor(@NonNull Class> targetType) {
+ public Map getResolverMapFor(Class> targetType) {
return cache.computeIfAbsent(targetType, delegate::getResolverMapFor);
}
}
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/ClassPathScanningAnnotatedRequestBeanIntrospector.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/ClassPathScanningAnnotatedRequestBeanIntrospector.java
index 2a64fb4..961cff4 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/ClassPathScanningAnnotatedRequestBeanIntrospector.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/ClassPathScanningAnnotatedRequestBeanIntrospector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2022 the original author or authors.
+ * Copyright 2024 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.
@@ -23,7 +23,6 @@
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
-import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -39,7 +38,7 @@ public class ClassPathScanningAnnotatedRequestBeanIntrospector implements Annota
private final CachedAnnotatedRequestBeanIntrospector introspectorCache;
private final Set basePackages;
- public ClassPathScanningAnnotatedRequestBeanIntrospector(@NonNull AnnotatedRequestBeanIntrospector delegate, @Nullable Set basePackages) {
+ public ClassPathScanningAnnotatedRequestBeanIntrospector(AnnotatedRequestBeanIntrospector delegate, @Nullable Set basePackages) {
this.basePackages = new HashSet<>();
if (basePackages != null) {
this.basePackages.addAll(basePackages);
@@ -50,8 +49,7 @@ public ClassPathScanningAnnotatedRequestBeanIntrospector(@NonNull AnnotatedReque
}
@Override
- @NonNull
- public Map getResolverMapFor(@NonNull Class> targetType) {
+ public Map getResolverMapFor(Class> targetType) {
return introspectorCache.getResolverMapFor(targetType);
}
@@ -62,7 +60,7 @@ public void afterPropertiesSet() {
}
}
- private void scanAndLoadRequestBeans(@NonNull String basePackage) {
+ private void scanAndLoadRequestBeans(String basePackage) {
ClassLoader classLoader = ClassPathScanningAnnotatedRequestBeanIntrospector.class.getClassLoader();
LOGGER.debug("Searching for @RequestBean annotated classes in package [" + basePackage + "]");
Set candidateComponents = scanner.findCandidateComponents(basePackage);
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/DefaultAnnotatedRequestBeanIntrospector.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/DefaultAnnotatedRequestBeanIntrospector.java
index c7d04b9..5962946 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/DefaultAnnotatedRequestBeanIntrospector.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/DefaultAnnotatedRequestBeanIntrospector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2022 the original author or authors.
+ * Copyright 2024 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.
@@ -21,7 +21,6 @@
import com.mattbertolini.spring.web.bind.resolver.RequestPropertyResolverBase;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
-import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import java.beans.PropertyDescriptor;
@@ -39,7 +38,7 @@ public class DefaultAnnotatedRequestBeanIntrospector implements AnnotatedRequest
private final AbstractPropertyResolverRegistry> registry;
- public DefaultAnnotatedRequestBeanIntrospector(@NonNull AbstractPropertyResolverRegistry> registry) {
+ public DefaultAnnotatedRequestBeanIntrospector(AbstractPropertyResolverRegistry> registry) {
this.registry = registry;
}
@@ -52,18 +51,17 @@ public DefaultAnnotatedRequestBeanIntrospector(@NonNull AbstractPropertyResolver
* @throws CircularReferenceException If a circular reference is found while traversing the object graph.
*/
@Override
- @NonNull
- public Map getResolverMapFor(@NonNull Class> targetType) {
+ public Map getResolverMapFor(Class> targetType) {
Set> cycleClasses = new LinkedHashSet<>();
Map propertyData = new HashMap<>();
recursiveGetResolverMapFor(targetType, null, propertyData, cycleClasses);
return Collections.unmodifiableMap(propertyData);
}
- private void recursiveGetResolverMapFor(@NonNull final Class> targetType,
+ private void recursiveGetResolverMapFor(final Class> targetType,
@Nullable final String prefix,
- @NonNull Map propertyData,
- @NonNull final Set> cycleClasses) {
+ Map propertyData,
+ final Set> cycleClasses) {
PropertyDescriptor[] propertyDescriptors;
try {
propertyDescriptors = BeanUtils.getPropertyDescriptors(targetType);
@@ -102,7 +100,7 @@ private void recursiveGetResolverMapFor(@NonNull final Class> targetType,
* @param propertyDescriptor The property descriptor to find a name for. Required.
* @return The full property name path
*/
- private String getPropertyName(@Nullable String prefix, @NonNull PropertyDescriptor propertyDescriptor) {
+ private String getPropertyName(@Nullable String prefix, PropertyDescriptor propertyDescriptor) {
if (prefix == null) {
return propertyDescriptor.getName();
}
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/ResolvedPropertyData.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/ResolvedPropertyData.java
index d2e236c..074c118 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/ResolvedPropertyData.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/ResolvedPropertyData.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 the original author or authors.
+ * Copyright 2024 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,7 +17,6 @@
package com.mattbertolini.spring.web.bind.introspect;
import com.mattbertolini.spring.web.bind.resolver.RequestPropertyResolverBase;
-import org.springframework.lang.NonNull;
import java.util.Objects;
@@ -27,26 +26,23 @@ public final class ResolvedPropertyData {
private final RequestPropertyResolverBase, ?> resolver;
public ResolvedPropertyData(
- @NonNull String propertyName,
- @NonNull BindingProperty bindingProperty,
- @NonNull RequestPropertyResolverBase, ?> resolver
+ String propertyName,
+ BindingProperty bindingProperty,
+ RequestPropertyResolverBase, ?> resolver
) {
this.propertyName = propertyName;
this.bindingProperty = bindingProperty;
this.resolver = resolver;
}
- @NonNull
public String getPropertyName() {
return propertyName;
}
- @NonNull
public BindingProperty getBindingProperty() {
return bindingProperty;
}
- @NonNull
public RequestPropertyResolverBase, ?> getResolver() {
return resolver;
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
index aacee29..bdf0be8 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/BeanParameterMethodArgumentResolverTest.java
@@ -307,6 +307,7 @@ public void withBindingResult(@BeanParameter @Validated ABeanClass aBeanClass, B
}
}
+ @SuppressWarnings("unused")
private static class ABeanClass {
@Nullable
private String propertyOne;
@@ -323,7 +324,6 @@ public void setPropertyOne(String propertyOne) {
this.propertyOne = propertyOne;
}
- @SuppressWarnings("unused")
@Nullable
public Integer getPropertyTwo() {
return propertyTwo;
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java
index aef8d7c..9be2838 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolverTest.java
@@ -325,6 +325,7 @@ public void withBindingResult(@BeanParameter @Validated ABeanClass aBeanClass, B
}
}
+ @SuppressWarnings("unused")
private static class ABeanClass {
@Nullable
private String propertyOne;
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java
index eee8741..5d147a9 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java
@@ -10,6 +10,7 @@
public class MockWebDataBinderFactory implements WebDataBinderFactory {
private MockWebDataBinder binder;
+ @Nullable
private BindingResult bindingResult;
@Override
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterRequestPropertyResolverTest.java
index d625bc0..46e649d 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterRequestPropertyResolverTest.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.ServletWebRequest;
@@ -100,17 +101,22 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@HeaderParameter("X-HeaderName")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
@HeaderParameter
private String missingValue;
+ @Nullable
@HeaderParameter("X-Multiple")
private List multipleValues;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -119,6 +125,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
@@ -127,6 +134,7 @@ public void setNotAnnotated(String notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public String getMissingValue() {
return missingValue;
}
@@ -135,6 +143,7 @@ public void setMissingValue(String missingValue) {
this.missingValue = missingValue;
}
+ @Nullable
public List getMultipleValues() {
return multipleValues;
}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolverTest.java
index 72c7123..862e30a 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolverTest.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.web.context.request.ServletWebRequest;
@@ -91,11 +92,14 @@ private BindingProperty bindingProperty(String propertyName) throws Introspectio
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@SessionParameter("sessionKey")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -104,6 +108,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
From 270b27bcccd2782b6cc97945f17f7f52a56e73b4 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Thu, 18 Jul 2024 21:48:07 -0400
Subject: [PATCH 14/33] More NullAway support
---
...estContextRequestPropertyResolverTest.java | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolverTest.java
index 7b6f168..e3792d4 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestContextRequestPropertyResolverTest.java
@@ -24,6 +24,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod;
+import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.web.context.request.NativeWebRequest;
@@ -189,35 +190,46 @@ private static class NotKnown {}
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
private WebRequest notAnnotated;
+ @Nullable
@RequestContext
private NotKnown notKnown;
+ @Nullable
@RequestContext
private HttpServletRequest httpServletRequest;
+ @Nullable
@RequestContext
private ServletRequest servletRequest;
+ @Nullable
@RequestContext
private WebRequest webRequest;
+ @Nullable
@RequestContext
private HttpSession httpSession;
+ @Nullable
@RequestContext
private HttpMethod httpMethod;
+ @Nullable
@RequestContext
private Locale locale;
+ @Nullable
@RequestContext
private TimeZone timeZone;
+ @Nullable
@RequestContext
private ZoneId zoneId;
+ @Nullable
public WebRequest getNotAnnotated() {
return notAnnotated;
}
@@ -226,6 +238,7 @@ public void setNotAnnotated(WebRequest notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public NotKnown getNotKnown() {
return notKnown;
}
@@ -234,6 +247,7 @@ public void setNotKnown(NotKnown notKnown) {
this.notKnown = notKnown;
}
+ @Nullable
public HttpServletRequest getHttpServletRequest() {
return httpServletRequest;
}
@@ -242,6 +256,7 @@ public void setHttpServletRequest(HttpServletRequest httpServletRequest) {
this.httpServletRequest = httpServletRequest;
}
+ @Nullable
public ServletRequest getServletRequest() {
return servletRequest;
}
@@ -250,6 +265,7 @@ public void setServletRequest(ServletRequest servletRequest) {
this.servletRequest = servletRequest;
}
+ @Nullable
public WebRequest getWebRequest() {
return webRequest;
}
@@ -258,6 +274,7 @@ public void setWebRequest(WebRequest webRequest) {
this.webRequest = webRequest;
}
+ @Nullable
public HttpSession getHttpSession() {
return httpSession;
}
@@ -266,6 +283,7 @@ public void setHttpSession(HttpSession httpSession) {
this.httpSession = httpSession;
}
+ @Nullable
public HttpMethod getHttpMethod() {
return httpMethod;
}
@@ -274,6 +292,7 @@ public void setHttpMethod(HttpMethod httpMethod) {
this.httpMethod = httpMethod;
}
+ @Nullable
public Locale getLocale() {
return locale;
}
@@ -282,6 +301,7 @@ public void setLocale(Locale locale) {
this.locale = locale;
}
+ @Nullable
public TimeZone getTimeZone() {
return timeZone;
}
@@ -290,6 +310,7 @@ public void setTimeZone(TimeZone timeZone) {
this.timeZone = timeZone;
}
+ @Nullable
public ZoneId getZoneId() {
return zoneId;
}
From d4e84c3147e871325851dc99d6e9b7bc741515f2 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Fri, 19 Jul 2024 08:06:16 -0400
Subject: [PATCH 15/33] Docs updates
---
README.md | 2 +-
RELEASE_NOTES.md | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index e31bc4c..6a83ab5 100644
--- a/README.md
+++ b/README.md
@@ -166,7 +166,7 @@ public class ExampleConfiguration {
### Build Requirements
-* Java 17 or above to build. The release jars are compiled to Java 8 bytecode. Integration tests are compiled to Java 17 bytecode.
+* Java 17 or above to build and use.
To build:
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 2dec21b..b33d72c 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,8 +1,14 @@
# Release Notes
-## 0.7.0-SNAPSHOT
+## 1.0.0-SNAPSHOT
Released N/A
+- Breaking change
+- Updated to support Spring 6.x and Spring Boot 3.x. This brings with it a minimum Java version of 17. With the Spring
+ upgrade comes a switch to the Jakara EE Servlet API instead of Java EE.
+- Update build to Gradle 8.9
+- Added support for ErrorProne and NullAway for compile time checks of nullability.
+
## 0.6.0
Released 2023-12-01
From f3eb43922c48d2e63dae968e509b3e195db46371 Mon Sep 17 00:00:00 2001
From: Matt Bertolini
Date: Sun, 21 Jul 2024 21:35:01 -0400
Subject: [PATCH 16/33] More NullAway support
---
docs/build.gradle.kts | 1 +
integration-tests/build.gradle.kts | 2 ++
.../test/web/bind/PathParameterBean.java | 13 +++++++++++++
.../web/bind/PathParameterController.java | 6 ++++++
.../web/bind/support/MapValueResolver.java | 5 +++++
...eParameterRequestPropertyResolverTest.java | 2 +-
...mParameterRequestPropertyResolverTest.java | 2 +-
...rParameterRequestPropertyResolverTest.java | 2 +-
...hParameterRequestPropertyResolverTest.java | 2 +-
...tParameterRequestPropertyResolverTest.java | 2 +-
...nParameterRequestPropertyResolverTest.java | 2 +-
.../BeanParameterMethodArgumentResolver.java | 2 +-
.../mvc/bind/MockWebDataBinderFactory.java | 3 +++
...eParameterRequestPropertyResolverTest.java | 2 +-
...rameterMapRequestPropertyResolverTest.java | 19 +++++++++++++++++++
...mParameterRequestPropertyResolverTest.java | 15 ++++++++++++++-
...rameterMapRequestPropertyResolverTest.java | 13 +++++++++++++
...rParameterRequestPropertyResolverTest.java | 2 +-
...rameterMapRequestPropertyResolverTest.java | 9 +++++++++
...hParameterRequestPropertyResolverTest.java | 9 ++++++++-
...equestBodyRequestPropertyResolverTest.java | 5 +++++
...rameterMapRequestPropertyResolverTest.java | 19 +++++++++++++++++++
...tParameterRequestPropertyResolverTest.java | 15 ++++++++++++++-
...nParameterRequestPropertyResolverTest.java | 2 +-
24 files changed, 141 insertions(+), 13 deletions(-)
diff --git a/docs/build.gradle.kts b/docs/build.gradle.kts
index 612632c..330fa0c 100644
--- a/docs/build.gradle.kts
+++ b/docs/build.gradle.kts
@@ -13,6 +13,7 @@ dependencies {
implementation(project(":spring-webmvc-annotated-data-binder"))
implementation(project(":spring-webflux-annotated-data-binder"))
implementation(libs.jakartaServletApi) // Version defined in Spring BOM file
+ compileOnly(libs.findbugsJsr305)
add("asciidoctorExt", libs.springAsciidoctorExtBlockSwitch)
diff --git a/integration-tests/build.gradle.kts b/integration-tests/build.gradle.kts
index faeea26..7c89684 100644
--- a/integration-tests/build.gradle.kts
+++ b/integration-tests/build.gradle.kts
@@ -11,11 +11,13 @@ dependencies {
implementation(libs.jacksonDatabind)
implementation(libs.jakartaWebsocketApi)
implementation(libs.jakartaWebsocketClientApi)
+ compileOnly(libs.findbugsJsr305)
testImplementation(libs.junitJupiterApi)
testImplementation(libs.assertJCore)
testImplementation(libs.springTest)
testCompileOnly(libs.hamcrest) // Needed for Spring mock MVC matchers
+ testCompileOnly(libs.findbugsJsr305)
}
tasks.named("jacocoTestReport").configure {
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterBean.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterBean.java
index d035c99..ff02106 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterBean.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterBean.java
@@ -19,27 +19,35 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import com.mattbertolini.spring.web.bind.annotation.PathParameter;
import jakarta.validation.constraints.NotEmpty;
+import org.springframework.lang.Nullable;
import java.util.Map;
public class PathParameterBean {
+ @Nullable
@PathParameter("annotated_field")
private String annotatedField;
+ @Nullable
private String annotatedSetter;
+ @Nullable
private String annotatedGetter;
+ @Nullable
@PathParameter
private Map simpleMap;
+ @Nullable
@NotEmpty
@PathParameter("validated")
private String validated;
+ @Nullable
@BeanParameter
private NestedBean nestedBean;
+ @Nullable
public String getAnnotatedField() {
return annotatedField;
}
@@ -48,6 +56,7 @@ public void setAnnotatedField(String annotatedField) {
this.annotatedField = annotatedField;
}
+ @Nullable
public String getAnnotatedSetter() {
return annotatedSetter;
}
@@ -57,6 +66,7 @@ public void setAnnotatedSetter(String annotatedSetter) {
this.annotatedSetter = annotatedSetter;
}
+ @Nullable
@PathParameter("annotated_getter")
public String getAnnotatedGetter() {
return annotatedGetter;
@@ -66,6 +76,7 @@ public void setAnnotatedGetter(String annotatedGetter) {
this.annotatedGetter = annotatedGetter;
}
+ @Nullable
public Map getSimpleMap() {
return simpleMap;
}
@@ -74,6 +85,7 @@ public void setSimpleMap(Map simpleMap) {
this.simpleMap = simpleMap;
}
+ @Nullable
public String getValidated() {
return validated;
}
@@ -82,6 +94,7 @@ public void setValidated(String validated) {
this.validated = validated;
}
+ @Nullable
public NestedBean getNestedBean() {
return nestedBean;
}
diff --git a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterController.java b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterController.java
index 0d4c3cb..4768633 100644
--- a/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterController.java
+++ b/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/PathParameterController.java
@@ -20,6 +20,7 @@
import com.mattbertolini.spring.web.bind.annotation.BeanParameter;
import jakarta.validation.Valid;
import org.springframework.http.MediaType;
+import org.springframework.lang.Nullable;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -29,21 +30,25 @@
@SuppressWarnings("MVCPathVariableInspection")
@RestController
public class PathParameterController {
+ @Nullable
@GetMapping(value = "/annotatedField/{annotated_field}", produces = MediaType.TEXT_PLAIN_VALUE)
public String annotatedField(@BeanParameter PathParameterBean pathParameterBean) {
return pathParameterBean.getAnnotatedField();
}
+ @Nullable
@GetMapping(value = "/annotatedSetter/{annotated_setter}", produces = MediaType.TEXT_PLAIN_VALUE)
public String annotatedSetter(@BeanParameter PathParameterBean pathParameterBean) {
return pathParameterBean.getAnnotatedSetter();
}
+ @Nullable
@GetMapping(value = "/annotatedGetter/{annotated_getter}", produces = MediaType.TEXT_PLAIN_VALUE)
public String annotatedGetter(@BeanParameter PathParameterBean pathParameterBean) {
return pathParameterBean.getAnnotatedGetter();
}
+ @Nullable
@GetMapping(value = "/simpleMap/{simple_map}")
public String simpleMap(@BeanParameter PathParameterBean pathParameterBean) {
Map simpleMap = pathParameterBean.getSimpleMap();
@@ -55,6 +60,7 @@ public String bindingResult(@BeanParameter PathParameterBean pathParameterBean,
return Integer.toString(bindingResult.getErrorCount());
}
+ @Nullable
@GetMapping(value = {"/validated", "/validated/{validated}"}, produces = MediaType.TEXT_PLAIN_VALUE)
public String validated(@Valid @BeanParameter PathParameterBean pathParameterBean) {
return pathParameterBean.getValidated();
diff --git a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java
index 51e649e..0933c05 100644
--- a/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java
+++ b/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/MapValueResolver.java
@@ -23,6 +23,11 @@
import java.util.Map;
import java.util.Set;
+/**
+ * Implementation of the {@link DataBinder.ValueResolver} to assist in mapping binding data for constructor binding.
+ *
+ * @param values The Map of values to pass to the binder
+ */
public record MapValueResolver(Map values) implements DataBinder.ValueResolver {
@Override
@Nullable
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolverTest.java
index ade20f3..653bac1 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/CookieParameterRequestPropertyResolverTest.java
@@ -61,7 +61,7 @@ void throwsExceptionIfResolveCalledWithNoAnnotation() throws Exception {
.build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
BindingProperty bindingProperty = bindingProperty("notAnnotated");
- assertThatExceptionOfType(IllegalStateException.class)
+ assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> resolver.resolve(bindingProperty, exchange));
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolverTest.java
index 68664b9..52b31c2 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/FormParameterRequestPropertyResolverTest.java
@@ -90,7 +90,7 @@ void throwsExceptionIfResolveCalledWithNoAnnotation() throws Exception {
.build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
BindingProperty bindingProperty = bindingProperty("notAnnotated");
- assertThatExceptionOfType(IllegalStateException.class)
+ assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> resolver.resolve(bindingProperty, exchange));
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolverTest.java
index 8621a9e..3c6ef03 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/HeaderParameterRequestPropertyResolverTest.java
@@ -68,7 +68,7 @@ void throwsExceptionIfResolveCalledWithNoAnnotation() throws Exception {
.build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
BindingProperty bindingProperty = bindingProperty("notAnnotated");
- assertThatExceptionOfType(IllegalStateException.class)
+ assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> resolver.resolve(bindingProperty, exchange));
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolverTest.java
index 28ae69b..0b843f1 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/PathParameterRequestPropertyResolverTest.java
@@ -77,7 +77,7 @@ void throwsExceptionIfResolveCalledWithNoAnnotation() throws Exception {
.build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
BindingProperty bindingProperty = bindingProperty("notAnnotated");
- assertThatExceptionOfType(IllegalStateException.class)
+ assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> resolver.resolve(bindingProperty, exchange));
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolverTest.java
index 499106b..46867c1 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestParameterRequestPropertyResolverTest.java
@@ -67,7 +67,7 @@ void throwsExceptionIfResolveCalledWithNoAnnotation() throws Exception {
.build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
BindingProperty bindingProperty = bindingProperty("notAnnotated");
- assertThatExceptionOfType(IllegalStateException.class)
+ assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> resolver.resolve(bindingProperty, exchange));
}
diff --git a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolverTest.java b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolverTest.java
index 289af60..992d8d5 100644
--- a/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolverTest.java
+++ b/spring-webflux-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolverTest.java
@@ -59,7 +59,7 @@ void throwsExceptionIfResolveCalledWithNoAnnotation() throws Exception {
.build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
BindingProperty bindingProperty = bindingProperty("notAnnotated");
- assertThatExceptionOfType(IllegalStateException.class)
+ assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> resolver.resolve(bindingProperty, exchange));
}
diff --git a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java
index 01c3557..38c1c0f 100644
--- a/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java
+++ b/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/BeanParameterMethodArgumentResolver.java
@@ -72,7 +72,7 @@ protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest requ
@SuppressWarnings("unchecked")
private Map memoizedGetValuesToBind(Class> targetType, NativeWebRequest request) {
- Map memoizedValues = (Map) request.getAttribute(BIND_VALUES_ATTRIBUTE_KEY, NativeWebRequest.SCOPE_REQUEST);
+ /* Nullable */ Map memoizedValues = (Map) request.getAttribute(BIND_VALUES_ATTRIBUTE_KEY, NativeWebRequest.SCOPE_REQUEST);
if (memoizedValues != null) {
return memoizedValues;
}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java
index 5d147a9..c365a9b 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/MockWebDataBinderFactory.java
@@ -1,5 +1,6 @@
package com.mattbertolini.spring.web.servlet.mvc.bind;
+import com.uber.nullaway.annotations.Initializer;
import org.springframework.core.ResolvableType;
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
import org.springframework.lang.Nullable;
@@ -13,6 +14,7 @@ public class MockWebDataBinderFactory implements WebDataBinderFactory {
@Nullable
private BindingResult bindingResult;
+ @Initializer
@Override
public WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object target, String objectName, ResolvableType targetType) throws Exception {
binder = new MockWebDataBinder(target, objectName);
@@ -31,6 +33,7 @@ public WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object
return binder;
}
+ @Initializer
@Override
public WebDataBinder createBinder(NativeWebRequest webRequest, @Nullable Object target, String objectName) throws Exception {
binder = new MockWebDataBinder(target, objectName);
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java
index 9932fae..c50caf0 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/CookieParameterRequestPropertyResolverTest.java
@@ -64,7 +64,7 @@ void supportsReturnsFalseOnMissingAnnotation() throws Exception {
void throwsExceptionIfResolveCalledWithNoAnnotation() throws Exception {
// Unlikely to happen as the library always checks the supports method.
BindingProperty bindingProperty = bindingProperty("notAnnotated");
- assertThatExceptionOfType(IllegalStateException.class)
+ assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> resolver.resolve(bindingProperty, request));
}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterMapRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterMapRequestPropertyResolverTest.java
index b87facf..18d3c73 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterMapRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterMapRequestPropertyResolverTest.java
@@ -23,6 +23,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
+import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.mock.web.MockMultipartHttpServletRequest;
@@ -298,32 +299,42 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@FormParameter
private Map annotated;
+ @Nullable
private Map notAnnotated;
+ @Nullable
@FormParameter
private MultiValueMap multivalue;
+ @Nullable
@FormParameter("name")
private String withName;
+ @Nullable
@FormParameter
private String notAMap;
+ @Nullable
@FormParameter
private Map multipartFileMap;
+ @Nullable
@FormParameter
private MultiValueMap multiValueMultipartMap;
+ @Nullable
@FormParameter
private Map partMap;
+ @Nullable
@FormParameter
private MultiValueMap multiValuePartMap;
+ @Nullable
public Map getAnnotated() {
return annotated;
}
@@ -332,6 +343,7 @@ public void setAnnotated(Map annotated) {
this.annotated = annotated;
}
+ @Nullable
public Map getNotAnnotated() {
return notAnnotated;
}
@@ -340,6 +352,7 @@ public void setNotAnnotated(Map notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public MultiValueMap getMultivalue() {
return multivalue;
}
@@ -348,6 +361,7 @@ public void setMultivalue(MultiValueMap multivalue) {
this.multivalue = multivalue;
}
+ @Nullable
public String getWithName() {
return withName;
}
@@ -356,6 +370,7 @@ public void setWithName(String withName) {
this.withName = withName;
}
+ @Nullable
public String getNotAMap() {
return notAMap;
}
@@ -364,6 +379,7 @@ public void setNotAMap(String notAMap) {
this.notAMap = notAMap;
}
+ @Nullable
public Map getMultipartFileMap() {
return multipartFileMap;
}
@@ -372,6 +388,7 @@ public void setMultipartFileMap(Map multipartFileMap) {
this.multipartFileMap = multipartFileMap;
}
+ @Nullable
public MultiValueMap getMultiValueMultipartMap() {
return multiValueMultipartMap;
}
@@ -380,6 +397,7 @@ public void setMultiValueMultipartMap(MultiValueMap multi
this.multiValueMultipartMap = multiValueMultipartMap;
}
+ @Nullable
public Map getPartMap() {
return partMap;
}
@@ -388,6 +406,7 @@ public void setPartMap(Map partMap) {
this.partMap = partMap;
}
+ @Nullable
public MultiValueMap getMultiValuePartMap() {
return multiValuePartMap;
}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolverTest.java
index aa0845a..2f010e8 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolverTest.java
@@ -23,6 +23,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
+import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.mock.web.MockMultipartHttpServletRequest;
@@ -73,7 +74,7 @@ void supportsReturnsFalseOnMissingAnnotationValue() throws Exception {
void throwsExceptionIfResolveCalledWithNoAnnotation() throws Exception {
// Unlikely to happen as the library always checks the supports method.
BindingProperty bindingProperty = bindingProperty("notAnnotated");
- assertThatExceptionOfType(IllegalStateException.class)
+ assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> resolver.resolve(bindingProperty, request));
}
@@ -172,23 +173,30 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@FormParameter("testing")
private String annotated;
+ @Nullable
private String notAnnotated;
+ @Nullable
@FormParameter("multiple_values")
private List multipleValues;
+ @Nullable
@FormParameter
private String missingValue;
+ @Nullable
@FormParameter("multipart_file")
private MultipartFile multipartFile;
+ @Nullable
@FormParameter("part")
private Part part;
+ @Nullable
public String getAnnotated() {
return annotated;
}
@@ -197,6 +205,7 @@ public void setAnnotated(String annotated) {
this.annotated = annotated;
}
+ @Nullable
public String getNotAnnotated() {
return notAnnotated;
}
@@ -205,6 +214,7 @@ public void setNotAnnotated(String notAnnotated) {
this.notAnnotated = notAnnotated;
}
+ @Nullable
public List getMultipleValues() {
return multipleValues;
}
@@ -213,6 +223,7 @@ public void setMultipleValues(List multipleValues) {
this.multipleValues = multipleValues;
}
+ @Nullable
public String getMissingValue() {
return missingValue;
}
@@ -221,6 +232,7 @@ public void setMissingValue(String missingValue) {
this.missingValue = missingValue;
}
+ @Nullable
public MultipartFile getMultipartFile() {
return multipartFile;
}
@@ -229,6 +241,7 @@ public void setMultipartFile(MultipartFile multipartFile) {
this.multipartFile = multipartFile;
}
+ @Nullable
public Part getPart() {
return part;
}
diff --git a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterMapRequestPropertyResolverTest.java b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterMapRequestPropertyResolverTest.java
index 2ca33be..211474d 100644
--- a/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterMapRequestPropertyResolverTest.java
+++ b/spring-webmvc-annotated-data-binder/src/test/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/HeaderParameterMapRequestPropertyResolverTest.java
@@ -21,6 +21,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
+import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.util.MultiValueMap;
import org.springframework.web.context.request.NativeWebRequest;
@@ -130,23 +131,30 @@ private BindingProperty bindingProperty(String property) throws IntrospectionExc
@SuppressWarnings("unused")
private static class TestingBean {
+ @Nullable
@HeaderParameter
private Map annotated;
+ @Nullable
private Map notAnnotated;
+ @Nullable
@HeaderParameter
private MultiValueMap multivalue;
+ @Nullable
@HeaderParameter
private HttpHeaders httpHeaders;
+ @Nullable
@HeaderParameter("irrelevant")
private String withValue;
+ @Nullable
@HeaderParameter
private String notAMap;
+ @Nullable
public Map getAnnotated() {
return annotated;
}
@@ -155,6 +163,7 @@ public void setAnnotated(Map