├── .java-version
├── .git-blame-ignore-revs
├── .gitattributes
├── gradle.properties
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── libs.versions.toml
├── publish.sh
├── .gitignore
├── webflux-annotated-data-binder-spring-boot-starter
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── spring
│ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ │ └── java
│ │ └── com
│ │ └── mattbertolini
│ │ └── spring
│ │ └── web
│ │ └── reactive
│ │ └── bind
│ │ └── autoconfigure
│ │ └── WebFluxBinderAutoConfiguration.java
└── build.gradle.kts
├── webmvc-annotated-data-binder-spring-boot-starter
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── META-INF
│ │ │ │ └── spring
│ │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ │ └── java
│ │ │ └── com
│ │ │ └── mattbertolini
│ │ │ └── spring
│ │ │ └── web
│ │ │ └── servlet
│ │ │ └── mvc
│ │ │ └── bind
│ │ │ └── autoconfigure
│ │ │ └── WebMvcBinderAutoConfiguration.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── mattbertolini
│ │ └── spring
│ │ └── web
│ │ └── servlet
│ │ └── mvc
│ │ └── bind
│ │ └── autoconfigure
│ │ └── WebMvcBinderAutoConfigurationTest.java
└── build.gradle.kts
├── .github
└── workflows
│ ├── gradle-wrapper-validation.yml
│ └── build.yml
├── settings.gradle.kts
├── LICENSE_HEADER.txt
├── .editorconfig
├── spring-annotated-data-binder-core
├── src
│ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── mattbertolini
│ │ │ └── spring
│ │ │ └── web
│ │ │ └── bind
│ │ │ ├── package-info.java
│ │ │ ├── support
│ │ │ ├── package-info.java
│ │ │ └── MapValueResolver.java
│ │ │ ├── resolver
│ │ │ ├── package-info.java
│ │ │ ├── RequestPropertyResolverBase.java
│ │ │ └── AbstractNamedRequestPropertyResolver.java
│ │ │ ├── annotation
│ │ │ ├── package-info.java
│ │ │ ├── SessionParameter.java
│ │ │ ├── PathParameter.java
│ │ │ ├── RequestBean.java
│ │ │ ├── CookieParameter.java
│ │ │ ├── RequestBody.java
│ │ │ ├── HeaderParameter.java
│ │ │ ├── BeanParameter.java
│ │ │ ├── RequestContext.java
│ │ │ ├── FormParameter.java
│ │ │ └── RequestParameter.java
│ │ │ ├── introspect
│ │ │ ├── package-info.java
│ │ │ ├── RequestBeanIntrospectionException.java
│ │ │ ├── ResolvedPropertyData.java
│ │ │ ├── CircularReferenceException.java
│ │ │ ├── CachedAnnotatedRequestBeanIntrospector.java
│ │ │ └── AnnotatedRequestBeanIntrospector.java
│ │ │ ├── RequestPropertyBindingException.java
│ │ │ ├── PropertyResolutionException.java
│ │ │ └── AbstractPropertyResolverRegistry.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── mattbertolini
│ │ └── spring
│ │ └── web
│ │ └── bind
│ │ ├── introspect
│ │ └── scan
│ │ │ ├── IgnoredBean.java
│ │ │ ├── ScannedBean.java
│ │ │ └── subbackage
│ │ │ └── SubpackageBean.java
│ │ ├── support
│ │ └── MapValueResolverTest.java
│ │ └── resolver
│ │ └── AbstractNamedRequestPropertyResolverTest.java
└── build.gradle.kts
├── spring-webflux-annotated-data-binder
├── src
│ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── mattbertolini
│ │ │ └── spring
│ │ │ └── web
│ │ │ └── reactive
│ │ │ └── bind
│ │ │ ├── package-info.java
│ │ │ ├── config
│ │ │ └── package-info.java
│ │ │ ├── resolver
│ │ │ ├── package-info.java
│ │ │ ├── RequestPropertyResolver.java
│ │ │ ├── SessionParameterRequestPropertyResolver.java
│ │ │ ├── PathParameterMapRequestPropertyResolver.java
│ │ │ ├── HeaderParameterRequestPropertyResolver.java
│ │ │ ├── FormParameterMapRequestPropertyResolver.java
│ │ │ ├── HeaderParameterMapRequestPropertyResolver.java
│ │ │ ├── RequestParameterMapRequestPropertyResolver.java
│ │ │ ├── RequestParameterRequestPropertyResolver.java
│ │ │ ├── CookieParameterRequestPropertyResolver.java
│ │ │ ├── PathParameterRequestPropertyResolver.java
│ │ │ ├── FormParameterRequestPropertyResolver.java
│ │ │ └── RequestBodyRequestPropertyResolver.java
│ │ │ └── PropertyResolverRegistry.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── mattbertolini
│ │ └── spring
│ │ └── web
│ │ └── reactive
│ │ └── bind
│ │ ├── MockWebExchangeDataBinder.java
│ │ ├── PropertyResolverRegistryTest.java
│ │ └── MockBindingContext.java
└── build.gradle.kts
├── spring-webmvc-annotated-data-binder
├── src
│ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── mattbertolini
│ │ │ └── spring
│ │ │ └── web
│ │ │ └── servlet
│ │ │ └── mvc
│ │ │ └── bind
│ │ │ ├── package-info.java
│ │ │ ├── config
│ │ │ └── package-info.java
│ │ │ ├── resolver
│ │ │ ├── package-info.java
│ │ │ ├── RequestPropertyResolver.java
│ │ │ ├── FormParameterMapRequestPropertyResolver.java
│ │ │ ├── FormParameterRequestPropertyResolver.java
│ │ │ ├── SessionParameterRequestPropertyResolver.java
│ │ │ ├── HeaderParameterRequestPropertyResolver.java
│ │ │ ├── PathParameterMapRequestPropertyResolver.java
│ │ │ ├── PathParameterRequestPropertyResolver.java
│ │ │ ├── CookieParameterRequestPropertyResolver.java
│ │ │ ├── RequestBodyRequestPropertyResolver.java
│ │ │ ├── RequestParameterRequestPropertyResolver.java
│ │ │ └── HeaderParameterMapRequestPropertyResolver.java
│ │ │ └── PropertyResolverRegistry.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── mattbertolini
│ │ └── spring
│ │ └── web
│ │ └── servlet
│ │ └── mvc
│ │ └── bind
│ │ ├── resolver
│ │ └── ExceptionThrowingMockMultipartHttpServletRequest.java
│ │ ├── PropertyResolverRegistryTest.java
│ │ ├── MockWebDataBinder.java
│ │ └── MockWebDataBinderFactory.java
└── build.gradle.kts
├── docs
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── mattbertolini
│ │ │ │ └── spring
│ │ │ │ └── web
│ │ │ │ └── bind
│ │ │ │ └── docs
│ │ │ │ ├── ExampleService.java
│ │ │ │ ├── NestedBean.java
│ │ │ │ ├── ExampleController.java
│ │ │ │ ├── webflux
│ │ │ │ └── ExampleWebFluxContext.java
│ │ │ │ └── webmvc
│ │ │ │ └── ExampleMvcContext.java
│ │ └── resources
│ │ │ └── com
│ │ │ └── mattbertolini
│ │ │ └── spring
│ │ │ └── web
│ │ │ └── bind
│ │ │ └── docs
│ │ │ └── webmvc
│ │ │ └── example-context.xml
│ └── test
│ │ └── java
│ │ └── com
│ │ └── mattbertolini
│ │ └── spring
│ │ └── web
│ │ └── bind
│ │ └── docs
│ │ ├── webflux
│ │ └── WebFluxDocsJavaConfigIntegrationTest.java
│ │ └── webmvc
│ │ ├── WebMvcDocsJavaConfigIntegrationTest.java
│ │ └── WebMvcDocsXmlConfigIntegrationTest.java
└── build.gradle.kts
├── integration-tests
├── src
│ └── test
│ │ └── java
│ │ └── com
│ │ └── mattbertolini
│ │ └── spring
│ │ ├── test
│ │ └── web
│ │ │ └── bind
│ │ │ ├── records
│ │ │ ├── FormParameterRecord.java
│ │ │ ├── PathParameterRecord.java
│ │ │ ├── CookieParameterRecord.java
│ │ │ ├── HeaderParameterRecord.java
│ │ │ ├── RequestParameterRecord.java
│ │ │ ├── SessionParameterRecord.java
│ │ │ ├── RequestContextRecord.java
│ │ │ └── RequestBodyRecord.java
│ │ │ ├── JsonBody.java
│ │ │ ├── CookieParameterBean.java
│ │ │ ├── SessionParameterBean.java
│ │ │ ├── DirectFieldAccessBean.java
│ │ │ ├── PathParameterBean.java
│ │ │ ├── DirectFieldAccessController.java
│ │ │ ├── CookieParameterController.java
│ │ │ └── SessionParameterController.java
│ │ └── web
│ │ └── reactive
│ │ └── test
│ │ ├── SessionFilter.java
│ │ └── SessionMutator.java
└── build.gradle.kts
├── RELEASE_NOTES.md
└── gradlew.bat
/.java-version:
--------------------------------------------------------------------------------
1 | 17
2 |
3 |
--------------------------------------------------------------------------------
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
1 | # Update license year 2025
2 | a236fc3e5f121c109edcdd113f63618a5492dd5b
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
3 | *.bat text eol=crlf
4 | *.cmd text eol=crlf
5 |
6 | *.jar binary
7 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.parallel=true
2 | org.gradle.caching=true
3 | org.gradle.configuration-cache=true
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattbertolini/spring-annotated-web-data-binder/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/publish.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Disabling parallel builds as it doesn't work when publishing to Maven Central
4 | ./gradlew --no-parallel --no-configuration-cache build publish
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore Gradle project-specific cache directory
2 | .gradle/
3 |
4 | # Ignore IntelliJ files
5 | .idea/
6 |
7 | # Ignore Gradle build output directory
8 | build/
9 | !buildSrc/src/**/build
10 |
--------------------------------------------------------------------------------
/webflux-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | com.mattbertolini.spring.web.reactive.bind.autoconfigure.WebFluxBinderAutoConfiguration
2 |
--------------------------------------------------------------------------------
/webmvc-annotated-data-binder-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | com.mattbertolini.spring.web.servlet.mvc.bind.autoconfigure.WebMvcBinderAutoConfiguration
2 |
--------------------------------------------------------------------------------
/.github/workflows/gradle-wrapper-validation.yml:
--------------------------------------------------------------------------------
1 | name: "Validate Gradle Wrapper"
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | validation:
6 | name: "Validation"
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v4
10 | - uses: gradle/actions/wrapper-validation@v3
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "spring-annotated-web-data-binder"
2 |
3 | dependencyResolutionManagement {
4 | repositories {
5 | mavenCentral()
6 | }
7 | }
8 |
9 | include(":spring-annotated-data-binder-core")
10 | include(":spring-webmvc-annotated-data-binder")
11 | include(":spring-webflux-annotated-data-binder")
12 | include(":integration-tests")
13 | include(":docs")
14 | include(":webmvc-annotated-data-binder-spring-boot-starter")
15 | include(":webflux-annotated-data-binder-spring-boot-starter")
16 |
--------------------------------------------------------------------------------
/LICENSE_HEADER.txt:
--------------------------------------------------------------------------------
1 | Copyright ${year} the original author or authors.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 |
7 | [*.{java,gradle,gradle.kts}]
8 | indent_size = 4
9 | indent_style = space
10 | insert_final_newline = true
11 |
12 | [*.java]
13 | ij_java_class_count_to_use_import_on_demand = 999
14 | ij_java_names_count_to_use_import_on_demand = 999
15 |
16 | [*.{bat,cmd}]
17 | end_of_line = crlf
18 |
19 | [*.adoc]
20 | indent_size = 2
21 | indent_style = space
22 | insert_final_newline = true
23 | trim_trailing_whitespace = true
24 |
25 | [*.md]
26 | indent_size = 4
27 | indent_style = space
28 | trim_trailing_whitespace = false
29 |
30 | [*.{yml,yaml}]
31 | indent_style = space
32 | indent_size = 2
33 |
--------------------------------------------------------------------------------
/webmvc-annotated-data-binder-spring-boot-starter/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.mattbertolini.buildlogic.java-library")
3 | id("com.mattbertolini.buildlogic.maven-central-publish")
4 | }
5 |
6 | dependencies {
7 | api(project(":spring-webmvc-annotated-data-binder"))
8 | api(libs.springBootStarter)
9 |
10 | testImplementation(libs.junitJupiterApi)
11 | testImplementation(libs.assertJCore)
12 | testImplementation(libs.springTest)
13 | testImplementation(libs.springBootTest)
14 | }
15 |
16 | tasks.named("jar").configure {
17 | manifest {
18 | attributes(
19 | "Automatic-Module-Name" to "com.mattbertolini.spring.web.mvc.bind.autoconfigure"
20 | )
21 | }
22 | }
23 |
24 | mavenCentralPublish {
25 | name.set("Spring MVC Annotated Data Binder Spring Boot Starter")
26 | description.set("Spring Boot starter for Spring MVC Annotated Java Bean data binder")
27 | }
28 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.bind;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/support/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.bind.support;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.bind.resolver;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.reactive.bind;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.bind.annotation;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.bind.introspect;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.servlet.mvc.bind;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/config/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.reactive.bind.config;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/ExampleService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.docs;
17 |
18 | public class ExampleService {
19 | @SuppressWarnings("unused")
20 | public String doSomethingWith(CustomRequestBean customRequestBean) {
21 | return "";
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.reactive.bind.resolver;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/config/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.servlet.mvc.bind.config;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @NonNullApi
17 | @NonNullFields
18 | package com.mattbertolini.spring.web.servlet.mvc.bind.resolver;
19 |
20 | import org.springframework.lang.NonNullApi;
21 | import org.springframework.lang.NonNullFields;
22 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/records/FormParameterRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.test.web.bind.records;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.FormParameter;
19 |
20 | public record FormParameterRecord(
21 | @FormParameter("annotated_field") String annotated
22 | ) {}
23 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/records/PathParameterRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.test.web.bind.records;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.PathParameter;
19 |
20 | public record PathParameterRecord(
21 | @PathParameter("annotated_field") String annotated
22 | ) {}
23 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/records/CookieParameterRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.test.web.bind.records;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.CookieParameter;
19 |
20 | public record CookieParameterRecord(
21 | @CookieParameter("annotated_field") String annotated
22 | ) {}
23 |
--------------------------------------------------------------------------------
/webflux-annotated-data-binder-spring-boot-starter/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.mattbertolini.buildlogic.java-library")
3 | id("com.mattbertolini.buildlogic.maven-central-publish")
4 | }
5 |
6 | dependencies {
7 | api(project(":spring-webflux-annotated-data-binder"))
8 | api(libs.springBootStarter)
9 |
10 | testImplementation(libs.junitJupiterApi)
11 | testImplementation(libs.assertJCore)
12 | testImplementation(libs.springBootTest)
13 | testImplementation(libs.jakartaWebsocketClientApi)
14 | testImplementation(libs.jakartaWebsocketApi)
15 | }
16 |
17 | tasks.named("jar").configure {
18 | manifest {
19 | attributes(
20 | "Automatic-Module-Name" to "com.mattbertolini.spring.web.reactive.bind.autoconfigure"
21 | )
22 | }
23 | }
24 |
25 | mavenCentralPublish {
26 | name.set("Spring WebFlux Annotated Data Binder Spring Boot Starter")
27 | description.set("Spring Boot starter for Spring WebFlux Annotated Java Bean data binder")
28 | }
29 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/records/HeaderParameterRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.test.web.bind.records;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.HeaderParameter;
19 |
20 | public record HeaderParameterRecord(
21 | @HeaderParameter("x-annotated-field") String annotated
22 | ) {}
23 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/records/RequestParameterRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.test.web.bind.records;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
19 |
20 | public record RequestParameterRecord(
21 | @RequestParameter("annotated_field") String annotated
22 | ) {}
23 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/records/SessionParameterRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.test.web.bind.records;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.SessionParameter;
19 |
20 | public record SessionParameterRecord(
21 | @SessionParameter("annotated_field") String annotated
22 | ) {}
23 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/records/RequestContextRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.test.web.bind.records;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.RequestContext;
19 |
20 | import java.util.TimeZone;
21 |
22 | public record RequestContextRecord(
23 | @RequestContext TimeZone timeZone
24 | ) {}
25 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/RequestPropertyBindingException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind;
17 |
18 | public class RequestPropertyBindingException extends RuntimeException {
19 | public RequestPropertyBindingException(String message, Throwable cause) {
20 | super(message, cause);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/integration-tests/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.mattbertolini.buildlogic.java-conventions")
3 | }
4 |
5 | dependencies {
6 | implementation(project(":spring-webmvc-annotated-data-binder"))
7 | implementation(project(":spring-webflux-annotated-data-binder"))
8 | implementation(libs.jakartaServletApi)
9 | implementation(libs.hibernateValidator)
10 | implementation(libs.glassfishJakartaEl) // Needed by Hibernate Validator
11 | implementation(libs.jacksonDatabind)
12 | implementation(libs.jakartaWebsocketApi)
13 | implementation(libs.jakartaWebsocketClientApi)
14 | compileOnly(libs.findbugsJsr305)
15 |
16 | testImplementation(libs.junitJupiterApi)
17 | testImplementation(libs.assertJCore)
18 | testImplementation(libs.springTest)
19 | testCompileOnly(libs.hamcrest) // Needed for Spring mock MVC matchers
20 | testCompileOnly(libs.findbugsJsr305)
21 | }
22 |
23 | tasks.named("jacocoTestReport").configure {
24 | reports {
25 | html.required.set(false)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/records/RequestBodyRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.test.web.bind.records;
17 |
18 | import com.mattbertolini.spring.test.web.bind.JsonBody;
19 | import com.mattbertolini.spring.web.bind.annotation.RequestBody;
20 |
21 | public record RequestBodyRecord(
22 | @RequestBody JsonBody jsonBody
23 | ) {}
24 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/RequestBeanIntrospectionException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.introspect;
17 |
18 | public class RequestBeanIntrospectionException extends RuntimeException {
19 | public RequestBeanIntrospectionException(String message, Throwable cause) {
20 | super(message, cause);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/ResolvedPropertyData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.introspect;
17 |
18 | import com.mattbertolini.spring.web.bind.resolver.RequestPropertyResolverBase;
19 |
20 | public record ResolvedPropertyData(
21 | String propertyName,
22 | BindingProperty bindingProperty,
23 | RequestPropertyResolverBase, ?> resolver) {}
24 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/introspect/CircularReferenceException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.introspect;
17 |
18 | /**
19 | * Exception thrown when the introspector encounters a circular reference.
20 | */
21 | public class CircularReferenceException extends RuntimeException {
22 | public CircularReferenceException(String message) {
23 | super(message);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/PropertyResolutionException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind;
17 |
18 | /**
19 | * Exception thrown when a known exception is thrown during property resolution.
20 | */
21 | public class PropertyResolutionException extends RuntimeException {
22 | public PropertyResolutionException(String message, Throwable cause) {
23 | super(message, cause);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/PropertyResolverRegistry.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.reactive.bind;
17 |
18 | import com.mattbertolini.spring.web.bind.AbstractPropertyResolverRegistry;
19 | import com.mattbertolini.spring.web.reactive.bind.resolver.RequestPropertyResolver;
20 |
21 | public class PropertyResolverRegistry extends AbstractPropertyResolverRegistry {
22 | }
23 |
--------------------------------------------------------------------------------
/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/PropertyResolverRegistry.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.servlet.mvc.bind;
17 |
18 | import com.mattbertolini.spring.web.bind.AbstractPropertyResolverRegistry;
19 | import com.mattbertolini.spring.web.servlet.mvc.bind.resolver.RequestPropertyResolver;
20 |
21 | public class PropertyResolverRegistry extends AbstractPropertyResolverRegistry {
22 | }
23 |
--------------------------------------------------------------------------------
/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/RequestPropertyResolver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.servlet.mvc.bind.resolver;
17 |
18 | import com.mattbertolini.spring.web.bind.resolver.RequestPropertyResolverBase;
19 | import org.springframework.web.context.request.NativeWebRequest;
20 |
21 | public interface RequestPropertyResolver extends RequestPropertyResolverBase {
22 | }
23 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.mattbertolini.buildlogic.java-library")
3 | id("com.mattbertolini.buildlogic.maven-central-publish")
4 | }
5 |
6 | dependencies {
7 | api(libs.springContext)
8 | api(libs.springBeans)
9 | api(libs.springWeb)
10 | compileOnly(libs.findbugsJsr305) // To Prevent warnings on missing enum constants
11 | compileOnly(libs.jakartaServletApi) // So Javadoc doesn't give warnings about missing links
12 |
13 | testImplementation(libs.junitJupiterApi)
14 | testImplementation(libs.assertJCore)
15 | testImplementation(libs.mockitoCore)
16 | testImplementation(libs.springTest)
17 | testImplementation(libs.equalsVerifier)
18 | testCompileOnly(libs.findbugsJsr305)
19 | }
20 |
21 | tasks.named("jar").configure {
22 | manifest {
23 | attributes(
24 | "Automatic-Module-Name" to "com.mattbertolini.spring.web.bind"
25 | )
26 | }
27 | }
28 |
29 | mavenCentralPublish {
30 | name.set("Spring Annotated Data Binder Core")
31 | description.set("Core module for Spring annotated web data binder")
32 | }
33 |
--------------------------------------------------------------------------------
/spring-webflux-annotated-data-binder/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.mattbertolini.buildlogic.java-library")
3 | id("com.mattbertolini.buildlogic.maven-central-publish")
4 | }
5 |
6 | dependencies {
7 | api(project(":spring-annotated-data-binder-core"))
8 | api(libs.springWebflux)
9 | compileOnly(libs.findbugsJsr305) // To Prevent warnings on missing enum constants
10 |
11 | testImplementation(libs.junitJupiterApi)
12 | testImplementation(libs.assertJCore)
13 | testImplementation(libs.mockitoCore)
14 | testImplementation(libs.springTest)
15 | testImplementation(libs.jakartaValidationApi) // Used to test validation annotations
16 | testCompileOnly(libs.findbugsJsr305) // To Prevent warnings on missing enum constants
17 | }
18 |
19 | tasks.named("jar").configure {
20 | manifest {
21 | attributes(
22 | "Automatic-Module-Name" to "com.mattbertolini.spring.web.reactive.bind"
23 | )
24 | }
25 | }
26 |
27 | mavenCentralPublish {
28 | name.set("Spring WebFlux Annotated Data Binder")
29 | description.set("Annotated Java Bean data binder for Spring WebFlux")
30 | }
31 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: CI build
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | pull_request:
8 | branches:
9 | - '*'
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | jdk:
18 | - version: 17
19 | tasks: build jacocoTestReport testCodeCoverageReport
20 | - version: 21
21 | tasks: build jacocoTestReport testCodeCoverageReport sonar
22 | name: JDK ${{ matrix.jdk.version }}
23 | steps:
24 | - name: Checkout
25 | uses: actions/checkout@v4
26 | with:
27 | # This is needed for Sonar to do analysis
28 | fetch-depth: 0
29 |
30 | - name: Setup Java JDK
31 | uses: actions/setup-java@v4
32 | with:
33 | java-version: ${{ matrix.jdk.version }}
34 | distribution: 'temurin'
35 |
36 | - name: Setup Gradle
37 | uses: gradle/actions/setup-gradle@v3
38 |
39 | - name: Run Gradle
40 | env:
41 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
42 | run: ./gradlew -Dorg.gradle.welcome=never ${{ matrix.jdk.tasks }}
43 |
--------------------------------------------------------------------------------
/spring-webmvc-annotated-data-binder/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.mattbertolini.buildlogic.java-library")
3 | id("com.mattbertolini.buildlogic.maven-central-publish")
4 | }
5 |
6 | dependencies {
7 | api(project(":spring-annotated-data-binder-core"))
8 | api(libs.springWebmvc)
9 | implementation(libs.jakartaServletApi)
10 | compileOnly(libs.findbugsJsr305) // To Prevent warnings on missing enum constants
11 |
12 | testImplementation(libs.junitJupiterApi)
13 | testImplementation(libs.assertJCore)
14 | testImplementation(libs.mockitoCore)
15 | testImplementation(libs.springTest)
16 | testImplementation(libs.jakartaValidationApi) // Used to test validation annotations
17 | testCompileOnly(libs.findbugsJsr305) // To Prevent warnings on missing enum constants
18 | }
19 |
20 | tasks.named("jar").configure {
21 | manifest {
22 | attributes(
23 | "Automatic-Module-Name" to "com.mattbertolini.spring.web.servlet.mvc.bind"
24 | )
25 | }
26 | }
27 |
28 | mavenCentralPublish {
29 | name.set("Spring MVC Annotated Data Binder")
30 | description.set("Annotated Java Bean data binder for Spring MVC")
31 | }
32 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/IgnoredBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.introspect.scan;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
19 | import org.springframework.lang.Nullable;
20 |
21 | public class IgnoredBean {
22 | @RequestParameter("property")
23 | @Nullable
24 | private String property;
25 |
26 | @Nullable
27 | public String getProperty() {
28 | return property;
29 | }
30 |
31 | public void setProperty(String property) {
32 | this.property = property;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/NestedBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.docs;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
19 | import org.springframework.lang.Nullable;
20 |
21 | public class NestedBean {
22 | @Nullable
23 | @RequestParameter("nested_request_param")
24 | private String nestedRequestParameter;
25 |
26 | @Nullable
27 | public String getNestedRequestParameter() {
28 | return nestedRequestParameter;
29 | }
30 |
31 | public void setNestedRequestParameter(String nestedRequestParameter) {
32 | this.nestedRequestParameter = nestedRequestParameter;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/ScannedBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.introspect.scan;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.RequestBean;
19 | import com.mattbertolini.spring.web.bind.annotation.RequestParameter;
20 | import org.springframework.lang.Nullable;
21 |
22 | @RequestBean
23 | public class ScannedBean {
24 | @RequestParameter("property")
25 | @Nullable
26 | private String property;
27 |
28 | @Nullable
29 | public String getProperty() {
30 | return property;
31 | }
32 |
33 | public void setProperty(String property) {
34 | this.property = property;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/test/web/bind/JsonBody.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.test.web.bind;
17 |
18 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
19 | import com.fasterxml.jackson.annotation.JsonInclude;
20 | import com.fasterxml.jackson.annotation.JsonProperty;
21 | import org.springframework.lang.Nullable;
22 |
23 | @JsonIgnoreProperties(ignoreUnknown = true)
24 | @JsonInclude(JsonInclude.Include.NON_EMPTY)
25 | public class JsonBody {
26 | @Nullable
27 | @JsonProperty("json_property")
28 | private String property;
29 |
30 | @Nullable
31 | public String getProperty() {
32 | return property;
33 | }
34 |
35 | public void setProperty(String property) {
36 | this.property = property;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/introspect/scan/subbackage/SubpackageBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.introspect.scan.subbackage;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.FormParameter;
19 | import com.mattbertolini.spring.web.bind.annotation.RequestBean;
20 | import org.springframework.lang.Nullable;
21 |
22 | @RequestBean
23 | public class SubpackageBean {
24 | @FormParameter("subpackage_property")
25 | @Nullable
26 | private String subpackageProperty;
27 |
28 | @Nullable
29 | public String getSubpackageProperty() {
30 | return subpackageProperty;
31 | }
32 |
33 | public void setSubpackageProperty(String subpackageProperty) {
34 | this.subpackageProperty = subpackageProperty;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/RequestPropertyResolverBase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.resolver;
17 |
18 | import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
19 | import org.springframework.lang.Nullable;
20 |
21 | /**
22 | * This interface should be considered an internal interface and should not be implemented by external users. Instead,
23 | * use one of the sub-interfaces that are bound to a concrete request type.
24 | *
25 | * @param The request type to use with the resolver.
26 | * @param The response type to use.
27 | */
28 | public interface RequestPropertyResolverBase {
29 | boolean supports(BindingProperty bindingProperty);
30 |
31 | @Nullable
32 | R resolve(BindingProperty bindingProperty, T request);
33 | }
34 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/resolver/AbstractNamedRequestPropertyResolver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.resolver;
17 |
18 | import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
19 | import org.springframework.lang.Nullable;
20 |
21 | public abstract class AbstractNamedRequestPropertyResolver implements RequestPropertyResolverBase {
22 | protected abstract String getName(BindingProperty bindingProperty);
23 |
24 | @Override
25 | @Nullable
26 | public final R resolve(BindingProperty bindingProperty, T request) {
27 | String name = getName(bindingProperty);
28 | return resolveWithName(bindingProperty, name, request);
29 | }
30 |
31 | @Nullable
32 | protected abstract R resolveWithName(BindingProperty bindingProperty, String name, T request);
33 | }
34 |
--------------------------------------------------------------------------------
/docs/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import org.asciidoctor.gradle.jvm.AsciidoctorTask
2 |
3 | plugins {
4 | id("com.mattbertolini.buildlogic.java-conventions")
5 | alias(libs.plugins.asciidoctorConvert)
6 | }
7 |
8 | configurations {
9 | register("asciidoctorExt")
10 | }
11 |
12 | dependencies {
13 | implementation(project(":spring-webmvc-annotated-data-binder"))
14 | implementation(project(":spring-webflux-annotated-data-binder"))
15 | implementation(libs.jakartaServletApi) // Version defined in Spring BOM file
16 | compileOnly(libs.findbugsJsr305)
17 |
18 | add("asciidoctorExt", libs.springAsciidoctorExtBlockSwitch)
19 |
20 | testImplementation(libs.junitJupiterApi)
21 | testImplementation(libs.assertJCore)
22 | testImplementation(libs.mockitoCore)
23 | testImplementation(libs.springTest)
24 | testImplementation(libs.jakartaWebsocketApi)
25 | testImplementation(libs.jakartaWebsocketClientApi)
26 | testCompileOnly(libs.hamcrest) // Needed for Spring mock MVC matchers
27 | testCompileOnly(libs.findbugsJsr305)
28 | }
29 |
30 | tasks.named("asciidoctor").configure {
31 | attributes(mapOf(
32 | "sourceDir" to project.sourceSets["main"].allJava.srcDirs.first(),
33 | "resourcesDir" to project.sourceSets["main"].resources.srcDirs.first(),
34 | "source-highlighter" to "coderay"
35 | ))
36 | configurations("asciidoctorExt")
37 | }
38 |
39 | tasks.named("jacocoTestReport").configure {
40 | reports {
41 | html.required.set(false)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/RequestPropertyResolver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.reactive.bind.resolver;
17 |
18 | import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
19 | import com.mattbertolini.spring.web.bind.resolver.RequestPropertyResolverBase;
20 | import org.springframework.lang.NonNull;
21 | import org.springframework.web.server.ServerWebExchange;
22 | import reactor.core.publisher.Mono;
23 |
24 | /**
25 | * The main property resolver interface for Spring WebFlux-based property resolvers.
26 | */
27 | public interface RequestPropertyResolver extends RequestPropertyResolverBase> {
28 | @Override
29 | @NonNull // Explicitly setting NonNull as we are overriding a Nullable parent method
30 | Mono
40 | */
41 | @Target({ElementType.FIELD, ElementType.METHOD})
42 | @Retention(RetentionPolicy.RUNTIME)
43 | @Documented
44 | public @interface SessionParameter {
45 | String value();
46 | }
47 |
--------------------------------------------------------------------------------
/docs/src/main/java/com/mattbertolini/spring/web/bind/docs/webmvc/ExampleMvcContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.docs.webmvc;
17 |
18 | import com.mattbertolini.spring.web.bind.docs.ExampleController;
19 | import com.mattbertolini.spring.web.bind.docs.ExampleService;
20 | import com.mattbertolini.spring.web.servlet.mvc.bind.config.BinderConfiguration;
21 | import org.springframework.context.annotation.Bean;
22 | import org.springframework.context.annotation.Configuration;
23 | import org.springframework.web.servlet.config.annotation.EnableWebMvc;
24 |
25 | @Configuration
26 | @EnableWebMvc
27 | public class ExampleMvcContext {
28 | // tag::javaMvcConfiguration[]
29 | @Bean
30 | public BinderConfiguration binderConfiguration() {
31 | return new BinderConfiguration();
32 | }
33 | // end::javaMvcConfiguration[]
34 |
35 | @Bean
36 | public ExampleController exampleController(ExampleService exampleService) {
37 | return new ExampleController(exampleService);
38 | }
39 |
40 | @Bean
41 | public ExampleService exampleService() {
42 | return new ExampleService();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/FormParameterRequestPropertyResolver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.servlet.mvc.bind.resolver;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.FormParameter;
19 | import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
20 | import org.springframework.util.StringUtils;
21 |
22 | import java.util.Objects;
23 |
24 | public class FormParameterRequestPropertyResolver extends RequestParameterRequestPropertyResolver {
25 | @Override
26 | public boolean supports(BindingProperty bindingProperty) {
27 | FormParameter annotation = bindingProperty.getAnnotation(FormParameter.class);
28 | return annotation != null && StringUtils.hasText(annotation.value());
29 | }
30 |
31 | @Override
32 | protected String getName(BindingProperty bindingProperty) {
33 | FormParameter annotation = bindingProperty.getAnnotation(FormParameter.class);
34 | Objects.requireNonNull(annotation, "No FormParameter annotation found on type");
35 | return annotation.value();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/docs/src/main/resources/com/mattbertolini/spring/web/bind/docs/webmvc/example-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/integration-tests/src/test/java/com/mattbertolini/spring/web/reactive/test/SessionMutator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.reactive.test;
17 |
18 | import org.springframework.http.client.reactive.ClientHttpConnector;
19 | import org.springframework.lang.NonNull;
20 | import org.springframework.test.web.reactive.server.WebTestClient;
21 | import org.springframework.test.web.reactive.server.WebTestClientConfigurer;
22 | import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
23 |
24 | import java.util.HashMap;
25 | import java.util.Map;
26 |
27 | class SessionMutator implements WebTestClientConfigurer {
28 | private final Map attributes = new HashMap<>();
29 |
30 | public static SessionMutator session() {
31 | return new SessionMutator();
32 | }
33 |
34 | public SessionMutator attribute(String name, String value) {
35 | attributes.put(name, value);
36 | return this;
37 | }
38 |
39 | @Override
40 | public void afterConfigurerAdded(@NonNull WebTestClient.Builder builder, WebHttpHandlerBuilder httpHandlerBuilder, ClientHttpConnector connector) {
41 | httpHandlerBuilder.filter(new SessionFilter(attributes));
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/spring-webmvc-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/servlet/mvc/bind/resolver/SessionParameterRequestPropertyResolver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.servlet.mvc.bind.resolver;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.SessionParameter;
19 | import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
20 | import org.springframework.lang.Nullable;
21 | import org.springframework.web.context.request.NativeWebRequest;
22 | import org.springframework.web.context.request.RequestAttributes;
23 |
24 | import java.util.Objects;
25 |
26 | public class SessionParameterRequestPropertyResolver implements RequestPropertyResolver {
27 | @Override
28 | public boolean supports(BindingProperty bindingProperty) {
29 | return bindingProperty.hasAnnotation(SessionParameter.class);
30 | }
31 |
32 | @Override
33 | @Nullable
34 | public Object resolve(BindingProperty bindingProperty, NativeWebRequest request) {
35 | SessionParameter annotation = bindingProperty.getAnnotation(SessionParameter.class);
36 | Objects.requireNonNull(annotation, "No SessionParameter annotation found on type");
37 | return request.getAttribute(annotation.value(), RequestAttributes.SCOPE_SESSION);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/test/java/com/mattbertolini/spring/web/bind/support/MapValueResolverTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.support;
17 |
18 | import org.junit.jupiter.api.Test;
19 |
20 | import java.util.Map;
21 |
22 | import static org.assertj.core.api.Assertions.assertThat;
23 |
24 | class MapValueResolverTest {
25 | @Test
26 | void resolveValueReturnsMapValueFromKey() {
27 | Map map = Map.of("key1", "value1", "key2", "value2");
28 | MapValueResolver valueResolver = new MapValueResolver(map);
29 | assertThat(valueResolver.resolveValue("key1", String.class)).isEqualTo("value1");
30 | }
31 |
32 | @Test
33 | void getNamesReturnsMapKeys() {
34 | Map map = Map.of("key1", "value1", "key2", "value2");
35 | MapValueResolver valueResolver = new MapValueResolver(map);
36 | assertThat(valueResolver.getNames()).contains("key1", "key2");
37 | }
38 |
39 | @Test
40 | void valuesAccessorIsUnmodifiable() {
41 | Map map = Map.of("key1", "value1", "key2", "value2");
42 | MapValueResolver valueResolver = new MapValueResolver(map);
43 | assertThat(valueResolver.values())
44 | .isUnmodifiable()
45 | .isEqualTo(map);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/spring-annotated-data-binder-core/src/main/java/com/mattbertolini/spring/web/bind/annotation/PathParameter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.bind.annotation;
17 |
18 | import java.lang.annotation.Documented;
19 | import java.lang.annotation.ElementType;
20 | import java.lang.annotation.Retention;
21 | import java.lang.annotation.RetentionPolicy;
22 | import java.lang.annotation.Target;
23 |
24 | /**
25 | *
Annotation for fetching Spring path variable values.
46 | *
47 | */
48 | @Target({ElementType.FIELD, ElementType.METHOD})
49 | @Retention(RetentionPolicy.RUNTIME)
50 | @Documented
51 | public @interface PathParameter {
52 | String value() default "";
53 | }
54 |
--------------------------------------------------------------------------------
/spring-webflux-annotated-data-binder/src/main/java/com/mattbertolini/spring/web/reactive/bind/resolver/SessionParameterRequestPropertyResolver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2025 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.mattbertolini.spring.web.reactive.bind.resolver;
17 |
18 | import com.mattbertolini.spring.web.bind.annotation.SessionParameter;
19 | import com.mattbertolini.spring.web.bind.introspect.BindingProperty;
20 | import org.springframework.lang.NonNull;
21 | import org.springframework.web.server.ServerWebExchange;
22 | import reactor.core.publisher.Mono;
23 |
24 | import java.util.Objects;
25 |
26 | public class SessionParameterRequestPropertyResolver implements RequestPropertyResolver {
27 | @Override
28 | public boolean supports(BindingProperty bindingProperty) {
29 | return bindingProperty.hasAnnotation(SessionParameter.class);
30 | }
31 |
32 | @NonNull
33 | @Override
34 | public Mono