diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 272c07a5..6fed9055 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -20,6 +20,7 @@ updates:
- dependency-name: "org.jboss.weld:weld-junit5"
- dependency-name: "org.hibernate.validator:hibernate-validator"
- dependency-name: "com.fasterxml.jackson.core:jackson-databind"
+ - dependency-name: "tools.jackson.core:jackson-databind"
groups:
maven:
patterns:
diff --git a/belgif-rest-problem-bom/pom.xml b/belgif-rest-problem-bom/pom.xml
index 1605625d..f4ac8e8b 100644
--- a/belgif-rest-problem-bom/pom.xml
+++ b/belgif-rest-problem-bom/pom.xml
@@ -63,17 +63,7 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common-client
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common-server
+ belgif-rest-problem-spring
${project.version}
@@ -83,37 +73,27 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-core
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-client
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-server
+ belgif-rest-problem-spring-boot-3-client-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4
+ belgif-rest-problem-spring-boot-3-server-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-core
+ belgif-rest-problem-spring-boot-4-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-client
+ belgif-rest-problem-spring-boot-4-client-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-server
+ belgif-rest-problem-spring-boot-4-server-starter
${project.version}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-it-common-jakarta/pom.xml b/belgif-rest-problem-it/belgif-rest-problem-it-common-jakarta/pom.xml
index 40749991..7212f334 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-it-common-jakarta/pom.xml
+++ b/belgif-rest-problem-it/belgif-rest-problem-it-common-jakarta/pom.xml
@@ -12,26 +12,151 @@
belgif-rest-problem-it-common-jakarta
${project.groupId}:${project.artifactId}
+
+
+ io.github.belgif.rest.problem
+ belgif-rest-problem
+ ${project.version}
+
+
+ io.github.belgif.rest.problem
+ belgif-rest-problem-apt
+ ${project.version}
+ true
+
+
+ jakarta.platform
+ jakarta.jakartaee-api
+ 9.0.0
+ provided
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${version.jackson.minimal}
+ provided
+
+
+ tools.jackson.core
+ jackson-databind
+ ${version.jackson3.minimal}
+ provided
+
+
+ org.junit.jupiter
+ junit-jupiter
+ provided
+
+
+ org.assertj
+ assertj-core
+ provided
+
+
+ io.rest-assured
+ rest-assured
+ provided
+
+
- org.eclipse.transformer
- transformer-maven-plugin
+ org.apache.maven.plugins
+ maven-dependency-plugin
- package
+ unpack-core-sources
+ generate-sources
- jar
+ unpack
-
- io.github.belgif.rest.problem
- belgif-rest-problem-it-common
- ${project.version}
-
-
- true
-
+
+
+ io.github.belgif.rest.problem
+ belgif-rest-problem-it-common
+ ${project.version}
+ sources
+
+ ${project.build.directory}/sources-to-transform
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+
+ transform-to-jakarta
+ generate-sources
+
+ java
+
+
+ true
+ false
+ true
+
+ org.eclipse.transformer.cli.JakartaTransformerCLI
+
+
+
+ ${project.build.directory}/sources-to-transform
+
+
+ ${project.build.directory}/generated-sources/jakarta
+
+
+
+
+
+
+
+ org.eclipse.transformer
+ org.eclipse.transformer.cli
+ 1.0.0
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ add-transformed-sources
+ generate-sources
+
+ add-source
+
+
+
+
+ ${project.build.directory}/generated-sources/jakarta
+
+
+
+
+
+ add-resource
+ generate-resources
+
+ add-resource
+
+
+
+
+ ${project.build.directory}/generated-sources/jakarta
+
+ **/*.java
+ META-INF/MANIFEST.MF
+ META-INF/io.github.belgif.rest.problem/**
+
+
+
diff --git a/belgif-rest-problem-it/belgif-rest-problem-it-common/pom.xml b/belgif-rest-problem-it/belgif-rest-problem-it-common/pom.xml
index be20e755..405f6c12 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-it-common/pom.xml
+++ b/belgif-rest-problem-it/belgif-rest-problem-it-common/pom.xml
@@ -12,6 +12,23 @@
belgif-rest-problem-it-common
${project.groupId}:${project.artifactId}
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+
+
io.github.belgif.rest.problem
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/pom.xml b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/pom.xml
index e19b6479..bfd3afee 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/pom.xml
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/pom.xml
@@ -87,8 +87,8 @@
${project.basedir}/../belgif-rest-problem-it-common/src/main/resources/openapi.yaml
spring
- io.github.belgif.rest.problem.openapi.validation.sb3.api
- io.github.belgif.rest.problem.openapi.validation.sb3.model
+ io.github.belgif.rest.problem.it.openapi.validation.sb3.api
+ io.github.belgif.rest.problem.it.openapi.validation.sb3.model
REF_AS_PARENT_IN_ALLOF=true
false
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/Application.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/Application.java
similarity index 87%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/Application.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/Application.java
index 39f16429..72206306 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/Application.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/Application.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/BackendController.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/BackendController.java
similarity index 94%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/BackendController.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/BackendController.java
index b3d6af05..8a627e80 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/BackendController.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/BackendController.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import java.net.URI;
@@ -9,6 +9,7 @@
import com.acme.custom.CustomProblem;
+import io.github.belgif.rest.problem.BadRequestProblem;
import io.github.belgif.rest.problem.api.Problem;
import io.github.belgif.rest.problem.it.model.JacksonModel;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/Client.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/Client.java
similarity index 62%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/Client.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/Client.java
index 0a4f64af..bbc54c9d 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/Client.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/Client.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
public enum Client {
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/ControllerInterface.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/ControllerInterface.java
similarity index 95%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/ControllerInterface.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/ControllerInterface.java
index 3d39fd72..60516423 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/ControllerInterface.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/ControllerInterface.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/FrontendController.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/FrontendController.java
similarity index 98%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/FrontendController.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/FrontendController.java
index 1a4ca8e3..69e08e6e 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/FrontendController.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/FrontendController.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import java.net.URI;
@@ -26,6 +26,9 @@
import com.acme.custom.CustomProblem;
+import io.github.belgif.rest.problem.BadRequestProblem;
+import io.github.belgif.rest.problem.DefaultProblem;
+import io.github.belgif.rest.problem.ServiceUnavailableProblem;
import io.github.belgif.rest.problem.api.Input;
import io.github.belgif.rest.problem.api.Problem;
import io.github.belgif.rest.problem.i18n.I18N;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationConfig.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationConfig.java
similarity index 97%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationConfig.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationConfig.java
index b6ecd1fd..b40769d3 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationConfig.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationConfig.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import java.util.Collections;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationController.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationController.java
similarity index 71%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationController.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationController.java
index 1d3f6a2a..8c5cfc6a 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationController.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationController.java
@@ -1,15 +1,15 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import io.github.belgif.rest.problem.openapi.validation.sb4.api.MyFirstPathApi;
-import io.github.belgif.rest.problem.openapi.validation.sb4.api.MyHeaderPathApi;
-import io.github.belgif.rest.problem.openapi.validation.sb4.api.MyQueryPathApi;
-import io.github.belgif.rest.problem.openapi.validation.sb4.model.MyRequestBodySchema;
-import io.github.belgif.rest.problem.openapi.validation.sb4.model.PostOperationWithAllOfSchemaRequest;
-import io.github.belgif.rest.problem.openapi.validation.sb4.model.PostOperationWithOneOfSchemaRequest;
+import io.github.belgif.rest.problem.it.openapi.validation.sb3.api.MyFirstPathApi;
+import io.github.belgif.rest.problem.it.openapi.validation.sb3.api.MyHeaderPathApi;
+import io.github.belgif.rest.problem.it.openapi.validation.sb3.api.MyQueryPathApi;
+import io.github.belgif.rest.problem.it.openapi.validation.sb3.model.MyRequestBodySchema;
+import io.github.belgif.rest.problem.it.openapi.validation.sb3.model.PostOperationWithAllOfSchemaRequest;
+import io.github.belgif.rest.problem.it.openapi.validation.sb3.model.PostOperationWithOneOfSchemaRequest;
@RestController
@RequestMapping("/openapi-validation")
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/RestProblemOpenApiValidationSpringBoot3IT.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemOpenApiValidationSpringBoot3IT.java
similarity index 85%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/RestProblemOpenApiValidationSpringBoot3IT.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemOpenApiValidationSpringBoot3IT.java
index fcf01eef..4310f8ee 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/RestProblemOpenApiValidationSpringBoot3IT.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemOpenApiValidationSpringBoot3IT.java
@@ -1,10 +1,9 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.annotation.DirtiesContext;
-import io.github.belgif.rest.problem.it.AbstractOpenApiValidationSpringBootIT;
import io.restassured.RestAssured;
import io.restassured.specification.RequestSpecification;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot3ExtIT.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot3ExtIT.java
similarity index 87%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot3ExtIT.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot3ExtIT.java
index 565266ad..75c8f388 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot3ExtIT.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot3ExtIT.java
@@ -1,11 +1,10 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
-import io.github.belgif.rest.problem.it.AbstractRestProblemExtIT;
import io.restassured.RestAssured;
import io.restassured.specification.RequestSpecification;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot3IT.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot3IT.java
similarity index 88%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot3IT.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot3IT.java
index 6675d0f0..7cb4174f 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot3IT.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot3IT.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import java.util.Arrays;
import java.util.stream.Stream;
@@ -7,7 +7,6 @@
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.annotation.DirtiesContext;
-import io.github.belgif.rest.problem.it.AbstractRestProblemSpringBootIT;
import io.restassured.RestAssured;
import io.restassured.specification.RequestSpecification;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/pom.xml b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/pom.xml
index 86ec535a..24876100 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/pom.xml
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/pom.xml
@@ -32,7 +32,7 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4
+ belgif-rest-problem-spring-boot-4-starter
${project.version}
@@ -104,12 +104,13 @@
${project.basedir}/../belgif-rest-problem-it-common/src/main/resources/openapi.yaml
spring
- io.github.belgif.rest.problem.openapi.validation.sb4.api
- io.github.belgif.rest.problem.openapi.validation.sb4.model
+ io.github.belgif.rest.problem.it.openapi.validation.sb4.api
+ io.github.belgif.rest.problem.it.openapi.validation.sb4.model
REF_AS_PARENT_IN_ALLOF=true
false
- true
+ true
+ true
true
true
false
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/Application.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/Application.java
similarity index 87%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/Application.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/Application.java
index 39f16429..72206306 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/Application.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/Application.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/BackendController.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/BackendController.java
similarity index 94%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/BackendController.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/BackendController.java
index b3d6af05..8a627e80 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/BackendController.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/BackendController.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import java.net.URI;
@@ -9,6 +9,7 @@
import com.acme.custom.CustomProblem;
+import io.github.belgif.rest.problem.BadRequestProblem;
import io.github.belgif.rest.problem.api.Problem;
import io.github.belgif.rest.problem.it.model.JacksonModel;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/Client.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/Client.java
similarity index 62%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/Client.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/Client.java
index 0a4f64af..bbc54c9d 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/Client.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/Client.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
public enum Client {
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/ControllerInterface.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/ControllerInterface.java
similarity index 95%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/ControllerInterface.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/ControllerInterface.java
index 3d39fd72..60516423 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/ControllerInterface.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/ControllerInterface.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/FrontendController.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/FrontendController.java
similarity index 98%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/FrontendController.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/FrontendController.java
index 8821242d..1494824e 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/FrontendController.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/FrontendController.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import java.net.URI;
@@ -26,6 +26,9 @@
import com.acme.custom.CustomProblem;
+import io.github.belgif.rest.problem.BadRequestProblem;
+import io.github.belgif.rest.problem.DefaultProblem;
+import io.github.belgif.rest.problem.ServiceUnavailableProblem;
import io.github.belgif.rest.problem.api.Input;
import io.github.belgif.rest.problem.api.Problem;
import io.github.belgif.rest.problem.i18n.I18N;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationConfig.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationConfig.java
similarity index 97%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationConfig.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationConfig.java
index 97506597..2ef7ca3c 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationConfig.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationConfig.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import java.util.Collections;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationController.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationController.java
similarity index 71%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationController.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationController.java
index 5d61539b..cf0fc1e9 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it/src/main/java/io/github/belgif/rest/problem/OpenApiValidationController.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationController.java
@@ -1,13 +1,15 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import io.github.belgif.rest.problem.openapi.validation.sb3.api.*;
-import io.github.belgif.rest.problem.openapi.validation.sb3.model.MyRequestBodySchema;
-import io.github.belgif.rest.problem.openapi.validation.sb3.model.PostOperationWithAllOfSchemaRequest;
-import io.github.belgif.rest.problem.openapi.validation.sb3.model.PostOperationWithOneOfSchemaRequest;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.api.MyFirstPathApi;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.api.MyHeaderPathApi;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.api.MyQueryPathApi;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.model.MyRequestBodySchema;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.model.PostOperationWithAllOfSchemaRequest;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.model.PostOperationWithOneOfSchemaRequest;
@RestController
@RequestMapping("/openapi-validation")
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/RestProblemOpenApiValidationSpringBoot4IT.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemOpenApiValidationSpringBoot4IT.java
similarity index 85%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/RestProblemOpenApiValidationSpringBoot4IT.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemOpenApiValidationSpringBoot4IT.java
index 863d2502..d20c375d 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/RestProblemOpenApiValidationSpringBoot4IT.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemOpenApiValidationSpringBoot4IT.java
@@ -1,10 +1,9 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.annotation.DirtiesContext;
-import io.github.belgif.rest.problem.it.AbstractOpenApiValidationSpringBootIT;
import io.restassured.RestAssured;
import io.restassured.specification.RequestSpecification;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot4ExtIT.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot4ExtIT.java
similarity index 87%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot4ExtIT.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot4ExtIT.java
index 8e7b2551..638e3455 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot4ExtIT.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot4ExtIT.java
@@ -1,11 +1,10 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
-import io.github.belgif.rest.problem.it.AbstractRestProblemExtIT;
import io.restassured.RestAssured;
import io.restassured.specification.RequestSpecification;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot4IT.java b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot4IT.java
similarity index 88%
rename from belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot4IT.java
rename to belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot4IT.java
index b2928c16..6c9b01df 100644
--- a/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/RestProblemSpringBoot4IT.java
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringBoot4IT.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem;
+package io.github.belgif.rest.problem.it;
import java.util.Arrays;
import java.util.stream.Stream;
@@ -7,7 +7,6 @@
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.annotation.DirtiesContext;
-import io.github.belgif.rest.problem.it.AbstractRestProblemSpringBootIT;
import io.restassured.RestAssured;
import io.restassured.specification.RequestSpecification;
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/pom.xml b/belgif-rest-problem-it/belgif-rest-problem-spring-it/pom.xml
new file mode 100644
index 00000000..6f96b5a9
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/pom.xml
@@ -0,0 +1,146 @@
+
+
+ 4.0.0
+
+
+ io.github.belgif.rest.problem
+ belgif-rest-problem-it
+ ${revision}
+
+
+ belgif-rest-problem-spring-it
+ ${project.groupId}:${project.artifactId}
+ jar
+
+
+ 17
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${version.spring.boot.4}
+ pom
+ import
+
+
+
+
+
+
+ io.github.belgif.rest.problem
+ belgif-rest-problem-spring
+ ${project.version}
+
+
+ tools.jackson.core
+ jackson-databind
+
+
+ io.github.belgif.rest.problem
+ belgif-rest-problem-validator
+ ${project.version}
+
+
+ org.springframework
+ spring-webmvc
+
+
+ io.github.belgif.rest.problem
+ belgif-rest-problem-it-common-jakarta
+ ${project.version}
+
+
+ org.hibernate.validator
+ hibernate-validator
+
+
+ jakarta.validation
+ jakarta.validation-api
+
+
+ jakarta.annotation
+ jakarta.annotation-api
+
+
+ jakarta.servlet
+ jakarta.servlet-api
+
+
+ com.atlassian.oai
+ swagger-request-validator-spring-webmvc
+ 2.46.0
+
+
+ org.springframework.boot
+ spring-boot-starter-webmvc
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ test
+
+
+ org.springframework.boot
+ spring-boot-test
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.springframework
+ spring-webflux
+
+
+ org.springframework
+ spring-test
+ test
+
+
+ io.rest-assured
+ rest-assured
+ 6.0.0
+ test
+
+
+
+
+
+
+ org.openapitools
+ openapi-generator-maven-plugin
+
+
+
+ generate
+
+
+ ${project.basedir}/../belgif-rest-problem-it-common/src/main/resources/openapi.yaml
+ spring
+ io.github.belgif.rest.problem.it.openapi.validation.sb4.api
+ io.github.belgif.rest.problem.it.openapi.validation.sb4.model
+ REF_AS_PARENT_IN_ALLOF=true
+ false
+
+ true
+ true
+ true
+ false
+ none
+ none
+ false
+
+
+
+
+
+
+
+
+
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/BackendController.java b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/BackendController.java
new file mode 100644
index 00000000..8a627e80
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/BackendController.java
@@ -0,0 +1,59 @@
+package io.github.belgif.rest.problem.it;
+
+import java.net.URI;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.acme.custom.CustomProblem;
+
+import io.github.belgif.rest.problem.BadRequestProblem;
+import io.github.belgif.rest.problem.api.Problem;
+import io.github.belgif.rest.problem.it.model.JacksonModel;
+
+@RestController
+@RequestMapping("/backend")
+public class BackendController {
+
+ @GetMapping("/ok")
+ public ResponseEntity ok() {
+ return ResponseEntity.ok("OK");
+ }
+
+ @GetMapping("/badRequest")
+ public void badRequest() {
+ BadRequestProblem problem = new BadRequestProblem();
+ problem.setDetail("Bad Request from backend");
+ throw problem;
+ }
+
+ @GetMapping("/custom")
+ public void custom() {
+ throw new CustomProblem("value from backend");
+ }
+
+ @GetMapping("/unmapped")
+ public void unmapped() {
+ Problem unmapped = new Problem(URI.create("urn:problem-type:belgif:test:unmapped"), "Unmapped problem", 400) {
+ };
+ unmapped.setDetail("Unmapped problem from backend");
+ throw unmapped;
+ }
+
+ @GetMapping("/applicationJsonProblem")
+ public ResponseEntity applicationJsonProblem() {
+ BadRequestProblem problem = new BadRequestProblem();
+ problem.setDetail("Bad Request with application/json media type from backend");
+ return ResponseEntity.badRequest().body(problem);
+ }
+
+ @GetMapping("/jacksonMismatchedInput")
+ public ResponseEntity mismatchedInput() {
+ JacksonModel model = new JacksonModel(null);
+ model.setDescription("description");
+ return ResponseEntity.ok(model);
+ }
+
+}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/Client.java b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/Client.java
new file mode 100644
index 00000000..bbc54c9d
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/Client.java
@@ -0,0 +1,7 @@
+package io.github.belgif.rest.problem.it;
+
+public enum Client {
+
+ REST_TEMPLATE, WEB_CLIENT, REST_CLIENT
+
+}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/ControllerInterface.java b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/ControllerInterface.java
new file mode 100644
index 00000000..60516423
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/ControllerInterface.java
@@ -0,0 +1,24 @@
+package io.github.belgif.rest.problem.it;
+
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+
+@Validated
+@Controller
+public interface ControllerInterface {
+
+ @GetMapping("/beanValidation/pathParameter/inherited/{param}")
+ ResponseEntity beanValidationPathParameterInherited(
+ @PathVariable("param") @Positive @NotNull Integer p);
+
+ @GetMapping("/beanValidation/pathParameter/overridden/{param}")
+ ResponseEntity beanValidationPathParameterOverridden(
+ @PathVariable("param") @Positive @NotNull Integer p);
+
+}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/FrontendController.java b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/FrontendController.java
new file mode 100644
index 00000000..b9f93410
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/FrontendController.java
@@ -0,0 +1,267 @@
+package io.github.belgif.rest.problem.it;
+
+import java.net.URI;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import jakarta.validation.constraints.Size;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestClient;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import com.acme.custom.CustomProblem;
+
+import io.github.belgif.rest.problem.BadRequestProblem;
+import io.github.belgif.rest.problem.DefaultProblem;
+import io.github.belgif.rest.problem.ServiceUnavailableProblem;
+import io.github.belgif.rest.problem.api.Input;
+import io.github.belgif.rest.problem.api.Problem;
+import io.github.belgif.rest.problem.i18n.I18N;
+import io.github.belgif.rest.problem.it.model.ChildModel;
+import io.github.belgif.rest.problem.it.model.JacksonModel;
+import io.github.belgif.rest.problem.it.model.Model;
+import io.github.belgif.rest.problem.it.model.NestedModel;
+import io.github.belgif.rest.problem.validation.RequestValidator;
+
+@RestController
+@RequestMapping("/frontend")
+@Validated
+public class FrontendController implements ControllerInterface {
+
+ private static final String DETAIL_MESSAGE_SUFFIX = " (caught successfully by frontend)";
+ private static final String ILLEGAL_STATE_MESSAGE_PREFIX = "Unsupported client ";
+
+ private WebClient.Builder webClientBuilder;
+
+ private RestClient.Builder restClientBuilder;
+
+ private RestTemplate restTemplate;
+
+ private WebClient webClient;
+
+ private RestClient restClient;
+
+ public FrontendController(WebClient.Builder webClientBuilder, RestClient.Builder restClientBuilder) {
+ this.webClientBuilder = webClientBuilder;
+ this.restClientBuilder = restClientBuilder;
+ }
+
+ public void initClients(int port) {
+ String apiBaseUrl = "http://localhost:" + port + "/spring/backend";
+ this.webClient = this.webClientBuilder
+ .baseUrl(apiBaseUrl)
+ .build();
+ this.restClient = this.restClientBuilder
+ .baseUrl(apiBaseUrl)
+ .build();
+ // we're not testing RestTemplate for now
+ // there's no builder or baseUrl support for RestTemplate without Spring Boot, so would require more refactoring
+ }
+
+ @GetMapping("/ping")
+ public String ping() {
+ return "pong";
+ }
+
+ @GetMapping("/badRequest")
+ public void badRequest() {
+ BadRequestProblem problem = new BadRequestProblem();
+ problem.setDetail("Bad Request from frontend");
+ throw problem;
+ }
+
+ @GetMapping("/custom")
+ public void custom() {
+ throw new CustomProblem("value from frontend");
+ }
+
+ @GetMapping("/runtime")
+ public void runtime() {
+ throw new RuntimeException("oops");
+ }
+
+ @GetMapping("/unmapped")
+ public void unmapped() {
+ Problem unmapped = new Problem(URI.create("urn:problem-type:belgif:test:unmapped"), "Unmapped problem", 400) {
+ };
+ unmapped.setDetail("Unmapped problem from frontend");
+ throw unmapped;
+ }
+
+ @GetMapping("/retryAfter")
+ public void retryAfter() {
+ ServiceUnavailableProblem problem = new ServiceUnavailableProblem();
+ problem.setRetryAfterSec(10000L);
+ throw problem;
+ }
+
+ @GetMapping(value = "/okFromBackend", produces = "application/json")
+ public ResponseEntity okFromBackend(@RequestParam("client") Client client) {
+ String result = null;
+ if (client == Client.REST_TEMPLATE) {
+ result = restTemplate.getForObject("/ok", String.class);
+ } else if (client == Client.WEB_CLIENT) {
+ result = webClient.get().uri("/ok").retrieve().toEntity(String.class).block().getBody();
+ } else if (client == Client.REST_CLIENT) {
+ result = restClient.get().uri("/ok").retrieve().toEntity(String.class).getBody();
+ }
+ return ResponseEntity.ok(result);
+ }
+
+ @GetMapping("/badRequestFromBackend")
+ public void badRequestFromBackend(@RequestParam("client") Client client) {
+ try {
+ if (client == Client.REST_TEMPLATE) {
+ restTemplate.getForObject("/badRequest", String.class);
+ } else if (client == Client.WEB_CLIENT) {
+ webClient.get().uri("/badRequest").retrieve().toEntity(String.class).block();
+ } else if (client == Client.REST_CLIENT) {
+ restClient.get().uri("/badRequest").retrieve().toEntity(String.class);
+ }
+ throw new IllegalStateException(ILLEGAL_STATE_MESSAGE_PREFIX + client);
+ } catch (BadRequestProblem e) {
+ e.setDetail(e.getDetail() + DETAIL_MESSAGE_SUFFIX);
+ throw e;
+ }
+ }
+
+ @GetMapping("/customFromBackend")
+ public void customFromBackend(@RequestParam("client") Client client) {
+ try {
+ if (client == Client.REST_TEMPLATE) {
+ restTemplate.getForObject("/custom", String.class);
+ } else if (client == Client.WEB_CLIENT) {
+ webClient.get().uri("/custom").retrieve().toEntity(String.class).block();
+ } else if (client == Client.REST_CLIENT) {
+ restClient.get().uri("/custom").retrieve().toEntity(String.class);
+ }
+ throw new IllegalStateException(ILLEGAL_STATE_MESSAGE_PREFIX + client);
+ } catch (CustomProblem e) {
+ e.setCustomField(e.getCustomField() + DETAIL_MESSAGE_SUFFIX);
+ throw e;
+ }
+ }
+
+ @GetMapping("/unmappedFromBackend")
+ public void unmappedFromBackend(@RequestParam("client") Client client) {
+ try {
+ if (client == Client.REST_TEMPLATE) {
+ restTemplate.getForObject("/unmapped", String.class);
+ } else if (client == Client.WEB_CLIENT) {
+ webClient.get().uri("/unmapped").retrieve().toEntity(String.class).block();
+ } else if (client == Client.REST_CLIENT) {
+ restClient.get().uri("/unmapped").retrieve().toEntity(String.class);
+ }
+ throw new IllegalStateException(ILLEGAL_STATE_MESSAGE_PREFIX + client);
+ } catch (DefaultProblem e) {
+ e.setDetail(e.getDetail() + DETAIL_MESSAGE_SUFFIX);
+ throw e;
+ }
+ }
+
+ @GetMapping("/applicationJsonProblemFromBackend")
+ public void applicationJsonProblemFromBackend(@RequestParam("client") Client client) {
+ try {
+ if (client == Client.REST_TEMPLATE) {
+ restTemplate.getForObject("/applicationJsonProblem", String.class);
+ } else if (client == Client.WEB_CLIENT) {
+ webClient.get().uri("/applicationJsonProblem").retrieve().toEntity(String.class).block();
+ } else if (client == Client.REST_CLIENT) {
+ restClient.get().uri("/applicationJsonProblem").retrieve().toEntity(String.class);
+ }
+ throw new IllegalStateException(ILLEGAL_STATE_MESSAGE_PREFIX + client);
+ } catch (BadRequestProblem e) {
+ e.setDetail(e.getDetail() + DETAIL_MESSAGE_SUFFIX);
+ throw e;
+ }
+ }
+
+ @GetMapping("/jacksonMismatchedInputFromBackend")
+ public void jacksonMismatchedInputFromBackend(@RequestParam("client") Client client) {
+ if (client == Client.REST_TEMPLATE) {
+ restTemplate.getForObject("/jacksonMismatchedInput", JacksonModel.class);
+ } else if (client == Client.WEB_CLIENT) {
+ webClient.get().uri("/jacksonMismatchedInput").retrieve().toEntity(JacksonModel.class).block();
+ } else if (client == Client.REST_CLIENT) {
+ restClient.get().uri("/jacksonMismatchedInput").retrieve().toEntity(JacksonModel.class);
+ }
+ throw new IllegalStateException(ILLEGAL_STATE_MESSAGE_PREFIX + client);
+ }
+
+ @GetMapping("/beanValidation/queryParameter")
+ public ResponseEntity beanValidationQueryParameter(
+ @RequestParam("param") @Positive @NotNull Integer p,
+ @RequestParam @Size(max = 5) String other) {
+ return ResponseEntity.ok("param: " + p + ", other: " + other);
+ }
+
+ @GetMapping("/beanValidation/headerParameter")
+ public ResponseEntity beanValidationHeaderParameter(
+ @RequestHeader("param") @Positive @NotNull Integer p) {
+ return ResponseEntity.ok("param: " + p);
+ }
+
+ @GetMapping("/beanValidation/pathParameter/class/{param}")
+ public ResponseEntity beanValidationPathParameter(
+ @PathVariable("param") @Positive @NotNull Integer p) {
+ return ResponseEntity.ok("param: " + p);
+ }
+
+ @Override
+ public ResponseEntity beanValidationPathParameterInherited(Integer p) {
+ return ResponseEntity.ok("param: " + p);
+ }
+
+ @Override
+ @GetMapping("/beanValidation/pathParameter/overridden")
+ public ResponseEntity beanValidationPathParameterOverridden(@RequestParam("param") Integer p) {
+ return ResponseEntity.ok("param: " + p);
+ }
+
+ @PostMapping("/beanValidation/body")
+ public ResponseEntity beanValidationBody(@Valid @RequestBody Model body) {
+ return ResponseEntity.ok("body: " + body);
+ }
+
+ @PostMapping("/beanValidation/body/nested")
+ public ResponseEntity beanValidationBodyNested(@Valid @RequestBody NestedModel body) {
+ return ResponseEntity.ok("body: " + body);
+ }
+
+ @PostMapping("/beanValidation/body/inheritance")
+ public ResponseEntity beanValidationBodyInheritance(@Valid @RequestBody ChildModel body) {
+ return ResponseEntity.ok("body: " + body);
+ }
+
+ @PostMapping("/beanValidation/queryParameter/nested")
+ public ResponseEntity beanValidationQueryParameterNested(@Valid Model p) {
+ return ResponseEntity.ok("param: " + p);
+ }
+
+ @PostMapping("/jackson/mismatchedInputException")
+ public ResponseEntity jacksonMismatchedInputException(@Valid @RequestBody JacksonModel p) {
+ return ResponseEntity.ok("param: " + p);
+ }
+
+ @PostMapping("/i18n")
+ public ResponseEntity i18n(@RequestParam("enabled") boolean enabled) {
+ I18N.setEnabled(enabled);
+ return ResponseEntity.ok().build();
+ }
+
+ @GetMapping("/requestValidator")
+ public ResponseEntity requestValidator(@RequestParam("ssin") String ssin,
+ @RequestParam(name = "a", required = false) String a,
+ @RequestParam(name = "b", required = false) String b) {
+ new RequestValidator().ssin(Input.query("ssin", ssin))
+ .zeroOrAllOf(Input.query("a", a), Input.query("b", b))
+ .validate();
+ return ResponseEntity.ok().build();
+ }
+
+}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationConfig.java b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationConfig.java
new file mode 100644
index 00000000..e965740b
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationConfig.java
@@ -0,0 +1,45 @@
+package io.github.belgif.rest.problem.it;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.http.HttpServletRequest;
+
+import org.jspecify.annotations.NonNull;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import com.atlassian.oai.validator.OpenApiInteractionValidator;
+import com.atlassian.oai.validator.report.LevelResolver;
+import com.atlassian.oai.validator.report.ValidationReport;
+import com.atlassian.oai.validator.springmvc.OpenApiValidationFilter;
+import com.atlassian.oai.validator.springmvc.OpenApiValidationInterceptor;
+
+@Configuration
+public class OpenApiValidationConfig implements WebMvcConfigurer {
+
+ @Bean
+ public Filter validationFilter() {
+ return new OpenApiValidationFilter(true, false) {
+ @Override
+ protected boolean shouldNotFilter(HttpServletRequest request) {
+ String path = request.getServletPath();
+ return !path.startsWith("/openapi-validation"); // replaces FilterRegistrationBean in Spring Boot
+ }
+ };
+ }
+
+ @Override
+ public void addInterceptors(@NonNull InterceptorRegistry registry) {
+ OpenApiInteractionValidator validator = OpenApiInteractionValidator
+ .createForSpecificationUrl("/openapi.yaml")
+ .withLevelResolver(LevelResolver.create()
+ // Accept additionalProperties even if they're not defined in the schema
+ .withLevel("validation.schema.additionalProperties", ValidationReport.Level.IGNORE)
+ .build())
+ .withBasePathOverride("/openapi-validation")
+ .build();
+ registry.addInterceptor(new OpenApiValidationInterceptor(validator));
+ }
+
+}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationController.java b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationController.java
new file mode 100644
index 00000000..cf0fc1e9
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/OpenApiValidationController.java
@@ -0,0 +1,60 @@
+package io.github.belgif.rest.problem.it;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.api.MyFirstPathApi;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.api.MyHeaderPathApi;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.api.MyQueryPathApi;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.model.MyRequestBodySchema;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.model.PostOperationWithAllOfSchemaRequest;
+import io.github.belgif.rest.problem.it.openapi.validation.sb4.model.PostOperationWithOneOfSchemaRequest;
+
+@RestController
+@RequestMapping("/openapi-validation")
+public class OpenApiValidationController
+ implements MyFirstPathApi, MyHeaderPathApi, MyQueryPathApi {
+
+ @Override
+ public ResponseEntity myFirstGetOperation(String myParam) {
+ return buildResponse();
+ }
+
+ @Override
+ public ResponseEntity myFirstPostOperation(MyRequestBodySchema myRequestBodySchema) {
+ return buildResponse();
+ }
+
+ @Override
+ public ResponseEntity mySecondGetOperation(String pathParam) {
+ return buildResponse();
+ }
+
+ @Override
+ public ResponseEntity myHeaderGetOperation(String myHeader) {
+ return buildResponse();
+ }
+
+ @Override
+ public ResponseEntity myQueryParamOperation(String myParam) {
+ return buildResponse();
+ }
+
+ @Override
+ public ResponseEntity
+ postOperationWithAllOfSchema(PostOperationWithAllOfSchemaRequest postOperationWithAllOfSchemaRequest) {
+ return buildResponse();
+ }
+
+ @Override
+ public ResponseEntity
+ postOperationWithOneOfSchema(PostOperationWithOneOfSchemaRequest postOperationWithOneOfSchemaRequest) {
+ return buildResponse();
+ }
+
+ private ResponseEntity buildResponse() {
+ return ResponseEntity.ok("All good!");
+ }
+
+}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/WebConfig.java b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/WebConfig.java
new file mode 100644
index 00000000..39589f04
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/main/java/io/github/belgif/rest/problem/it/WebConfig.java
@@ -0,0 +1,53 @@
+package io.github.belgif.rest.problem.it;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.codec.json.JacksonJsonDecoder;
+import org.springframework.http.codec.json.JacksonJsonEncoder;
+import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
+import org.springframework.web.client.RestClient;
+import org.springframework.web.reactive.function.client.ExchangeStrategies;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import io.github.belgif.rest.problem.spring.EnableProblemModule;
+import io.github.belgif.rest.problem.spring.SpringProblemModuleJackson3;
+import io.github.belgif.rest.problem.spring.client.ProblemResponseErrorHandler;
+import io.github.belgif.rest.problem.spring.client.WebClientFilter;
+import tools.jackson.databind.json.JsonMapper;
+
+@Configuration
+@EnableProblemModule(beanValidation = true)
+public class WebConfig {
+
+ @Bean
+ public JsonMapper objectMapper(SpringProblemModuleJackson3 springProblemModule) {
+ return JsonMapper.builder()
+ // application-specific JsonMapper customizations can be added here
+ .changeDefaultPropertyInclusion((incl) -> incl.withContentInclusion(JsonInclude.Include.NON_NULL)
+ .withValueInclusion(JsonInclude.Include.NON_NULL))
+ .addModule(springProblemModule) // add springProblem module to the mapper.
+ .build();
+ }
+
+ @Bean
+ public RestClient.Builder restClientBuilder(ProblemResponseErrorHandler problemResponseErrorHandler,
+ JsonMapper mapper) {
+ return RestClient.builder()
+ .defaultStatusHandler(problemResponseErrorHandler)
+ .configureMessageConverters(converter -> converter.registerDefaults()
+ .withJsonConverter(new JacksonJsonHttpMessageConverter(mapper))); // change converter with
+ // custom json mapper
+ }
+
+ @Bean
+ public WebClient.Builder webClientBuilder(ProblemResponseErrorHandler problemResponseErrorHandler,
+ JsonMapper mapper) {
+ ExchangeStrategies strategies = ExchangeStrategies.builder().codecs(configurer -> {
+ configurer.defaultCodecs().jacksonJsonEncoder(new JacksonJsonEncoder(mapper));
+ configurer.defaultCodecs().jacksonJsonDecoder(new JacksonJsonDecoder(mapper));
+ }).build();
+ return WebClient.builder().exchangeStrategies(strategies).filter(WebClientFilter.PROBLEM_FILTER);
+ }
+}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/java/io/github/belgif/rest/problem/it/Application.java b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/java/io/github/belgif/rest/problem/it/Application.java
new file mode 100644
index 00000000..72206306
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/java/io/github/belgif/rest/problem/it/Application.java
@@ -0,0 +1,12 @@
+package io.github.belgif.rest.problem.it;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringIT.java b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringIT.java
new file mode 100644
index 00000000..894c87b9
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/java/io/github/belgif/rest/problem/it/RestProblemSpringIT.java
@@ -0,0 +1,40 @@
+package io.github.belgif.rest.problem.it;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.test.annotation.DirtiesContext;
+
+import io.restassured.RestAssured;
+import io.restassured.specification.RequestSpecification;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@DirtiesContext
+// uses spring boot to start the server-side, but doesn't rely on starter integration with rest-problem
+class RestProblemSpringIT extends AbstractRestProblemSpringBootIT {
+
+ @LocalServerPort
+ private int port;
+
+ @Autowired
+ private FrontendController frontendController;
+
+ @BeforeEach
+ public void init() {
+ frontendController.initClients(port);
+ }
+
+ @Override
+ protected RequestSpecification getSpec() {
+ return RestAssured.with().baseUri("http://localhost").port(port).basePath("/spring/frontend");
+ }
+
+ @Override
+ protected Stream getClients() {
+ return List.of(Client.REST_CLIENT.name(), Client.WEB_CLIENT.name()).stream();
+ }
+}
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/resources/application-ext.properties b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/resources/application-ext.properties
new file mode 100644
index 00000000..15345d91
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/resources/application-ext.properties
@@ -0,0 +1,2 @@
+io.github.belgif.rest.problem.ext.issue-types-enabled=true
+io.github.belgif.rest.problem.ext.inputs-array-enabled=true
diff --git a/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/resources/application.properties b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/resources/application.properties
new file mode 100644
index 00000000..c7602404
--- /dev/null
+++ b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/resources/application.properties
@@ -0,0 +1,7 @@
+server.servlet.context-path=/spring
+io.github.belgif.rest.problem.scan-additional-problem-packages=com.acme.custom
+
+#If this property is not set the client will receive an InvalidRequestException or InvalidResponseException
+#without knowing what is wrong with the request / response as the message field will be missing.
+# https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-spring-webmvc/README.md#Configuration
+spring.web.error.include-message=always
\ No newline at end of file
diff --git a/belgif-rest-problem-spring-boot-3-client/src/test/resources/logback-test.xml b/belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/resources/logback-test.xml
similarity index 100%
rename from belgif-rest-problem-spring-boot-3-client/src/test/resources/logback-test.xml
rename to belgif-rest-problem-it/belgif-rest-problem-spring-it/src/test/resources/logback-test.xml
diff --git a/belgif-rest-problem-it/pom.xml b/belgif-rest-problem-it/pom.xml
index 56562119..1ce7ff5e 100644
--- a/belgif-rest-problem-it/pom.xml
+++ b/belgif-rest-problem-it/pom.xml
@@ -35,6 +35,7 @@
belgif-rest-problem-apt
belgif-rest-problem-it-common
belgif-rest-problem-it-common-jakarta
+ belgif-rest-problem-spring-it
belgif-rest-problem-spring-boot-3-it
belgif-rest-problem-spring-boot-4-it
belgif-rest-problem-java-ee-it
diff --git a/belgif-rest-problem-spring-boot-common-client/pom.xml b/belgif-rest-problem-spring-boot-3-client-starter/pom.xml
similarity index 90%
rename from belgif-rest-problem-spring-boot-common-client/pom.xml
rename to belgif-rest-problem-spring-boot-3-client-starter/pom.xml
index 5ebfcea6..45277ce8 100644
--- a/belgif-rest-problem-spring-boot-common-client/pom.xml
+++ b/belgif-rest-problem-spring-boot-3-client-starter/pom.xml
@@ -9,9 +9,8 @@
${revision}
- belgif-rest-problem-spring-boot-common-client
+ belgif-rest-problem-spring-boot-3-client-starter
${project.groupId}:${project.artifactId}
- Contains shared client components that are common between Spring Boot versions
jar
@@ -33,7 +32,7 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common
+ belgif-rest-problem-spring
${project.version}
diff --git a/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfiguration.java b/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfiguration.java
new file mode 100644
index 00000000..ec5c39a0
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfiguration.java
@@ -0,0 +1,50 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
+import org.springframework.boot.web.client.RestClientCustomizer;
+import org.springframework.boot.web.client.RestTemplateCustomizer;
+import org.springframework.boot.web.reactive.function.client.WebClientCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+import org.springframework.web.client.RestClient;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import io.github.belgif.rest.problem.spring.ProblemJackson2Configuration;
+
+/**
+ * Spring Boot AutoConfiguration for rest-problem-spring.
+ */
+@AutoConfiguration
+@Import({ ProblemJackson2Configuration.class, JacksonAutoConfiguration.class })
+public class ClientProblemAutoConfiguration {
+
+ @Bean
+ public ProblemResponseErrorHandler problemResponseErrorHandler(ObjectMapper objectMapper) {
+ return new ProblemResponseJackson2ErrorHandler(objectMapper);
+ }
+
+ @ConditionalOnClass({ RestClient.class, RestClientCustomizer.class })
+ @Bean
+ public ProblemRestClientCustomizer
+ problemRestClientCustomizer(ProblemResponseErrorHandler problemResponseErrorHandler) {
+ return new ProblemRestClientCustomizer(problemResponseErrorHandler);
+ }
+
+ @ConditionalOnClass({ RestTemplate.class, RestTemplateCustomizer.class })
+ @Bean
+ public ProblemRestTemplateCustomizer
+ problemRestTemplateCustomizer(ProblemResponseErrorHandler problemResponseErrorHandler) {
+ return new ProblemRestTemplateCustomizer(problemResponseErrorHandler);
+ }
+
+ @ConditionalOnClass({ WebClient.class, WebClientCustomizer.class })
+ @Bean
+ public ProblemWebClientCustomizer problemWebClientCustomizer() {
+ return new ProblemWebClientCustomizer();
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestClientCustomizer.java b/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestClientCustomizer.java
new file mode 100644
index 00000000..582349aa
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestClientCustomizer.java
@@ -0,0 +1,22 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import org.springframework.boot.web.client.RestClientCustomizer;
+import org.springframework.web.client.RestClient;
+
+/**
+ * RestClientCustomizer that registers the {@link ProblemResponseErrorHandler}.
+ *
+ * @see ProblemResponseErrorHandler
+ */
+public class ProblemRestClientCustomizer implements RestClientCustomizer {
+
+ private final ProblemResponseErrorHandler errorHandler;
+
+ protected ProblemRestClientCustomizer(ProblemResponseErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ public void customize(RestClient.Builder restClientBuilder) {
+ restClientBuilder.defaultStatusHandler(errorHandler);
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestTemplateCustomizer.java b/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestTemplateCustomizer.java
new file mode 100644
index 00000000..3a5d6abe
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestTemplateCustomizer.java
@@ -0,0 +1,24 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import org.springframework.boot.web.client.RestTemplateCustomizer;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * RestTemplateCustomizer that registers the {@link ProblemResponseErrorHandler}.
+ *
+ * @see ProblemResponseErrorHandler
+ */
+public class ProblemRestTemplateCustomizer implements RestTemplateCustomizer {
+
+ private final ProblemResponseErrorHandler problemResponseErrorHandler;
+
+ public ProblemRestTemplateCustomizer(ProblemResponseErrorHandler problemResponseErrorHandler) {
+ this.problemResponseErrorHandler = problemResponseErrorHandler;
+
+ }
+
+ public void customize(RestTemplate restTemplate) {
+ restTemplate.setErrorHandler(problemResponseErrorHandler);
+ }
+
+}
diff --git a/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemWebClientCustomizer.java b/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemWebClientCustomizer.java
new file mode 100644
index 00000000..c69915f7
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemWebClientCustomizer.java
@@ -0,0 +1,14 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import org.springframework.boot.web.reactive.function.client.WebClientCustomizer;
+import org.springframework.web.reactive.function.client.WebClient;
+
+/**
+ * WebClientCustomizer that registers a filter that converts problem responses to Problem exceptions.
+ */
+public class ProblemWebClientCustomizer implements WebClientCustomizer {
+
+ public void customize(WebClient.Builder webClientBuilder) {
+ webClientBuilder.filter(WebClientFilter.PROBLEM_FILTER);
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-3-client-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/belgif-rest-problem-spring-boot-3-client-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..94df1c39
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-client-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+io.github.belgif.rest.problem.spring.client.ClientProblemAutoConfiguration
\ No newline at end of file
diff --git a/belgif-rest-problem-spring-boot-3-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfigurationTest.java b/belgif-rest-problem-spring-boot-3-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfigurationTest.java
new file mode 100644
index 00000000..bc1e4f2a
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfigurationTest.java
@@ -0,0 +1,22 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import io.github.belgif.rest.problem.spring.ProblemJackson2Configuration;
+
+class ClientProblemAutoConfigurationTest {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(ClientProblemAutoConfiguration.class));
+
+ @Test
+ void autoConfiguration() {
+ contextRunner.run((context) -> {
+ assertThat(context).hasSingleBean(ProblemJackson2Configuration.class);
+ });
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-3-core/src/test/resources/logback-test.xml b/belgif-rest-problem-spring-boot-3-client-starter/src/test/resources/logback-test.xml
similarity index 100%
rename from belgif-rest-problem-spring-boot-3-core/src/test/resources/logback-test.xml
rename to belgif-rest-problem-spring-boot-3-client-starter/src/test/resources/logback-test.xml
diff --git a/belgif-rest-problem-spring-boot-3-client/pom.xml b/belgif-rest-problem-spring-boot-3-client/pom.xml
deleted file mode 100644
index fbd0af4a..00000000
--- a/belgif-rest-problem-spring-boot-3-client/pom.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
- 4.0.0
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-parent
- ${revision}
-
-
- belgif-rest-problem-spring-boot-3-client
- ${project.groupId}:${project.artifactId}
- jar
-
-
- 17
-
-
-
-
-
- org.springframework.boot
- spring-boot-dependencies
- ${version.spring.boot.3}
- pom
- import
-
-
-
-
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-core
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common-client
- ${project.version}
-
-
- org.springframework.boot
- spring-boot-autoconfigure
- provided
-
-
- org.springframework
- spring-web
- provided
-
-
- org.springframework
- spring-webflux
- provided
- true
-
-
- org.slf4j
- slf4j-api
- provided
-
-
- com.fasterxml.jackson.core
- jackson-databind
- provided
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.jupiter
- junit-jupiter
- test
-
-
- org.assertj
- assertj-core
- test
-
-
-
-
diff --git a/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestClientCustomizer.java b/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestClientCustomizer.java
deleted file mode 100644
index 65672822..00000000
--- a/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestClientCustomizer.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.web.client.RestClientCustomizer;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestClient;
-
-/**
- * RestClientCustomizer that registers the {@link ProblemResponseErrorHandler}.
- *
- * @see ProblemResponseErrorHandler
- */
-@Component
-@ConditionalOnClass({ RestClient.class, RestClientCustomizer.class })
-public class ProblemRestClientCustomizer extends AbstractProblemRestClientCustomizer implements RestClientCustomizer {
-
- public ProblemRestClientCustomizer(ProblemResponseErrorHandler errorHandler) {
- super(errorHandler);
- }
-}
diff --git a/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestTemplateCustomizer.java b/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestTemplateCustomizer.java
deleted file mode 100644
index ad83b432..00000000
--- a/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestTemplateCustomizer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.web.client.RestTemplateCustomizer;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestTemplate;
-
-/**
- * RestTemplateCustomizer that registers the {@link ProblemResponseErrorHandler}.
- *
- * @see ProblemResponseErrorHandler
- */
-@Component
-@ConditionalOnClass({ RestTemplate.class, RestTemplateCustomizer.class })
-public class ProblemRestTemplateCustomizer extends AbstractProblemRestTemplateCustomizer
- implements RestTemplateCustomizer {
-
- public ProblemRestTemplateCustomizer(ProblemResponseErrorHandler problemResponseErrorHandler) {
- super(problemResponseErrorHandler);
- }
-
-}
diff --git a/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemWebClientCustomizer.java b/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemWebClientCustomizer.java
deleted file mode 100644
index c3b4ecff..00000000
--- a/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemWebClientCustomizer.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.web.reactive.function.client.WebClientCustomizer;
-import org.springframework.stereotype.Component;
-import org.springframework.web.reactive.function.client.WebClient;
-
-/**
- * WebClientCustomizer that registers a filter that converts problem responses to Problem exceptions.
- */
-@Component
-@ConditionalOnClass({ WebClient.class, WebClientCustomizer.class })
-public class ProblemWebClientCustomizer extends AbstractProblemWebClientCustomizer implements WebClientCustomizer {
-
-}
diff --git a/belgif-rest-problem-spring-boot-3-core/pom.xml b/belgif-rest-problem-spring-boot-3-core/pom.xml
deleted file mode 100644
index 791c8e52..00000000
--- a/belgif-rest-problem-spring-boot-3-core/pom.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
- 4.0.0
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-parent
- ${revision}
-
-
- belgif-rest-problem-spring-boot-3-core
- ${project.groupId}:${project.artifactId}
- jar
-
-
- 17
-
-
-
-
-
- org.springframework.boot
- spring-boot-dependencies
- ${version.spring.boot.3}
- pom
- import
-
-
-
-
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common
- ${project.version}
-
-
- org.springframework.boot
- spring-boot-autoconfigure
- provided
-
-
- org.slf4j
- slf4j-api
- provided
-
-
- com.fasterxml.jackson.core
- jackson-databind
- provided
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.jupiter
- junit-jupiter
- test
-
-
- org.assertj
- assertj-core
- test
-
-
-
-
diff --git a/belgif-rest-problem-spring-boot-common-server/pom.xml b/belgif-rest-problem-spring-boot-3-server-starter/pom.xml
similarity index 92%
rename from belgif-rest-problem-spring-boot-common-server/pom.xml
rename to belgif-rest-problem-spring-boot-3-server-starter/pom.xml
index 27b4fcff..7b2b2890 100644
--- a/belgif-rest-problem-spring-boot-common-server/pom.xml
+++ b/belgif-rest-problem-spring-boot-3-server-starter/pom.xml
@@ -9,9 +9,8 @@
${revision}
- belgif-rest-problem-spring-boot-common-server
+ belgif-rest-problem-spring-boot-3-server-starter
${project.groupId}:${project.artifactId}
- Contains shared server components that are common between Spring Boot versions
jar
@@ -33,7 +32,7 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common
+ belgif-rest-problem-spring
${project.version}
diff --git a/belgif-rest-problem-spring-boot-3-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ProblemValidationConfigurationCustomizer.java b/belgif-rest-problem-spring-boot-3-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ProblemValidationConfigurationCustomizer.java
new file mode 100644
index 00000000..d9e612af
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ProblemValidationConfigurationCustomizer.java
@@ -0,0 +1,15 @@
+package io.github.belgif.rest.problem.spring.server;
+
+import jakarta.validation.Configuration;
+
+import org.springframework.boot.autoconfigure.validation.ValidationConfigurationCustomizer;
+
+/**
+ * ValidationConfigurationCustomizer that registers the AnnotationParameterNameProvider.
+ */
+public class ProblemValidationConfigurationCustomizer implements ValidationConfigurationCustomizer {
+
+ public void customize(Configuration> configuration) {
+ configuration.parameterNameProvider(new AnnotationParameterNameProvider());
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-3-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfiguration.java b/belgif-rest-problem-spring-boot-3-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfiguration.java
new file mode 100644
index 00000000..f0913492
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfiguration.java
@@ -0,0 +1,61 @@
+package io.github.belgif.rest.problem.spring.server;
+
+import jakarta.validation.Configuration;
+import jakarta.validation.ConstraintViolationException;
+
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
+import org.springframework.boot.autoconfigure.validation.ValidationConfigurationCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+
+import com.atlassian.oai.validator.springmvc.InvalidRequestException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Spring Boot AutoConfiguration for rest-problem-spring.
+ */
+@AutoConfiguration
+@Import({ io.github.belgif.rest.problem.spring.ProblemJackson2Configuration.class, JacksonAutoConfiguration.class })
+public class ServerProblemAutoConfiguration {
+
+ private ObjectMapper objectMapper;
+
+ public ServerProblemAutoConfiguration(ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper;
+ }
+
+ @ConditionalOnClass(ConstraintViolationException.class)
+ @ConditionalOnWebApplication
+ @Bean
+ public BeanValidationExceptionsHandler beanValidationExceptionsHandler() {
+ return new BeanValidationExceptionsHandler();
+ }
+
+ @ConditionalOnWebApplication
+ @Bean
+ public ProblemExceptionHandler problemExceptionHandler() {
+ return new ProblemExceptionHandler();
+ }
+
+ @ConditionalOnWebApplication
+ @Bean
+ public RoutingExceptionsJackson2Handler routingExceptionsHandler() {
+ return new RoutingExceptionsJackson2Handler();
+ }
+
+ @ConditionalOnClass({ Configuration.class, ValidationConfigurationCustomizer.class })
+ @Bean
+ public ProblemValidationConfigurationCustomizer problemValidationConfigurationCustomizer() {
+ return new ProblemValidationConfigurationCustomizer();
+ }
+
+ @ConditionalOnWebApplication
+ @ConditionalOnClass(InvalidRequestException.class)
+ @Bean
+ public InvalidRequestExceptionJackson2Handler invalidRequestExceptionHandler() {
+ return new InvalidRequestExceptionJackson2Handler(objectMapper);
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-3-server-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/belgif-rest-problem-spring-boot-3-server-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..379d1750
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-server-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+io.github.belgif.rest.problem.spring.server.ServerProblemAutoConfiguration
\ No newline at end of file
diff --git a/belgif-rest-problem-spring-boot-3-server-starter/src/test/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfigurationTest.java b/belgif-rest-problem-spring-boot-3-server-starter/src/test/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfigurationTest.java
new file mode 100644
index 00000000..44245f70
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-3-server-starter/src/test/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfigurationTest.java
@@ -0,0 +1,23 @@
+package io.github.belgif.rest.problem.spring.server;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import io.github.belgif.rest.problem.spring.ProblemJackson2Configuration;
+
+class ServerProblemAutoConfigurationTest {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(ServerProblemAutoConfiguration.class));
+
+ @Test
+ void autoConfiguration() {
+ contextRunner.run((context) -> {
+ assertThat(context).hasSingleBean(ProblemJackson2Configuration.class);
+ });
+ }
+
+}
diff --git a/belgif-rest-problem-spring-boot-3-server/src/test/resources/logback-test.xml b/belgif-rest-problem-spring-boot-3-server-starter/src/test/resources/logback-test.xml
similarity index 100%
rename from belgif-rest-problem-spring-boot-3-server/src/test/resources/logback-test.xml
rename to belgif-rest-problem-spring-boot-3-server-starter/src/test/resources/logback-test.xml
diff --git a/belgif-rest-problem-spring-boot-3-server/src/main/java/io/github/belgif/rest/problem/spring/ProblemValidationConfigurationCustomizer.java b/belgif-rest-problem-spring-boot-3-server/src/main/java/io/github/belgif/rest/problem/spring/ProblemValidationConfigurationCustomizer.java
deleted file mode 100644
index c7ef15f5..00000000
--- a/belgif-rest-problem-spring-boot-3-server/src/main/java/io/github/belgif/rest/problem/spring/ProblemValidationConfigurationCustomizer.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import jakarta.validation.Configuration;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.validation.ValidationConfigurationCustomizer;
-import org.springframework.stereotype.Component;
-
-/**
- * ValidationConfigurationCustomizer that registers the AnnotationParameterNameProvider.
- */
-@Component
-@ConditionalOnClass({ Configuration.class, ValidationConfigurationCustomizer.class })
-public class ProblemValidationConfigurationCustomizer extends AbstractProblemValidationConfigurationCustomizer
- implements ValidationConfigurationCustomizer {
-
-}
diff --git a/belgif-rest-problem-spring-boot-3/pom.xml b/belgif-rest-problem-spring-boot-3/pom.xml
index af707bb5..d0fcfe73 100644
--- a/belgif-rest-problem-spring-boot-3/pom.xml
+++ b/belgif-rest-problem-spring-boot-3/pom.xml
@@ -16,12 +16,12 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-client
+ belgif-rest-problem-spring-boot-3-client-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-server
+ belgif-rest-problem-spring-boot-3-server-starter
${project.version}
diff --git a/belgif-rest-problem-spring-boot-4-client/pom.xml b/belgif-rest-problem-spring-boot-4-client-starter/pom.xml
similarity index 89%
rename from belgif-rest-problem-spring-boot-4-client/pom.xml
rename to belgif-rest-problem-spring-boot-4-client-starter/pom.xml
index 56d9c6a6..238ec2ee 100644
--- a/belgif-rest-problem-spring-boot-4-client/pom.xml
+++ b/belgif-rest-problem-spring-boot-4-client-starter/pom.xml
@@ -9,7 +9,7 @@
${revision}
- belgif-rest-problem-spring-boot-4-client
+ belgif-rest-problem-spring-boot-4-client-starter
${project.groupId}:${project.artifactId}
jar
@@ -32,12 +32,7 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-core
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common-client
+ belgif-rest-problem-spring
${project.version}
diff --git a/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfiguration.java b/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfiguration.java
new file mode 100644
index 00000000..b9f321bd
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfiguration.java
@@ -0,0 +1,48 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration;
+import org.springframework.boot.restclient.RestClientCustomizer;
+import org.springframework.boot.restclient.RestTemplateCustomizer;
+import org.springframework.boot.webclient.WebClientCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+import org.springframework.web.client.RestClient;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import tools.jackson.databind.ObjectMapper;
+
+/**
+ * Spring Boot AutoConfiguration for rest-problem-spring.
+ */
+@AutoConfiguration
+@Import({ io.github.belgif.rest.problem.spring.ProblemJackson3Configuration.class, JacksonAutoConfiguration.class })
+public class ClientProblemAutoConfiguration {
+
+ @Bean
+ public ProblemResponseErrorHandler problemResponseErrorHandler(ObjectMapper objectMapper) {
+ return new ProblemResponseJackson3ErrorHandler(objectMapper);
+ }
+
+ @ConditionalOnClass({ RestClient.class, RestClientCustomizer.class })
+ @Bean
+ public ProblemRestClientCustomizer
+ problemRestClientCustomizer(ProblemResponseErrorHandler problemResponseErrorHandler) {
+ return new ProblemRestClientCustomizer(problemResponseErrorHandler);
+ }
+
+ @ConditionalOnClass({ RestTemplate.class, RestTemplateCustomizer.class })
+ @Bean
+ public ProblemRestTemplateCustomizer
+ problemRestTemplateCustomizer(ProblemResponseErrorHandler problemResponseErrorHandler) {
+ return new ProblemRestTemplateCustomizer(problemResponseErrorHandler);
+ }
+
+ @ConditionalOnClass({ WebClient.class, WebClientCustomizer.class })
+ @Bean
+ public ProblemWebClientCustomizer problemWebClientCustomizer() {
+ return new ProblemWebClientCustomizer();
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestClientCustomizer.java b/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestClientCustomizer.java
new file mode 100644
index 00000000..9621df39
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestClientCustomizer.java
@@ -0,0 +1,23 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import org.springframework.boot.restclient.RestClientCustomizer;
+import org.springframework.web.client.RestClient;
+
+/**
+ * RestClientCustomizer that registers the {@link ProblemResponseErrorHandler}.
+ *
+ * @see ProblemResponseErrorHandler
+ */
+public class ProblemRestClientCustomizer implements RestClientCustomizer {
+
+ private final ProblemResponseErrorHandler errorHandler;
+
+ protected ProblemRestClientCustomizer(ProblemResponseErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ public void customize(RestClient.Builder restClientBuilder) {
+ restClientBuilder.defaultStatusHandler(errorHandler);
+ }
+
+}
diff --git a/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestTemplateCustomizer.java b/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestTemplateCustomizer.java
new file mode 100644
index 00000000..c4bb7ec8
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemRestTemplateCustomizer.java
@@ -0,0 +1,24 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import org.springframework.boot.restclient.RestTemplateCustomizer;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * RestTemplateCustomizer that registers the {@link ProblemResponseErrorHandler}.
+ *
+ * @see ProblemResponseErrorHandler
+ */
+public class ProblemRestTemplateCustomizer implements RestTemplateCustomizer {
+
+ private final ProblemResponseErrorHandler problemResponseErrorHandler;
+
+ public ProblemRestTemplateCustomizer(ProblemResponseErrorHandler problemResponseErrorHandler) {
+ this.problemResponseErrorHandler = problemResponseErrorHandler;
+
+ }
+
+ public void customize(RestTemplate restTemplate) {
+ restTemplate.setErrorHandler(problemResponseErrorHandler);
+ }
+
+}
diff --git a/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemWebClientCustomizer.java b/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemWebClientCustomizer.java
new file mode 100644
index 00000000..797ef3d0
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-client-starter/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemWebClientCustomizer.java
@@ -0,0 +1,15 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import org.springframework.boot.webclient.WebClientCustomizer;
+import org.springframework.web.reactive.function.client.WebClient;
+
+/**
+ * WebClientCustomizer that registers a filter that converts problem responses to Problem exceptions.
+ */
+public class ProblemWebClientCustomizer implements WebClientCustomizer {
+
+ public void customize(WebClient.Builder webClientBuilder) {
+ webClientBuilder.filter(WebClientFilter.PROBLEM_FILTER);
+ }
+
+}
diff --git a/belgif-rest-problem-spring-boot-4-client-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/belgif-rest-problem-spring-boot-4-client-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..94df1c39
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-client-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+io.github.belgif.rest.problem.spring.client.ClientProblemAutoConfiguration
\ No newline at end of file
diff --git a/belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfigurationTest.java b/belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfigurationTest.java
new file mode 100644
index 00000000..175e9ecd
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ClientProblemAutoConfigurationTest.java
@@ -0,0 +1,22 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import io.github.belgif.rest.problem.spring.ProblemJackson3Configuration;
+
+class ClientProblemAutoConfigurationTest {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(ClientProblemAutoConfiguration.class));
+
+ @Test
+ void autoConfiguration() {
+ contextRunner.run((context) -> {
+ assertThat(context).hasSingleBean(ProblemJackson3Configuration.class);
+ });
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemRestClientCustomizerTest.java b/belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ProblemRestClientCustomizerTest.java
similarity index 64%
rename from belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemRestClientCustomizerTest.java
rename to belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ProblemRestClientCustomizerTest.java
index 21325ed7..ef51f745 100644
--- a/belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemRestClientCustomizerTest.java
+++ b/belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ProblemRestClientCustomizerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.client;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
@@ -9,12 +9,12 @@
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.RestClient;
-class AbstractProblemRestClientCustomizerTest {
+class ProblemRestClientCustomizerTest {
@Test
void customize() {
- AbstractProblemResponseErrorHandler handler = mock(AbstractProblemResponseErrorHandler.class);
- AbstractProblemRestClientCustomizer customizer = new AbstractProblemRestClientCustomizer(handler) {
+ ProblemResponseErrorHandler handler = mock(ProblemResponseErrorHandler.class);
+ ProblemRestClientCustomizer customizer = new ProblemRestClientCustomizer(handler) {
};
RestClient.Builder builder = RestClient.builder();
customizer.customize(builder);
diff --git a/belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemRestTemplateCustomizerTest.java b/belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ProblemRestTemplateCustomizerTest.java
similarity index 56%
rename from belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemRestTemplateCustomizerTest.java
rename to belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ProblemRestTemplateCustomizerTest.java
index 8f46d473..46c9a121 100644
--- a/belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemRestTemplateCustomizerTest.java
+++ b/belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ProblemRestTemplateCustomizerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.client;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
@@ -6,12 +6,12 @@
import org.junit.jupiter.api.Test;
import org.springframework.web.client.RestTemplate;
-class AbstractProblemRestTemplateCustomizerTest {
+class ProblemRestTemplateCustomizerTest {
@Test
void customize() {
- AbstractProblemResponseErrorHandler handler = mock(AbstractProblemResponseErrorHandler.class);
- AbstractProblemRestTemplateCustomizer customizer = new AbstractProblemRestTemplateCustomizer(handler) {
+ ProblemResponseErrorHandler handler = mock(ProblemResponseErrorHandler.class);
+ ProblemRestTemplateCustomizer customizer = new ProblemRestTemplateCustomizer(handler) {
};
RestTemplate restTemplate = new RestTemplate();
customizer.customize(restTemplate);
diff --git a/belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemWebClientCustomizerTest.java b/belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ProblemWebClientCustomizerTest.java
similarity index 94%
rename from belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemWebClientCustomizerTest.java
rename to belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ProblemWebClientCustomizerTest.java
index f1460e2a..1d72d27d 100644
--- a/belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemWebClientCustomizerTest.java
+++ b/belgif-rest-problem-spring-boot-4-client-starter/src/test/java/io/github/belgif/rest/problem/spring/client/ProblemWebClientCustomizerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.client;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
@@ -20,9 +20,9 @@
import reactor.core.publisher.Mono;
@ExtendWith(MockitoExtension.class)
-class AbstractProblemWebClientCustomizerTest {
+class ProblemWebClientCustomizerTest {
- private final AbstractProblemWebClientCustomizer customizer = new AbstractProblemWebClientCustomizer() {
+ private final ProblemWebClientCustomizer customizer = new ProblemWebClientCustomizer() {
};
@Mock
diff --git a/belgif-rest-problem-spring-boot-4-client/src/test/resources/logback-test.xml b/belgif-rest-problem-spring-boot-4-client-starter/src/test/resources/logback-test.xml
similarity index 100%
rename from belgif-rest-problem-spring-boot-4-client/src/test/resources/logback-test.xml
rename to belgif-rest-problem-spring-boot-4-client-starter/src/test/resources/logback-test.xml
diff --git a/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestClientCustomizer.java b/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestClientCustomizer.java
deleted file mode 100644
index 7c9f4188..00000000
--- a/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestClientCustomizer.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.restclient.RestClientCustomizer;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestClient;
-
-/**
- * RestClientCustomizer that registers the {@link ProblemResponseErrorHandler}.
- *
- * @see ProblemResponseErrorHandler
- */
-@Component
-@ConditionalOnClass({ RestClient.class, RestClientCustomizer.class })
-public class ProblemRestClientCustomizer extends AbstractProblemRestClientCustomizer implements RestClientCustomizer {
-
- public ProblemRestClientCustomizer(ProblemResponseErrorHandler errorHandler) {
- super(errorHandler);
- }
-
-}
diff --git a/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestTemplateCustomizer.java b/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestTemplateCustomizer.java
deleted file mode 100644
index 02c7b37c..00000000
--- a/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemRestTemplateCustomizer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.restclient.RestTemplateCustomizer;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestTemplate;
-
-/**
- * RestTemplateCustomizer that registers the {@link ProblemResponseErrorHandler}.
- *
- * @see ProblemResponseErrorHandler
- */
-@Component
-@ConditionalOnClass({ RestTemplate.class, RestTemplateCustomizer.class })
-public class ProblemRestTemplateCustomizer extends AbstractProblemRestTemplateCustomizer
- implements RestTemplateCustomizer {
-
- public ProblemRestTemplateCustomizer(ProblemResponseErrorHandler problemResponseErrorHandler) {
- super(problemResponseErrorHandler);
- }
-
-}
diff --git a/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemWebClientCustomizer.java b/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemWebClientCustomizer.java
deleted file mode 100644
index f7ad2295..00000000
--- a/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemWebClientCustomizer.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.webclient.WebClientCustomizer;
-import org.springframework.stereotype.Component;
-import org.springframework.web.reactive.function.client.WebClient;
-
-/**
- * WebClientCustomizer that registers a filter that converts problem responses to Problem exceptions.
- */
-@Component
-@ConditionalOnClass({ WebClient.class, WebClientCustomizer.class })
-public class ProblemWebClientCustomizer extends AbstractProblemWebClientCustomizer implements WebClientCustomizer {
-
-}
diff --git a/belgif-rest-problem-spring-boot-4-core/pom.xml b/belgif-rest-problem-spring-boot-4-core/pom.xml
deleted file mode 100644
index 612ac9e6..00000000
--- a/belgif-rest-problem-spring-boot-4-core/pom.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
- 4.0.0
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-parent
- ${revision}
-
-
- belgif-rest-problem-spring-boot-4-core
- ${project.groupId}:${project.artifactId}
- jar
-
-
- 17
-
-
-
-
-
- org.springframework.boot
- spring-boot-dependencies
- ${version.spring.boot.4}
- pom
- import
-
-
-
-
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common
- ${project.version}
-
-
- org.springframework.boot
- spring-boot-autoconfigure
- provided
-
-
- org.springframework.boot
- spring-boot-starter-jackson
- provided
-
-
- org.slf4j
- slf4j-api
- provided
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.jupiter
- junit-jupiter
- test
-
-
- org.assertj
- assertj-core
- test
-
-
-
-
diff --git a/belgif-rest-problem-spring-boot-4-server/pom.xml b/belgif-rest-problem-spring-boot-4-server-starter/pom.xml
similarity index 89%
rename from belgif-rest-problem-spring-boot-4-server/pom.xml
rename to belgif-rest-problem-spring-boot-4-server-starter/pom.xml
index 825b1920..75b0d368 100644
--- a/belgif-rest-problem-spring-boot-4-server/pom.xml
+++ b/belgif-rest-problem-spring-boot-4-server-starter/pom.xml
@@ -9,7 +9,7 @@
${revision}
- belgif-rest-problem-spring-boot-4-server
+ belgif-rest-problem-spring-boot-4-server-starter
${project.groupId}:${project.artifactId}
jar
@@ -32,12 +32,7 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-core
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common-server
+ belgif-rest-problem-spring
${project.version}
diff --git a/belgif-rest-problem-spring-boot-4-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ProblemValidationConfigurationCustomizer.java b/belgif-rest-problem-spring-boot-4-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ProblemValidationConfigurationCustomizer.java
new file mode 100644
index 00000000..d779d3bc
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ProblemValidationConfigurationCustomizer.java
@@ -0,0 +1,15 @@
+package io.github.belgif.rest.problem.spring.server;
+
+import jakarta.validation.Configuration;
+
+import org.springframework.boot.validation.autoconfigure.ValidationConfigurationCustomizer;
+
+/**
+ * ValidationConfigurationCustomizer that registers the AnnotationParameterNameProvider.
+ */
+public class ProblemValidationConfigurationCustomizer implements ValidationConfigurationCustomizer {
+
+ public void customize(Configuration> configuration) {
+ configuration.parameterNameProvider(new AnnotationParameterNameProvider());
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-4-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfiguration.java b/belgif-rest-problem-spring-boot-4-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfiguration.java
new file mode 100644
index 00000000..c3adfa5c
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-server-starter/src/main/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfiguration.java
@@ -0,0 +1,62 @@
+package io.github.belgif.rest.problem.spring.server;
+
+import jakarta.validation.Configuration;
+import jakarta.validation.ConstraintViolationException;
+
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration;
+import org.springframework.boot.validation.autoconfigure.ValidationConfigurationCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+
+import com.atlassian.oai.validator.springmvc.InvalidRequestException;
+
+import tools.jackson.databind.ObjectMapper;
+
+/**
+ * Spring Boot AutoConfiguration for rest-problem-spring.
+ */
+@AutoConfiguration
+@Import({ io.github.belgif.rest.problem.spring.ProblemJackson3Configuration.class, JacksonAutoConfiguration.class })
+public class ServerProblemAutoConfiguration {
+
+ private ObjectMapper objectMapper;
+
+ public ServerProblemAutoConfiguration(ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper;
+ }
+
+ @ConditionalOnClass(ConstraintViolationException.class)
+ @ConditionalOnWebApplication
+ @Bean
+ public BeanValidationExceptionsHandler beanValidationExceptionsHandler() {
+ return new BeanValidationExceptionsHandler();
+ }
+
+ @ConditionalOnWebApplication
+ @Bean
+ public ProblemExceptionHandler problemExceptionHandler() {
+ return new ProblemExceptionHandler();
+ }
+
+ @ConditionalOnWebApplication
+ @Bean
+ public RoutingExceptionsJackson3Handler routingExceptionsHandler() {
+ return new RoutingExceptionsJackson3Handler();
+ }
+
+ @ConditionalOnClass({ Configuration.class, ValidationConfigurationCustomizer.class })
+ @Bean
+ public ProblemValidationConfigurationCustomizer problemValidationConfigurationCustomizer() {
+ return new ProblemValidationConfigurationCustomizer();
+ }
+
+ @ConditionalOnWebApplication
+ @ConditionalOnClass(InvalidRequestException.class)
+ @Bean
+ public InvalidRequestExceptionJackson3Handler invalidRequestExceptionHandler() {
+ return new InvalidRequestExceptionJackson3Handler(objectMapper);
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-4-server-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/belgif-rest-problem-spring-boot-4-server-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..379d1750
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-server-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+io.github.belgif.rest.problem.spring.server.ServerProblemAutoConfiguration
\ No newline at end of file
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemValidationConfigurationCustomizerTest.java b/belgif-rest-problem-spring-boot-4-server-starter/src/test/java/io/github/belgif/rest/problem/spring/server/ProblemValidationConfigurationCustomizerTest.java
similarity index 76%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemValidationConfigurationCustomizerTest.java
rename to belgif-rest-problem-spring-boot-4-server-starter/src/test/java/io/github/belgif/rest/problem/spring/server/ProblemValidationConfigurationCustomizerTest.java
index 4a4cf774..72d543d9 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemValidationConfigurationCustomizerTest.java
+++ b/belgif-rest-problem-spring-boot-4-server-starter/src/test/java/io/github/belgif/rest/problem/spring/server/ProblemValidationConfigurationCustomizerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
@@ -14,11 +14,10 @@
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
-class AbstractProblemValidationConfigurationCustomizerTest {
+class ProblemValidationConfigurationCustomizerTest {
- private final AbstractProblemValidationConfigurationCustomizer customizer =
- new AbstractProblemValidationConfigurationCustomizer() {
- };
+ private final ProblemValidationConfigurationCustomizer customizer =
+ new ProblemValidationConfigurationCustomizer();
@Mock
private Configuration configuration;
diff --git a/belgif-rest-problem-spring-boot-4-server-starter/src/test/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfigurationTest.java b/belgif-rest-problem-spring-boot-4-server-starter/src/test/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfigurationTest.java
new file mode 100644
index 00000000..795d8059
--- /dev/null
+++ b/belgif-rest-problem-spring-boot-4-server-starter/src/test/java/io/github/belgif/rest/problem/spring/server/ServerProblemAutoConfigurationTest.java
@@ -0,0 +1,23 @@
+package io.github.belgif.rest.problem.spring.server;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import io.github.belgif.rest.problem.spring.ProblemJackson3Configuration;
+
+class ServerProblemAutoConfigurationTest {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(ServerProblemAutoConfiguration.class));
+
+ @Test
+ void autoConfiguration() {
+ contextRunner.run((context) -> {
+ assertThat(context).hasSingleBean(ProblemJackson3Configuration.class);
+ });
+ }
+
+}
diff --git a/belgif-rest-problem-spring-boot-4-core/src/test/resources/logback-test.xml b/belgif-rest-problem-spring-boot-4-server-starter/src/test/resources/logback-test.xml
similarity index 100%
rename from belgif-rest-problem-spring-boot-4-core/src/test/resources/logback-test.xml
rename to belgif-rest-problem-spring-boot-4-server-starter/src/test/resources/logback-test.xml
diff --git a/belgif-rest-problem-spring-boot-4-server/src/main/java/io/github/belgif/rest/problem/spring/ProblemValidationConfigurationCustomizer.java b/belgif-rest-problem-spring-boot-4-server/src/main/java/io/github/belgif/rest/problem/spring/ProblemValidationConfigurationCustomizer.java
deleted file mode 100644
index 8e7fbbfb..00000000
--- a/belgif-rest-problem-spring-boot-4-server/src/main/java/io/github/belgif/rest/problem/spring/ProblemValidationConfigurationCustomizer.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import jakarta.validation.Configuration;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.validation.autoconfigure.ValidationConfigurationCustomizer;
-import org.springframework.stereotype.Component;
-
-/**
- * ValidationConfigurationCustomizer that registers the AnnotationParameterNameProvider.
- */
-@Component
-@ConditionalOnClass({ Configuration.class, ValidationConfigurationCustomizer.class })
-public class ProblemValidationConfigurationCustomizer extends AbstractProblemValidationConfigurationCustomizer
- implements ValidationConfigurationCustomizer {
-
-}
diff --git a/belgif-rest-problem-spring-boot-4/pom.xml b/belgif-rest-problem-spring-boot-4-starter/pom.xml
similarity index 78%
rename from belgif-rest-problem-spring-boot-4/pom.xml
rename to belgif-rest-problem-spring-boot-4-starter/pom.xml
index 4ff85f26..dcc2589e 100644
--- a/belgif-rest-problem-spring-boot-4/pom.xml
+++ b/belgif-rest-problem-spring-boot-4-starter/pom.xml
@@ -9,19 +9,19 @@
${revision}
- belgif-rest-problem-spring-boot-4
+ belgif-rest-problem-spring-boot-4-starter
${project.groupId}:${project.artifactId}
jar
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-client
+ belgif-rest-problem-spring-boot-4-client-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-server
+ belgif-rest-problem-spring-boot-4-server-starter
${project.version}
diff --git a/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemRestClientCustomizer.java b/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemRestClientCustomizer.java
deleted file mode 100644
index a5b70bd5..00000000
--- a/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemRestClientCustomizer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.web.client.RestClient;
-
-/**
- * RestClientCustomizer that registers the {@link AbstractProblemResponseErrorHandler}.
- *
- * @see AbstractProblemResponseErrorHandler
- */
-public abstract class AbstractProblemRestClientCustomizer {
-
- private final AbstractProblemResponseErrorHandler errorHandler;
-
- protected AbstractProblemRestClientCustomizer(AbstractProblemResponseErrorHandler errorHandler) {
- this.errorHandler = errorHandler;
- }
-
- public void customize(RestClient.Builder restClientBuilder) {
- restClientBuilder.defaultStatusHandler(errorHandler);
- }
-
-}
diff --git a/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemRestTemplateCustomizer.java b/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemRestTemplateCustomizer.java
deleted file mode 100644
index 6e85fe78..00000000
--- a/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemRestTemplateCustomizer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.web.client.RestTemplate;
-
-/**
- * RestTemplateCustomizer that registers the {@link AbstractProblemResponseErrorHandler}.
- *
- * @see AbstractProblemResponseErrorHandler
- */
-public abstract class AbstractProblemRestTemplateCustomizer {
-
- private final AbstractProblemResponseErrorHandler problemResponseErrorHandler;
-
- protected AbstractProblemRestTemplateCustomizer(AbstractProblemResponseErrorHandler problemResponseErrorHandler) {
- this.problemResponseErrorHandler = problemResponseErrorHandler;
- }
-
- public void customize(RestTemplate restTemplate) {
- restTemplate.setErrorHandler(problemResponseErrorHandler);
- }
-
-}
diff --git a/belgif-rest-problem-spring-boot-common-client/src/test/resources/logback-test.xml b/belgif-rest-problem-spring-boot-common-client/src/test/resources/logback-test.xml
deleted file mode 100644
index fe45af16..00000000
--- a/belgif-rest-problem-spring-boot-common-client/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
- %d [%thread] %.-1level %logger{36} %M - %msg%n
-
-
- ERROR
- DENY
- ACCEPT
-
- System.out
-
-
-
-
- %d [%thread] %.-1level %logger{36} %M - %msg%n
-
-
- ERROR
- ACCEPT
- DENY
-
- System.err
-
-
-
-
-
-
-
-
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/NoResourceFoundExceptionHandler.java b/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/NoResourceFoundExceptionHandler.java
deleted file mode 100644
index ad2e4d68..00000000
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/NoResourceFoundExceptionHandler.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
-import org.springframework.core.annotation.Order;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-import org.springframework.web.servlet.resource.NoResourceFoundException;
-
-import io.github.belgif.rest.problem.ResourceNotFoundProblem;
-import io.github.belgif.rest.problem.api.Problem;
-
-@RestControllerAdvice
-@Order(1)
-@ConditionalOnWebApplication
-public class NoResourceFoundExceptionHandler {
-
- @ExceptionHandler(NoResourceFoundException.class)
- public ResponseEntity handleNoResourceFoundException(
- NoResourceFoundException exception) {
- ResourceNotFoundProblem problem = new ResourceNotFoundProblem();
- problem.setDetail("No resource %s found".formatted(
- exception.getResourcePath().startsWith("/") ? exception.getResourcePath()
- : "/" + exception.getResourcePath()));
- return ProblemMediaType.INSTANCE.toResponse(problem);
- }
-
-}
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/resources/META-INF/services/io.github.belgif.rest.problem.i18n.LocaleResolver b/belgif-rest-problem-spring-boot-common-server/src/main/resources/META-INF/services/io.github.belgif.rest.problem.i18n.LocaleResolver
deleted file mode 100644
index 8ac9f41a..00000000
--- a/belgif-rest-problem-spring-boot-common-server/src/main/resources/META-INF/services/io.github.belgif.rest.problem.i18n.LocaleResolver
+++ /dev/null
@@ -1 +0,0 @@
-io.github.belgif.rest.problem.spring.i18n.LocaleContextHolderLocaleResolver
\ No newline at end of file
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/NoResourceFoundExceptionHandlerTest.java b/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/NoResourceFoundExceptionHandlerTest.java
deleted file mode 100644
index 5de8f636..00000000
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/NoResourceFoundExceptionHandlerTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import static org.assertj.core.api.Assertions.*;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.servlet.resource.NoResourceFoundException;
-
-import io.github.belgif.rest.problem.ResourceNotFoundProblem;
-import io.github.belgif.rest.problem.api.Problem;
-
-class NoResourceFoundExceptionHandlerTest {
-
- private final NoResourceFoundExceptionHandler handler = new NoResourceFoundExceptionHandler();
-
- @Test
- void handleNoResourceFoundException() {
- ResponseEntity entity = handler.handleNoResourceFoundException(
- new NoResourceFoundException(HttpMethod.GET, "/test"));
- assertThat(entity.getStatusCode().value()).isEqualTo(404);
- assertThat(entity.getHeaders().getContentType()).isEqualTo(ProblemMediaType.INSTANCE);
- ResourceNotFoundProblem problem = (ResourceNotFoundProblem) entity.getBody();
- assertThat(problem.getDetail()).isEqualTo("No resource /test found");
- }
-
- @Test
- void handleNoResourceFoundExceptionAddsLeadingSlash() {
- ResponseEntity entity = handler.handleNoResourceFoundException(
- new NoResourceFoundException(HttpMethod.GET, "test"));
- assertThat(entity.getStatusCode().value()).isEqualTo(404);
- assertThat(entity.getHeaders().getContentType()).isEqualTo(ProblemMediaType.INSTANCE);
- ResourceNotFoundProblem problem = (ResourceNotFoundProblem) entity.getBody();
- assertThat(problem.getDetail()).isEqualTo("No resource /test found");
- }
-
-}
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/resources/logback-test.xml b/belgif-rest-problem-spring-boot-common-server/src/test/resources/logback-test.xml
deleted file mode 100644
index fe45af16..00000000
--- a/belgif-rest-problem-spring-boot-common-server/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
- %d [%thread] %.-1level %logger{36} %M - %msg%n
-
-
- ERROR
- DENY
- ACCEPT
-
- System.out
-
-
-
-
- %d [%thread] %.-1level %logger{36} %M - %msg%n
-
-
- ERROR
- ACCEPT
- DENY
-
- System.err
-
-
-
-
-
-
-
-
diff --git a/belgif-rest-problem-spring-boot-common/pom.xml b/belgif-rest-problem-spring-boot-common/pom.xml
deleted file mode 100644
index cd7feac7..00000000
--- a/belgif-rest-problem-spring-boot-common/pom.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
- 4.0.0
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-parent
- ${revision}
-
-
- belgif-rest-problem-spring-boot-common
- ${project.groupId}:${project.artifactId}
- Contains shared components that are common between Spring Boot versions
- jar
-
-
- 17
-
-
-
-
-
- org.springframework.boot
- spring-boot-dependencies
- ${version.spring.boot.3}
- pom
- import
-
-
-
-
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem
- ${project.version}
-
-
- org.springframework.boot
- spring-boot-autoconfigure
- provided
-
-
- org.springframework
- spring-web
- provided
-
-
- org.slf4j
- slf4j-api
- provided
-
-
- com.fasterxml.jackson.core
- jackson-databind
- provided
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.jupiter
- junit-jupiter
- test
-
-
- org.assertj
- assertj-core
- test
-
-
-
-
diff --git a/belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemAutoConfiguration.java b/belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemAutoConfiguration.java
deleted file mode 100644
index e3fe9a52..00000000
--- a/belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemAutoConfiguration.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.ComponentScan;
-
-/**
- * Spring Boot AutoConfiguration for rest-problem-spring.
- */
-@AutoConfiguration
-@ComponentScan("io.github.belgif.rest.problem")
-@EnableConfigurationProperties({ ProblemConfigurationProperties.class, ProblemExtConfigurationProperties.class })
-public class ProblemAutoConfiguration {
-
-}
diff --git a/belgif-rest-problem-spring-boot-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/belgif-rest-problem-spring-boot-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index f115dc5b..00000000
--- a/belgif-rest-problem-spring-boot-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1 +0,0 @@
-io.github.belgif.rest.problem.spring.ProblemAutoConfiguration
\ No newline at end of file
diff --git a/belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/ProblemAutoConfigurationTest.java b/belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/ProblemAutoConfigurationTest.java
deleted file mode 100644
index c5a5c66b..00000000
--- a/belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/ProblemAutoConfigurationTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package io.github.belgif.rest.problem.spring;
-
-import static org.assertj.core.api.Assertions.*;
-
-import org.junit.jupiter.api.Test;
-
-class ProblemAutoConfigurationTest {
-
- @Test
- void autoConfiguration() {
- assertThatNoException().isThrownBy(ProblemAutoConfiguration::new);
- }
-
-}
diff --git a/belgif-rest-problem-spring-boot-common/src/test/resources/logback-test.xml b/belgif-rest-problem-spring-boot-common/src/test/resources/logback-test.xml
deleted file mode 100644
index fe45af16..00000000
--- a/belgif-rest-problem-spring-boot-common/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
- %d [%thread] %.-1level %logger{36} %M - %msg%n
-
-
- ERROR
- DENY
- ACCEPT
-
- System.out
-
-
-
-
- %d [%thread] %.-1level %logger{36} %M - %msg%n
-
-
- ERROR
- ACCEPT
- DENY
-
- System.err
-
-
-
-
-
-
-
-
diff --git a/belgif-rest-problem-spring-boot-3-server/pom.xml b/belgif-rest-problem-spring/pom.xml
similarity index 74%
rename from belgif-rest-problem-spring-boot-3-server/pom.xml
rename to belgif-rest-problem-spring/pom.xml
index 80f1419b..7581ffe6 100644
--- a/belgif-rest-problem-spring-boot-3-server/pom.xml
+++ b/belgif-rest-problem-spring/pom.xml
@@ -9,8 +9,9 @@
${revision}
- belgif-rest-problem-spring-boot-3-server
+ belgif-rest-problem-spring
${project.groupId}:${project.artifactId}
+ Contains shared components that are common between Spring Boot versions
jar
@@ -32,28 +33,31 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-core
+ belgif-rest-problem
${project.version}
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common-server
- ${project.version}
-
-
- org.springframework.boot
- spring-boot-autoconfigure
+ org.springframework
+ spring-web
provided
org.springframework
- spring-web
+ spring-webflux
provided
+ true
org.springframework
spring-webmvc
provided
+ true
+
+
+ com.atlassian.oai
+ swagger-request-validator-springmvc
+ 2.46.0
+ true
org.slf4j
@@ -66,39 +70,49 @@
provided
- jakarta.validation
- jakarta.validation-api
+ tools.jackson.core
+ jackson-databind
+ ${version.jackson3.minimal}
provided
+
jakarta.servlet
jakarta.servlet-api
provided
+
+
+ org.hibernate.validator
+ hibernate-validator
+ provided
+ true
+
- com.atlassian.oai
- swagger-request-validator-springmvc
- 2.46.0
+ jakarta.validation
+ jakarta.validation-api
+ provided
true
+
- org.springframework.boot
- spring-boot-starter-test
+ org.junit.jupiter
+ junit-jupiter
test
- org.springframework.boot
- spring-boot-starter-validation
+ org.assertj
+ assertj-core
test
- org.junit.jupiter
- junit-jupiter
+ org.mockito
+ mockito-junit-jupiter
test
- org.assertj
- assertj-core
+ org.springframework
+ spring-test
test
diff --git a/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/EnableProblemModule.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/EnableProblemModule.java
new file mode 100644
index 00000000..f8ce0e35
--- /dev/null
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/EnableProblemModule.java
@@ -0,0 +1,127 @@
+package io.github.belgif.rest.problem.spring;
+
+import java.lang.annotation.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.ImportSelector;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
+
+import io.github.belgif.rest.problem.spring.client.ProblemResponseJackson2ErrorHandler;
+import io.github.belgif.rest.problem.spring.client.ProblemResponseJackson3ErrorHandler;
+import io.github.belgif.rest.problem.spring.server.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Import(EnableProblemModule.ProblemModuleImportSelector.class)
+/**
+ * Activate support of the belgif-rest-problem integration for spring.
+ *
+ * When running in a Spring Boot environment, use of the 'starter' modules is recommended, which require less
+ * configuration.
+ *
+ * Attributes select which optional integrations are activated.
+ * An application using this module, should provide an ObjectMapper bean on which the {@link SpringProblemModule}
+ * or {@link SpringProblemModuleJackson3} support bean is registered.
+ */
+public @interface EnableProblemModule {
+
+ /**
+ * Activate RestControllerAdvice for rest-problem support on any RestController
+ */
+ boolean server() default true;
+
+ /**
+ * Creates support beans for REST clients.
+ * Requires:
+ * - setting ProblemResponseErrorHandler as defaultStatusHandler on the client
+ * - or for {@link org.springframework.web.reactive.function.client.WebClient}, setting PROBLEM_FILTER from
+ * {@link io.github.belgif.rest.problem.spring.client.WebClientFilter}
+ */
+ boolean client() default true;
+
+ /**
+ * Jackson version being used
+ */
+ JacksonVersion jacksonVersion() default JacksonVersion.JACKSON_3;
+
+ enum JacksonVersion {
+ JACKSON_2, JACKSON_3
+ }
+
+ /**
+ * Convert Jakarta Bean Validation exceptions to badRequestProblem
+ *
+ * Only supported server-side.
+ * For proper problem messages, requires using the {@link AnnotationParameterNameProvider} on the used
+ * {@link jakarta.validation.Configuration}
+ */
+ boolean beanValidation() default false;
+
+ /**
+ * Convert input validation exceptions from the swagger-request-validator library to badRequestProblem
+ *
+ * Only supported server-side
+ */
+ boolean swaggerRequestValidator() default false;
+
+ class ProblemModuleImportSelector implements ImportSelector {
+
+ @Override
+ public String[] selectImports(AnnotationMetadata importingClassMetadata) {
+ Map attributes = importingClassMetadata
+ .getAnnotationAttributes(EnableProblemModule.class.getName());
+ boolean includeServer = (boolean) attributes.get("server");
+ boolean includeClient = (boolean) attributes.get("client");
+ boolean useJackson3 = (attributes.get("jacksonVersion") == JacksonVersion.JACKSON_3);
+ boolean includeBeanValidation = (boolean) attributes.get("beanValidation");
+ boolean includeSwaggerRequestValidator = (boolean) attributes.get("swaggerRequestValidator");
+
+ List imports = new ArrayList<>();
+
+ Class commonConfig = useJackson3 ? ProblemJackson3Configuration.class : ProblemJackson2Configuration.class;
+ imports.add(commonConfig.getName());
+
+ if (includeServer) {
+ imports.add(ProblemExceptionHandler.class.getName());
+ Class routingExceptionsHandler =
+ useJackson3 ? RoutingExceptionsJackson3Handler.class : RoutingExceptionsJackson2Handler.class;
+ imports.add(routingExceptionsHandler.getName());
+
+ if (includeBeanValidation) {
+ imports.add(BeanValidationConfiguration.class.getName());
+ }
+ if (includeSwaggerRequestValidator) {
+ Class invalidRequestExceptionHandler = useJackson3 ? InvalidRequestExceptionJackson3Handler.class
+ : InvalidRequestExceptionJackson2Handler.class;
+ imports.add(invalidRequestExceptionHandler.getName());
+ }
+ }
+ if (includeClient) {
+ Class clientConfig =
+ useJackson3 ? ProblemResponseJackson3ErrorHandler.class
+ : ProblemResponseJackson2ErrorHandler.class;
+ imports.add(clientConfig.getName());
+ }
+ return imports.toArray(new String[imports.size()]);
+ }
+ }
+
+ @Configuration
+ @Import(BeanValidationExceptionsHandler.class)
+ class BeanValidationConfiguration {
+ @Bean
+ public LocalValidatorFactoryBean validator() {
+ LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
+ validator.setConfigurationInitializer(
+ configuration -> configuration.parameterNameProvider(new AnnotationParameterNameProvider()));
+ return validator;
+ }
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemConfigurationProperties.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemConfigurationProperties.java
similarity index 73%
rename from belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemConfigurationProperties.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemConfigurationProperties.java
index 52585db1..c104f59f 100644
--- a/belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemConfigurationProperties.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemConfigurationProperties.java
@@ -4,14 +4,15 @@
import java.util.List;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
import io.github.belgif.rest.problem.config.ProblemConfig;
/**
* Lists all supported application.properties configurations for the belgif-rest-problem-spring library.
*/
-@ConfigurationProperties(prefix = "io.github.belgif.rest.problem")
+@Component // not using @ConfigurationProperties to avoid Spring Boot dependency
public class ProblemConfigurationProperties implements InitializingBean {
private List scanAdditionalProblemPackages = new ArrayList<>();
@@ -20,6 +21,7 @@ public class ProblemConfigurationProperties implements InitializingBean {
private Boolean stackTraceEnabled = null;
+ @Value("${io.github.belgif.rest.problem.scan-additional-problem-packages:#{{}}}")
public void setScanAdditionalProblemPackages(List scanAdditionalProblemPackages) {
this.scanAdditionalProblemPackages = scanAdditionalProblemPackages;
}
@@ -28,10 +30,12 @@ public List getScanAdditionalProblemPackages() {
return scanAdditionalProblemPackages;
}
- public void setI18nEnabled(boolean i18nEnabled) {
+ @Value("${io.github.belgif.rest.problem.i18n-enabled:#{null}}")
+ public void setI18nEnabled(Boolean i18nEnabled) {
this.i18nEnabled = i18nEnabled;
}
+ @Value("${io.github.belgif.rest.problem.stack-trace-enabled:#{null}}")
public void setStackTraceEnabled(Boolean stackTraceEnabled) {
this.stackTraceEnabled = stackTraceEnabled;
}
diff --git a/belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationProperties.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationProperties.java
similarity index 65%
rename from belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationProperties.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationProperties.java
index 3d947fc9..05570665 100644
--- a/belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationProperties.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationProperties.java
@@ -1,25 +1,28 @@
package io.github.belgif.rest.problem.spring;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
import io.github.belgif.rest.problem.config.ProblemConfig;
/**
* Lists all supported application.properties extension configurations for the belgif-rest-problem-spring library.
*/
-@ConfigurationProperties(prefix = "io.github.belgif.rest.problem.ext")
+@Component // not using @ConfigurationProperties to avoid Spring Boot dependency
public class ProblemExtConfigurationProperties implements InitializingBean {
private Boolean issueTypesEnabled = null;
private Boolean inputsArrayEnabled = null;
- public void setIssueTypesEnabled(boolean issueTypesEnabled) {
+ @Value("${io.github.belgif.rest.problem.ext.issue-types-enabled:#{null}}")
+ public void setIssueTypesEnabled(Boolean issueTypesEnabled) {
this.issueTypesEnabled = issueTypesEnabled;
}
- public void setInputsArrayEnabled(boolean inputsArrayEnabled) {
+ @Value("${io.github.belgif.rest.problem.ext.inputs-array-enabled:#{null}}")
+ public void setInputsArrayEnabled(Boolean inputsArrayEnabled) {
this.inputsArrayEnabled = inputsArrayEnabled;
}
diff --git a/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemJackson2Configuration.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemJackson2Configuration.java
new file mode 100644
index 00000000..98263e7d
--- /dev/null
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemJackson2Configuration.java
@@ -0,0 +1,29 @@
+package io.github.belgif.rest.problem.spring;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ProblemJackson2Configuration {
+
+ @Bean
+ ProblemConfigurationProperties problemConfigurationProperties() {
+ return new ProblemConfigurationProperties();
+ }
+
+ @Bean
+ public ProblemExtConfigurationProperties problemExtConfigurationProperties() {
+ return new ProblemExtConfigurationProperties();
+ }
+
+ @Bean
+ public SpringProblemTypeRegistry
+ springProblemTypeRegistry(ProblemConfigurationProperties problemConfigurationProperties) {
+ return new SpringProblemTypeRegistry(problemConfigurationProperties);
+ }
+
+ @Bean
+ public SpringProblemModule springProblemModule(SpringProblemTypeRegistry springProblemTypeRegistry) {
+ return new SpringProblemModule(springProblemTypeRegistry);
+ }
+}
diff --git a/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemJackson3Configuration.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemJackson3Configuration.java
new file mode 100644
index 00000000..23522461
--- /dev/null
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemJackson3Configuration.java
@@ -0,0 +1,29 @@
+package io.github.belgif.rest.problem.spring;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ProblemJackson3Configuration {
+
+ @Bean
+ ProblemConfigurationProperties problemConfigurationProperties() {
+ return new ProblemConfigurationProperties();
+ }
+
+ @Bean
+ public ProblemExtConfigurationProperties problemExtConfigurationProperties() {
+ return new ProblemExtConfigurationProperties();
+ }
+
+ @Bean
+ public SpringProblemTypeRegistry
+ springProblemTypeRegistry(ProblemConfigurationProperties problemConfigurationProperties) {
+ return new SpringProblemTypeRegistry(problemConfigurationProperties);
+ }
+
+ @Bean
+ public SpringProblemModuleJackson3 springProblemModule(SpringProblemTypeRegistry springProblemTypeRegistry) {
+ return new SpringProblemModuleJackson3(springProblemTypeRegistry);
+ }
+}
diff --git a/belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemMediaType.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemMediaType.java
similarity index 100%
rename from belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/ProblemMediaType.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/ProblemMediaType.java
diff --git a/belgif-rest-problem-spring-boot-3-core/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModule.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModule.java
similarity index 100%
rename from belgif-rest-problem-spring-boot-3-core/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModule.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModule.java
diff --git a/belgif-rest-problem-spring-boot-4-core/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModule.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModuleJackson3.java
similarity index 66%
rename from belgif-rest-problem-spring-boot-4-core/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModule.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModuleJackson3.java
index 708a3a9e..d45158d2 100644
--- a/belgif-rest-problem-spring-boot-4-core/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModule.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemModuleJackson3.java
@@ -10,9 +10,9 @@
* @see SpringProblemTypeRegistry
*/
@Component
-public class SpringProblemModule extends ProblemModuleJackson3 {
+public class SpringProblemModuleJackson3 extends ProblemModuleJackson3 {
- public SpringProblemModule(SpringProblemTypeRegistry springProblemTypeRegistry) {
+ public SpringProblemModuleJackson3(SpringProblemTypeRegistry springProblemTypeRegistry) {
super(springProblemTypeRegistry);
}
diff --git a/belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistry.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistry.java
similarity index 100%
rename from belgif-rest-problem-spring-boot-common/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistry.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistry.java
diff --git a/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemResponseErrorHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/AbstractProblemResponseErrorHandler.java
similarity index 89%
rename from belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemResponseErrorHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/AbstractProblemResponseErrorHandler.java
index e1248fd2..e7987027 100644
--- a/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemResponseErrorHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/AbstractProblemResponseErrorHandler.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.client;
import java.io.IOException;
import java.io.InputStream;
@@ -13,11 +13,10 @@
import io.github.belgif.rest.problem.DefaultProblem;
import io.github.belgif.rest.problem.api.Problem;
+import io.github.belgif.rest.problem.spring.ProblemMediaType;
-/**
- * RestTemplate/RestClient error handler that converts problem responses to Problem exceptions.
- */
-public abstract class AbstractProblemResponseErrorHandler extends DefaultResponseErrorHandler {
+public abstract class AbstractProblemResponseErrorHandler extends DefaultResponseErrorHandler
+ implements ProblemResponseErrorHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractProblemResponseErrorHandler.class);
diff --git a/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemResponseErrorHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemResponseErrorHandler.java
new file mode 100644
index 00000000..f37478fd
--- /dev/null
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemResponseErrorHandler.java
@@ -0,0 +1,9 @@
+package io.github.belgif.rest.problem.spring.client;
+
+import org.springframework.web.client.ResponseErrorHandler;
+
+/**
+ * RestTemplate/RestClient error handler that converts problem responses to Problem exceptions.
+ */
+public interface ProblemResponseErrorHandler extends ResponseErrorHandler {
+}
diff --git a/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemResponseErrorHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemResponseJackson2ErrorHandler.java
similarity index 60%
rename from belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemResponseErrorHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemResponseJackson2ErrorHandler.java
index fa92ed58..7b1ef42e 100644
--- a/belgif-rest-problem-spring-boot-3-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemResponseErrorHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemResponseJackson2ErrorHandler.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.client;
import org.springframework.stereotype.Component;
@@ -10,9 +10,9 @@
* RestTemplate/RestClient error handler that converts problem responses to Problem exceptions.
*/
@Component
-public class ProblemResponseErrorHandler extends AbstractProblemResponseErrorHandler {
+public class ProblemResponseJackson2ErrorHandler extends AbstractProblemResponseErrorHandler {
- public ProblemResponseErrorHandler(ObjectMapper objectMapper) {
+ public ProblemResponseJackson2ErrorHandler(ObjectMapper objectMapper) {
super(input -> objectMapper.readValue(input, Problem.class));
}
diff --git a/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemResponseErrorHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemResponseJackson3ErrorHandler.java
similarity index 60%
rename from belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemResponseErrorHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemResponseJackson3ErrorHandler.java
index e92cf6bb..9a72d778 100644
--- a/belgif-rest-problem-spring-boot-4-client/src/main/java/io/github/belgif/rest/problem/spring/ProblemResponseErrorHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/ProblemResponseJackson3ErrorHandler.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.client;
import org.springframework.stereotype.Component;
@@ -9,9 +9,9 @@
* RestTemplate/RestClient error handler that converts problem responses to Problem exceptions.
*/
@Component
-public class ProblemResponseErrorHandler extends AbstractProblemResponseErrorHandler {
+public class ProblemResponseJackson3ErrorHandler extends AbstractProblemResponseErrorHandler {
- public ProblemResponseErrorHandler(ObjectMapper objectMapper) {
+ public ProblemResponseJackson3ErrorHandler(ObjectMapper objectMapper) {
super(input -> objectMapper.readValue(input, Problem.class));
}
diff --git a/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemWebClientCustomizer.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/WebClientFilter.java
similarity index 61%
rename from belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemWebClientCustomizer.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/WebClientFilter.java
index 9636e384..9dd9bf81 100644
--- a/belgif-rest-problem-spring-boot-common-client/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemWebClientCustomizer.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/client/WebClientFilter.java
@@ -1,18 +1,14 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.client;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
-import org.springframework.web.reactive.function.client.WebClient;
import io.github.belgif.rest.problem.api.Problem;
+import io.github.belgif.rest.problem.spring.ProblemMediaType;
import reactor.core.publisher.Mono;
-/**
- * WebClientCustomizer that registers a filter that converts problem responses to Problem exceptions.
- */
-public abstract class AbstractProblemWebClientCustomizer {
-
- private static final ExchangeFilterFunction PROBLEM_FILTER =
+public class WebClientFilter {
+ public static final ExchangeFilterFunction PROBLEM_FILTER =
ExchangeFilterFunction.ofResponseProcessor(response -> {
MediaType mediaType = response.headers().contentType().orElse(null);
if (ProblemMediaType.INSTANCE.isCompatibleWith(mediaType)
@@ -22,9 +18,4 @@ public abstract class AbstractProblemWebClientCustomizer {
return Mono.just(response);
}
});
-
- public void customize(WebClient.Builder webClientBuilder) {
- webClientBuilder.filter(PROBLEM_FILTER);
- }
-
}
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AbstractInvalidRequestExceptionHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AbstractInvalidRequestExceptionHandler.java
similarity index 96%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AbstractInvalidRequestExceptionHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AbstractInvalidRequestExceptionHandler.java
index 78bdc976..8fdde018 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AbstractInvalidRequestExceptionHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AbstractInvalidRequestExceptionHandler.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import java.util.ArrayList;
import java.util.LinkedHashSet;
@@ -22,7 +22,8 @@
import io.github.belgif.rest.problem.api.InputValidationIssue;
import io.github.belgif.rest.problem.api.InputValidationIssues;
import io.github.belgif.rest.problem.api.Problem;
-import io.github.belgif.rest.problem.spring.internal.InvalidRequestExceptionUtil;
+import io.github.belgif.rest.problem.spring.ProblemMediaType;
+import io.github.belgif.rest.problem.spring.server.internal.InvalidRequestExceptionUtil;
/**
* RestController exception handler for InvalidRequestException thrown by Atlassian swagger-request-validator library.
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemValidationConfigurationCustomizer.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AbstractProblemValidationConfigurationCustomizer.java
similarity index 87%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemValidationConfigurationCustomizer.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AbstractProblemValidationConfigurationCustomizer.java
index 4401ab74..277264df 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AbstractProblemValidationConfigurationCustomizer.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AbstractProblemValidationConfigurationCustomizer.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import jakarta.validation.Configuration;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AbstractRoutingExceptionsHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AbstractRoutingExceptionsHandler.java
similarity index 87%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AbstractRoutingExceptionsHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AbstractRoutingExceptionsHandler.java
index cb0566f4..dbf13746 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AbstractRoutingExceptionsHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AbstractRoutingExceptionsHandler.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import java.util.Arrays;
@@ -14,11 +14,14 @@
import org.springframework.web.bind.MissingRequestHeaderException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.servlet.resource.NoResourceFoundException;
import io.github.belgif.rest.problem.BadRequestProblem;
+import io.github.belgif.rest.problem.ResourceNotFoundProblem;
import io.github.belgif.rest.problem.api.InEnum;
import io.github.belgif.rest.problem.api.InputValidationIssues;
import io.github.belgif.rest.problem.api.Problem;
+import io.github.belgif.rest.problem.spring.ProblemMediaType;
/**
* RestController exception handler for routing-related exceptions.
@@ -113,4 +116,14 @@ public ResponseEntity handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupp
return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value()).build();
}
+ @ExceptionHandler(NoResourceFoundException.class)
+ public ResponseEntity handleNoResourceFoundException(
+ NoResourceFoundException exception) {
+ ResourceNotFoundProblem problem = new ResourceNotFoundProblem();
+ problem.setDetail("No resource %s found".formatted(
+ exception.getResourcePath().startsWith("/") ? exception.getResourcePath()
+ : "/" + exception.getResourcePath()));
+ return ProblemMediaType.INSTANCE.toResponse(problem);
+ }
+
}
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AnnotationParameterNameProvider.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AnnotationParameterNameProvider.java
similarity index 78%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AnnotationParameterNameProvider.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AnnotationParameterNameProvider.java
index 29ca1c54..251616fa 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/AnnotationParameterNameProvider.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/AnnotationParameterNameProvider.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import java.util.List;
import java.util.stream.Collectors;
@@ -6,7 +6,7 @@
import jakarta.validation.ParameterNameProvider;
-import io.github.belgif.rest.problem.spring.internal.CachedAnnotationParameterNameSupport;
+import io.github.belgif.rest.problem.spring.server.internal.CachedAnnotationParameterNameSupport;
/**
* ParameterNameProvider that retrieves the parameter name from Spring MVC annotations (if present).
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/BeanValidationExceptionsHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/BeanValidationExceptionsHandler.java
similarity index 89%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/BeanValidationExceptionsHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/BeanValidationExceptionsHandler.java
index 9e7e3046..45bea08b 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/BeanValidationExceptionsHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/BeanValidationExceptionsHandler.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import java.util.Comparator;
import java.util.List;
@@ -6,8 +6,6 @@
import jakarta.validation.ConstraintViolationException;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.annotation.Order;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
@@ -22,15 +20,14 @@
import io.github.belgif.rest.problem.api.InputValidationIssue;
import io.github.belgif.rest.problem.api.InputValidationIssues;
import io.github.belgif.rest.problem.api.Problem;
-import io.github.belgif.rest.problem.spring.internal.BeanValidationExceptionUtil;
-import io.github.belgif.rest.problem.spring.internal.DetermineSourceUtil;
+import io.github.belgif.rest.problem.spring.ProblemMediaType;
+import io.github.belgif.rest.problem.spring.server.internal.BeanValidationExceptionUtil;
+import io.github.belgif.rest.problem.spring.server.internal.DetermineSourceUtil;
/**
* RestController exception handler for exceptions related to bean validation.
*/
@RestControllerAdvice
-@ConditionalOnClass(ConstraintViolationException.class)
-@ConditionalOnWebApplication
@Order(1)
// @Order(1) to take precedence over io.github.belgif.rest.problem.spring.ProblemExceptionHandler
public class BeanValidationExceptionsHandler {
diff --git a/belgif-rest-problem-spring-boot-3-server/src/main/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson2Handler.java
similarity index 78%
rename from belgif-rest-problem-spring-boot-3-server/src/main/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson2Handler.java
index 9db7da99..51e6d110 100644
--- a/belgif-rest-problem-spring-boot-3-server/src/main/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson2Handler.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import java.io.IOException;
import java.io.InputStream;
@@ -8,12 +8,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.RestControllerAdvice;
-import com.atlassian.oai.validator.springmvc.InvalidRequestException;
import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -22,17 +19,15 @@
* RestController exception handler for InvalidRequestException thrown by Atlassian swagger-request-validator library.
*/
@RestControllerAdvice
-@ConditionalOnWebApplication
-@ConditionalOnClass(InvalidRequestException.class)
@Order(1)
// @Order(1) to take precedence over io.github.belgif.rest.problem.spring.ProblemExceptionHandler
-public class InvalidRequestExceptionHandler extends AbstractInvalidRequestExceptionHandler {
+public class InvalidRequestExceptionJackson2Handler extends AbstractInvalidRequestExceptionHandler {
- private static final Logger LOGGER = LoggerFactory.getLogger(InvalidRequestExceptionHandler.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(InvalidRequestExceptionJackson2Handler.class);
private final ObjectMapper mapper;
- public InvalidRequestExceptionHandler(ObjectMapper mapper) {
+ public InvalidRequestExceptionJackson2Handler(ObjectMapper mapper) {
this.mapper = mapper;
}
diff --git a/belgif-rest-problem-spring-boot-4-server/src/main/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson3Handler.java
similarity index 80%
rename from belgif-rest-problem-spring-boot-4-server/src/main/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson3Handler.java
index 8e7725af..6fe9f74f 100644
--- a/belgif-rest-problem-spring-boot-4-server/src/main/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson3Handler.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import java.io.IOException;
import java.io.InputStream;
@@ -8,13 +8,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.RestControllerAdvice;
-import com.atlassian.oai.validator.springmvc.InvalidRequestException;
-
import tools.jackson.core.JsonPointer;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.ObjectMapper;
@@ -23,17 +19,15 @@
* RestController exception handler for InvalidRequestException thrown by Atlassian swagger-request-validator library.
*/
@RestControllerAdvice
-@ConditionalOnWebApplication
-@ConditionalOnClass(InvalidRequestException.class)
@Order(1)
// @Order(1) to take precedence over io.github.belgif.rest.problem.spring.ProblemExceptionHandler
-public class InvalidRequestExceptionHandler extends AbstractInvalidRequestExceptionHandler {
+public class InvalidRequestExceptionJackson3Handler extends AbstractInvalidRequestExceptionHandler {
- private static final Logger LOGGER = LoggerFactory.getLogger(InvalidRequestExceptionHandler.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(InvalidRequestExceptionJackson3Handler.class);
private final ObjectMapper mapper;
- public InvalidRequestExceptionHandler(ObjectMapper mapper) {
+ public InvalidRequestExceptionJackson3Handler(ObjectMapper mapper) {
this.mapper = mapper;
}
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/ProblemExceptionHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/ProblemExceptionHandler.java
similarity index 87%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/ProblemExceptionHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/ProblemExceptionHandler.java
index 4ebeb48a..3b3086b8 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/ProblemExceptionHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/ProblemExceptionHandler.java
@@ -1,14 +1,14 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import io.github.belgif.rest.problem.InternalServerErrorProblem;
import io.github.belgif.rest.problem.api.Problem;
+import io.github.belgif.rest.problem.spring.ProblemMediaType;
/**
* Exception handler for RestControllers.
@@ -19,7 +19,6 @@
*
*/
@RestControllerAdvice
-@ConditionalOnWebApplication
public class ProblemExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(ProblemExceptionHandler.class);
diff --git a/belgif-rest-problem-spring-boot-3-server/src/main/java/io/github/belgif/rest/problem/spring/RoutingExceptionsHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/RoutingExceptionsJackson2Handler.java
similarity index 80%
rename from belgif-rest-problem-spring-boot-3-server/src/main/java/io/github/belgif/rest/problem/spring/RoutingExceptionsHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/RoutingExceptionsJackson2Handler.java
index 0019577f..436ff91d 100644
--- a/belgif-rest-problem-spring-boot-3-server/src/main/java/io/github/belgif/rest/problem/spring/RoutingExceptionsHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/RoutingExceptionsJackson2Handler.java
@@ -1,6 +1,5 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@@ -15,13 +14,12 @@
* RestController exception handler for routing-related exceptions.
*/
@RestControllerAdvice
-@ConditionalOnWebApplication
@Order(1)
// @Order(1) to take precedence over org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
// and io.github.belgif.rest.problem.spring.ProblemExceptionHandler
-public class RoutingExceptionsHandler extends AbstractRoutingExceptionsHandler {
+public class RoutingExceptionsJackson2Handler extends AbstractRoutingExceptionsHandler {
- public RoutingExceptionsHandler() {
+ public RoutingExceptionsJackson2Handler() {
super(JacksonException.class);
}
diff --git a/belgif-rest-problem-spring-boot-4-server/src/main/java/io/github/belgif/rest/problem/spring/RoutingExceptionsHandler.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/RoutingExceptionsJackson3Handler.java
similarity index 80%
rename from belgif-rest-problem-spring-boot-4-server/src/main/java/io/github/belgif/rest/problem/spring/RoutingExceptionsHandler.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/RoutingExceptionsJackson3Handler.java
index 4c3a4956..88853076 100644
--- a/belgif-rest-problem-spring-boot-4-server/src/main/java/io/github/belgif/rest/problem/spring/RoutingExceptionsHandler.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/RoutingExceptionsJackson3Handler.java
@@ -1,6 +1,5 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@@ -14,13 +13,12 @@
* RestController exception handler for routing-related exceptions.
*/
@RestControllerAdvice
-@ConditionalOnWebApplication
@Order(1)
// @Order(1) to take precedence over org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
// and io.github.belgif.rest.problem.spring.ProblemExceptionHandler
-public class RoutingExceptionsHandler extends AbstractRoutingExceptionsHandler {
+public class RoutingExceptionsJackson3Handler extends AbstractRoutingExceptionsHandler {
- public RoutingExceptionsHandler() {
+ public RoutingExceptionsJackson3Handler() {
super(JacksonException.class);
}
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/i18n/LocaleContextHolderLocaleResolver.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/i18n/LocaleContextHolderLocaleResolver.java
similarity index 88%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/i18n/LocaleContextHolderLocaleResolver.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/i18n/LocaleContextHolderLocaleResolver.java
index 0f45a044..b3f8e3b4 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/i18n/LocaleContextHolderLocaleResolver.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/i18n/LocaleContextHolderLocaleResolver.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.i18n;
+package io.github.belgif.rest.problem.spring.server.i18n;
import java.util.Locale;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/BeanValidationExceptionUtil.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/BeanValidationExceptionUtil.java
similarity index 97%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/BeanValidationExceptionUtil.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/BeanValidationExceptionUtil.java
index 38d82eef..a76fee7c 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/BeanValidationExceptionUtil.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/BeanValidationExceptionUtil.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.internal;
+package io.github.belgif.rest.problem.spring.server.internal;
import java.util.Iterator;
import java.util.LinkedList;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/CachedAnnotationParameterNameSupport.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/CachedAnnotationParameterNameSupport.java
similarity index 97%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/CachedAnnotationParameterNameSupport.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/CachedAnnotationParameterNameSupport.java
index 68ac4b1b..fd26d46d 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/CachedAnnotationParameterNameSupport.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/CachedAnnotationParameterNameSupport.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.internal;
+package io.github.belgif.rest.problem.spring.server.internal;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/DetermineSourceUtil.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/DetermineSourceUtil.java
similarity index 98%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/DetermineSourceUtil.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/DetermineSourceUtil.java
index 3c7c5e65..069a25d8 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/DetermineSourceUtil.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/DetermineSourceUtil.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.internal;
+package io.github.belgif.rest.problem.spring.server.internal;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/InvalidRequestExceptionUtil.java b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/InvalidRequestExceptionUtil.java
similarity index 97%
rename from belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/InvalidRequestExceptionUtil.java
rename to belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/InvalidRequestExceptionUtil.java
index 0461bcb8..e7142299 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/main/java/io/github/belgif/rest/problem/spring/internal/InvalidRequestExceptionUtil.java
+++ b/belgif-rest-problem-spring/src/main/java/io/github/belgif/rest/problem/spring/server/internal/InvalidRequestExceptionUtil.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.internal;
+package io.github.belgif.rest.problem.spring.server.internal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
diff --git a/belgif-rest-problem-spring/src/main/resources/META-INF/services/io.github.belgif.rest.problem.i18n.LocaleResolver b/belgif-rest-problem-spring/src/main/resources/META-INF/services/io.github.belgif.rest.problem.i18n.LocaleResolver
new file mode 100644
index 00000000..7b3287f1
--- /dev/null
+++ b/belgif-rest-problem-spring/src/main/resources/META-INF/services/io.github.belgif.rest.problem.i18n.LocaleResolver
@@ -0,0 +1 @@
+io.github.belgif.rest.problem.spring.server.i18n.LocaleContextHolderLocaleResolver
\ No newline at end of file
diff --git a/belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/ProblemConfigurationPropertiesTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/ProblemConfigurationPropertiesTest.java
similarity index 100%
rename from belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/ProblemConfigurationPropertiesTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/ProblemConfigurationPropertiesTest.java
diff --git a/belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationPropertiesTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationPropertiesTest.java
similarity index 100%
rename from belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationPropertiesTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/ProblemExtConfigurationPropertiesTest.java
diff --git a/belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/ProblemMediaTypeTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/ProblemMediaTypeTest.java
similarity index 100%
rename from belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/ProblemMediaTypeTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/ProblemMediaTypeTest.java
diff --git a/belgif-rest-problem-spring-boot-4-core/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleJackson3Test.java
similarity index 86%
rename from belgif-rest-problem-spring-boot-4-core/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleJackson3Test.java
index 82430cee..914c6111 100644
--- a/belgif-rest-problem-spring-boot-4-core/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleJackson3Test.java
@@ -11,7 +11,7 @@
import tools.jackson.databind.jsontype.NamedType;
@ExtendWith(MockitoExtension.class)
-class SpringProblemModuleTest {
+class SpringProblemModuleJackson3Test {
@Mock
private SetupContext setupContext;
@@ -20,7 +20,7 @@ class SpringProblemModuleTest {
void module() {
SpringProblemTypeRegistry problemTypeRegistry =
new SpringProblemTypeRegistry(new ProblemConfigurationProperties());
- SpringProblemModule module = new SpringProblemModule(problemTypeRegistry);
+ SpringProblemModuleJackson3 module = new SpringProblemModuleJackson3(problemTypeRegistry);
module.setupModule(setupContext);
verify(setupContext).registerSubtypes(problemTypeRegistry.getProblemTypes().entrySet().stream()
.map(entry -> new NamedType(entry.getValue(), entry.getKey()))
diff --git a/belgif-rest-problem-spring-boot-3-core/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleTest.java
similarity index 100%
rename from belgif-rest-problem-spring-boot-3-core/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemModuleTest.java
diff --git a/belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistryTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistryTest.java
similarity index 84%
rename from belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistryTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistryTest.java
index 1418a167..c2fddc18 100644
--- a/belgif-rest-problem-spring-boot-common/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistryTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/SpringProblemTypeRegistryTest.java
@@ -7,22 +7,29 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
+import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import io.github.belgif.rest.problem.BadRequestProblem;
import io.github.belgif.rest.problem.api.ClientProblem;
import io.github.belgif.rest.problem.api.ProblemType;
import io.github.belgif.rest.problem.registry.ProblemTypeRegistry;
@ExtendWith(SpringExtension.class)
-@ContextConfiguration(classes = { ProblemAutoConfiguration.class, JacksonAutoConfiguration.class })
+@ContextConfiguration(classes = { ProblemJackson2Configuration.class })
class SpringProblemTypeRegistryTest {
@Autowired
private ProblemTypeRegistry problemTypeRegistry;
+ @Bean
+ public ObjectMapper objectMapper() {
+ return new ObjectMapper();
+ }
+
@Test
void getProblemTypes() {
assertThat(problemTypeRegistry.getProblemTypes()).isNotEmpty();
diff --git a/belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemResponseErrorHandlerTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/client/AbstractProblemResponseErrorHandlerTest.java
similarity index 95%
rename from belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemResponseErrorHandlerTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/client/AbstractProblemResponseErrorHandlerTest.java
index 8434df6f..538d2a31 100644
--- a/belgif-rest-problem-spring-boot-common-client/src/test/java/io/github/belgif/rest/problem/spring/AbstractProblemResponseErrorHandlerTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/client/AbstractProblemResponseErrorHandlerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.client;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
@@ -22,7 +22,8 @@
import io.github.belgif.rest.problem.BadRequestProblem;
import io.github.belgif.rest.problem.DefaultProblem;
import io.github.belgif.rest.problem.api.Problem;
-import io.github.belgif.rest.problem.spring.AbstractProblemResponseErrorHandler.ProblemReader;
+import io.github.belgif.rest.problem.spring.ProblemMediaType;
+import io.github.belgif.rest.problem.spring.client.AbstractProblemResponseErrorHandler.ProblemReader;
@ExtendWith(MockitoExtension.class)
class AbstractProblemResponseErrorHandlerTest {
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AbstractInvalidRequestExceptionHandlerTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/AbstractInvalidRequestExceptionHandlerTest.java
similarity index 96%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AbstractInvalidRequestExceptionHandlerTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/AbstractInvalidRequestExceptionHandlerTest.java
index b7a77a60..e2aff911 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AbstractInvalidRequestExceptionHandlerTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/AbstractInvalidRequestExceptionHandlerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import static org.assertj.core.api.Assertions.*;
@@ -30,12 +30,14 @@
class AbstractInvalidRequestExceptionHandlerTest {
- AbstractInvalidRequestExceptionHandler handler = new AbstractInvalidRequestExceptionHandler<>() {
- @Override
- protected String getBodyValue(String name, AtomicReference requestBody, HttpServletRequest request) {
- return "myDummyValue";
- }
- };
+ AbstractInvalidRequestExceptionHandler handler =
+ new AbstractInvalidRequestExceptionHandler<>() {
+ @Override
+ protected String getBodyValue(String name, AtomicReference requestBody,
+ HttpServletRequest request) {
+ return "myDummyValue";
+ }
+ };
@Test
void inBodyTest() {
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AbstractRoutingExceptionsHandlerTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/AbstractRoutingExceptionsHandlerTest.java
similarity index 89%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AbstractRoutingExceptionsHandlerTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/AbstractRoutingExceptionsHandlerTest.java
index e763a3a4..e3f39da2 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AbstractRoutingExceptionsHandlerTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/AbstractRoutingExceptionsHandlerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import static io.github.belgif.rest.problem.api.InputValidationIssues.*;
import static org.assertj.core.api.Assertions.*;
@@ -21,6 +21,7 @@
import org.springframework.web.bind.MissingRequestHeaderException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.client.RestTemplate;
+import org.springframework.web.servlet.resource.NoResourceFoundException;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParseException;
@@ -29,9 +30,11 @@
import io.github.belgif.rest.problem.BadRequestProblem;
import io.github.belgif.rest.problem.InternalServerErrorProblem;
+import io.github.belgif.rest.problem.ResourceNotFoundProblem;
import io.github.belgif.rest.problem.api.InEnum;
import io.github.belgif.rest.problem.api.Problem;
import io.github.belgif.rest.problem.internal.Jackson2Util;
+import io.github.belgif.rest.problem.spring.ProblemMediaType;
class AbstractRoutingExceptionsHandlerTest {
@@ -191,4 +194,24 @@ void handleHttpMediaTypeNotSupported() {
assertThat(response.getStatusCode().value()).isEqualTo(415);
}
+ @Test
+ void handleNoResourceFoundException() {
+ ResponseEntity entity = handler.handleNoResourceFoundException(
+ new NoResourceFoundException(HttpMethod.GET, "/test"));
+ assertThat(entity.getStatusCode().value()).isEqualTo(404);
+ assertThat(entity.getHeaders().getContentType()).isEqualTo(ProblemMediaType.INSTANCE);
+ ResourceNotFoundProblem problem = (ResourceNotFoundProblem) entity.getBody();
+ assertThat(problem.getDetail()).isEqualTo("No resource /test found");
+ }
+
+ @Test
+ void handleNoResourceFoundExceptionAddsLeadingSlash() {
+ ResponseEntity entity = handler.handleNoResourceFoundException(
+ new NoResourceFoundException(HttpMethod.GET, "test"));
+ assertThat(entity.getStatusCode().value()).isEqualTo(404);
+ assertThat(entity.getHeaders().getContentType()).isEqualTo(ProblemMediaType.INSTANCE);
+ ResourceNotFoundProblem problem = (ResourceNotFoundProblem) entity.getBody();
+ assertThat(problem.getDetail()).isEqualTo("No resource /test found");
+ }
+
}
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AnnotationParameterNameProviderTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/AnnotationParameterNameProviderTest.java
similarity index 88%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AnnotationParameterNameProviderTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/AnnotationParameterNameProviderTest.java
index 5781c398..573c52d8 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/AnnotationParameterNameProviderTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/AnnotationParameterNameProviderTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import static org.assertj.core.api.Assertions.*;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/BeanValidationExceptionsHandlerTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/BeanValidationExceptionsHandlerTest.java
similarity index 98%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/BeanValidationExceptionsHandlerTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/BeanValidationExceptionsHandlerTest.java
index 4e818c31..20017d1c 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/BeanValidationExceptionsHandlerTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/BeanValidationExceptionsHandlerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import static org.assertj.core.api.Assertions.*;
@@ -25,6 +25,7 @@
import io.github.belgif.rest.problem.BadRequestProblem;
import io.github.belgif.rest.problem.api.InEnum;
import io.github.belgif.rest.problem.api.Problem;
+import io.github.belgif.rest.problem.spring.ProblemMediaType;
class BeanValidationExceptionsHandlerTest {
diff --git a/belgif-rest-problem-spring-boot-3-server/src/test/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandlerTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson2HandlerTest.java
similarity index 89%
rename from belgif-rest-problem-spring-boot-3-server/src/test/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandlerTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson2HandlerTest.java
index c49ef943..834fc17a 100644
--- a/belgif-rest-problem-spring-boot-3-server/src/test/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandlerTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson2HandlerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import static org.assertj.core.api.Assertions.*;
@@ -15,11 +15,11 @@
import io.github.belgif.rest.problem.api.InEnum;
import io.github.belgif.rest.problem.api.Problem;
-class InvalidRequestExceptionHandlerTest {
+class InvalidRequestExceptionJackson2HandlerTest {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
- InvalidRequestExceptionHandler handler = new InvalidRequestExceptionHandler(OBJECT_MAPPER);
+ InvalidRequestExceptionJackson2Handler handler = new InvalidRequestExceptionJackson2Handler(OBJECT_MAPPER);
@Test
void inBodyTest() {
diff --git a/belgif-rest-problem-spring-boot-4-server/src/test/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandlerTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson3HandlerTest.java
similarity index 89%
rename from belgif-rest-problem-spring-boot-4-server/src/test/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandlerTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson3HandlerTest.java
index 103831e2..5c5bb642 100644
--- a/belgif-rest-problem-spring-boot-4-server/src/test/java/io/github/belgif/rest/problem/spring/InvalidRequestExceptionHandlerTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/InvalidRequestExceptionJackson3HandlerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import static org.assertj.core.api.Assertions.*;
@@ -15,11 +15,11 @@
import io.github.belgif.rest.problem.api.Problem;
import tools.jackson.databind.ObjectMapper;
-class InvalidRequestExceptionHandlerTest {
+class InvalidRequestExceptionJackson3HandlerTest {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
- InvalidRequestExceptionHandler handler = new InvalidRequestExceptionHandler(OBJECT_MAPPER);
+ InvalidRequestExceptionJackson3Handler handler = new InvalidRequestExceptionJackson3Handler(OBJECT_MAPPER);
@Test
void inBodyTest() {
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/ProblemExceptionHandlerTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/ProblemExceptionHandlerTest.java
similarity index 96%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/ProblemExceptionHandlerTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/ProblemExceptionHandlerTest.java
index 02019f67..f9207acc 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/ProblemExceptionHandlerTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/ProblemExceptionHandlerTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring;
+package io.github.belgif.rest.problem.spring.server;
import static org.assertj.core.api.Assertions.*;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/i18n/LocaleContextHolderLocaleResolverTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/i18n/LocaleContextHolderLocaleResolverTest.java
similarity index 91%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/i18n/LocaleContextHolderLocaleResolverTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/i18n/LocaleContextHolderLocaleResolverTest.java
index 2d5c48ea..6263636f 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/i18n/LocaleContextHolderLocaleResolverTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/i18n/LocaleContextHolderLocaleResolverTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.i18n;
+package io.github.belgif.rest.problem.spring.server.i18n;
import static org.assertj.core.api.Assertions.*;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/BeanValidationExceptionUtilTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/BeanValidationExceptionUtilTest.java
similarity index 99%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/BeanValidationExceptionUtilTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/BeanValidationExceptionUtilTest.java
index 8bdf5eeb..7ec42ec8 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/BeanValidationExceptionUtilTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/BeanValidationExceptionUtilTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.internal;
+package io.github.belgif.rest.problem.spring.server.internal;
import static org.assertj.core.api.Assertions.*;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/CachedAnnotationParameterNameSupportTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/CachedAnnotationParameterNameSupportTest.java
similarity index 97%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/CachedAnnotationParameterNameSupportTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/CachedAnnotationParameterNameSupportTest.java
index 900a2d17..cabb7625 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/CachedAnnotationParameterNameSupportTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/CachedAnnotationParameterNameSupportTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.internal;
+package io.github.belgif.rest.problem.spring.server.internal;
import static org.assertj.core.api.Assertions.*;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/DetermineSourceUtilTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/DetermineSourceUtilTest.java
similarity index 98%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/DetermineSourceUtilTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/DetermineSourceUtilTest.java
index 47e8a8d6..c0f5acd8 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/DetermineSourceUtilTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/DetermineSourceUtilTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.internal;
+package io.github.belgif.rest.problem.spring.server.internal;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
diff --git a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/InvalidRequestExceptionUtilTest.java b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/InvalidRequestExceptionUtilTest.java
similarity index 99%
rename from belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/InvalidRequestExceptionUtilTest.java
rename to belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/InvalidRequestExceptionUtilTest.java
index 10f6197f..31c49cce 100644
--- a/belgif-rest-problem-spring-boot-common-server/src/test/java/io/github/belgif/rest/problem/spring/internal/InvalidRequestExceptionUtilTest.java
+++ b/belgif-rest-problem-spring/src/test/java/io/github/belgif/rest/problem/spring/server/internal/InvalidRequestExceptionUtilTest.java
@@ -1,4 +1,4 @@
-package io.github.belgif.rest.problem.spring.internal;
+package io.github.belgif.rest.problem.spring.server.internal;
import static org.assertj.core.api.Assertions.*;
diff --git a/belgif-rest-problem-spring-boot-4-server/src/test/resources/logback-test.xml b/belgif-rest-problem-spring/src/test/resources/logback-test.xml
similarity index 100%
rename from belgif-rest-problem-spring-boot-4-server/src/test/resources/logback-test.xml
rename to belgif-rest-problem-spring/src/test/resources/logback-test.xml
diff --git a/jacoco-aggregator/pom.xml b/jacoco-aggregator/pom.xml
index 82b30420..8b5145e3 100644
--- a/jacoco-aggregator/pom.xml
+++ b/jacoco-aggregator/pom.xml
@@ -61,17 +61,7 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common-client
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-common-server
+ belgif-rest-problem-spring
${project.version}
@@ -81,37 +71,27 @@
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-core
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-client
+ belgif-rest-problem-spring-boot-3-client-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-3-server
+ belgif-rest-problem-spring-boot-3-server-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4
+ belgif-rest-problem-spring-boot-4-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-core
+ belgif-rest-problem-spring-boot-4-client-starter
${project.version}
io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-client
- ${project.version}
-
-
- io.github.belgif.rest.problem
- belgif-rest-problem-spring-boot-4-server
+ belgif-rest-problem-spring-boot-4-server-starter
${project.version}
@@ -171,6 +151,16 @@
belgif-rest-problem-spring-boot-3-it
${project.version}
+
+ io.github.belgif.rest.problem
+ belgif-rest-problem-spring-boot-4-it
+ ${project.version}
+
+
+ io.github.belgif.rest.problem
+ belgif-rest-problem-spring-it
+ ${project.version}
+
io.github.belgif.rest.problem
belgif-rest-problem-quarkus-it
diff --git a/pom.xml b/pom.xml
index 682e93e6..b2646c99 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,8 @@
UTF-8
2.12.7
- 3.1.0
+
+ 3.0.4
3.5.11
4.0.3
3.32.2
@@ -233,11 +234,10 @@
belgif-rest-problem-it,
jacoco-aggregator,
-
+
belgif-rest-problem-spring-boot-3,
- belgif-rest-problem-spring-boot-3-core,
- belgif-rest-problem-spring-boot-3-client,
- belgif-rest-problem-spring-boot-3-server
+ belgif-rest-problem-spring-boot-3-client-starter,
+ belgif-rest-problem-spring-boot-3-server-starter
all,-missing
true
@@ -379,17 +379,13 @@
belgif-rest-problem-jakarta-ee-core
belgif-rest-problem-jakarta-ee-client
belgif-rest-problem-jakarta-ee-server
- belgif-rest-problem-spring-boot-common
- belgif-rest-problem-spring-boot-common-client
- belgif-rest-problem-spring-boot-common-server
+ belgif-rest-problem-spring
belgif-rest-problem-spring-boot-3
- belgif-rest-problem-spring-boot-3-core
- belgif-rest-problem-spring-boot-3-client
- belgif-rest-problem-spring-boot-3-server
- belgif-rest-problem-spring-boot-4
- belgif-rest-problem-spring-boot-4-core
- belgif-rest-problem-spring-boot-4-client
- belgif-rest-problem-spring-boot-4-server
+ belgif-rest-problem-spring-boot-3-client-starter
+ belgif-rest-problem-spring-boot-3-server-starter
+ belgif-rest-problem-spring-boot-4-starter
+ belgif-rest-problem-spring-boot-4-client-starter
+ belgif-rest-problem-spring-boot-4-server-starter
belgif-rest-problem-quarkus
belgif-rest-problem-quarkus-core
belgif-rest-problem-quarkus-core-deployment
@@ -471,6 +467,7 @@
belgif-rest-problem-jakarta-ee-it
belgif-rest-problem-java-ee-it
belgif-rest-problem-quarkus-it
+ belgif-rest-problem-spring-it
belgif-rest-problem-spring-boot-3-it
belgif-rest-problem-spring-boot-4-it
@@ -503,17 +500,13 @@
belgif-rest-problem-jakarta-ee-core
belgif-rest-problem-jakarta-ee-client
belgif-rest-problem-jakarta-ee-server
- belgif-rest-problem-spring-boot-common
- belgif-rest-problem-spring-boot-common-client
- belgif-rest-problem-spring-boot-common-server
+ belgif-rest-problem-spring
belgif-rest-problem-spring-boot-3
- belgif-rest-problem-spring-boot-3-core
- belgif-rest-problem-spring-boot-3-client
- belgif-rest-problem-spring-boot-3-server
- belgif-rest-problem-spring-boot-4
- belgif-rest-problem-spring-boot-4-core
- belgif-rest-problem-spring-boot-4-client
- belgif-rest-problem-spring-boot-4-server
+ belgif-rest-problem-spring-boot-3-client-starter
+ belgif-rest-problem-spring-boot-3-server-starter
+ belgif-rest-problem-spring-boot-4-starter
+ belgif-rest-problem-spring-boot-4-client-starter
+ belgif-rest-problem-spring-boot-4-server-starter
belgif-rest-problem-quarkus
belgif-rest-problem-quarkus-core
belgif-rest-problem-quarkus-core-deployment
@@ -562,17 +555,13 @@
spring-only
belgif-rest-problem
- belgif-rest-problem-spring-boot-common
- belgif-rest-problem-spring-boot-common-client
- belgif-rest-problem-spring-boot-common-server
+ belgif-rest-problem-spring
belgif-rest-problem-spring-boot-3
- belgif-rest-problem-spring-boot-3-core
- belgif-rest-problem-spring-boot-3-client
- belgif-rest-problem-spring-boot-3-server
- belgif-rest-problem-spring-boot-4
- belgif-rest-problem-spring-boot-4-core
- belgif-rest-problem-spring-boot-4-client
- belgif-rest-problem-spring-boot-4-server
+ belgif-rest-problem-spring-boot-3-client-starter
+ belgif-rest-problem-spring-boot-3-server-starter
+ belgif-rest-problem-spring-boot-4-starter
+ belgif-rest-problem-spring-boot-4-client-starter
+ belgif-rest-problem-spring-boot-4-server-starter
belgif-rest-problem-it/belgif-rest-problem-apt
belgif-rest-problem-it/belgif-rest-problem-codegen-it
@@ -581,6 +570,7 @@
belgif-rest-problem-it/belgif-rest-problem-jackson2-latest-it
belgif-rest-problem-it/belgif-rest-problem-jackson2-minimal-it
belgif-rest-problem-it/belgif-rest-problem-jackson3-it
+ belgif-rest-problem-it/belgif-rest-problem-spring-it
belgif-rest-problem-it/belgif-rest-problem-spring-boot-3-it
belgif-rest-problem-it/belgif-rest-problem-spring-boot-4-it
belgif-rest-problem-bom
diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc
index 56ecbfcd..d2b94312 100644
--- a/src/main/asciidoc/index.adoc
+++ b/src/main/asciidoc/index.adoc
@@ -237,7 +237,7 @@ Otherwise, you will see parameter names like `arg0`.
InvalidRequestExceptions thrown by the https://bitbucket.org/atlassian/swagger-request-validator[Atlassian swagger-request-validator] are automatically converted to a proper RFC 9457 `application/problem+json` response.
-For Spring Boot 3, use https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-spring-webmvc[swagger-request-validator-spring-webmvc].
+When using Spring, use https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-spring-webmvc[swagger-request-validator-spring-webmvc].
==== RestTemplate
@@ -257,6 +257,11 @@ Problem support is automatically enabled when constructing your RestClient throu
When manually constructing a RestClient instance, you'll need to apply the link:apidocs/io/github/belgif/rest/problem/spring/ProblemRestClientCustomizer.html[ProblemRestClientCustomizer] yourself.
+==== Without Spring Boot
+
+If your application uses Spring without Spring Boot, use the link:apidocs/io/github/belgif/rest/problem/spring/ProblemRestClientCustomizer.html[`@EnableProblemModule`] annotation to activate problem support. Your application needs to provide a configured `ObjectMapper` (Jackson 2) or `JsonMapper` (Jackson3) bean.
+REST clients have to be configured during their creation using beans provided by the problem module. See the `WebConfig` class in the integration test `belgif-rest-problem-spring-it` for an example.
+
[[getting-started-jakarta-ee]]
=== Jakarta EE
@@ -880,10 +885,10 @@ public void setClient(Client client) {
* *Jakarta EE 9+*: the main belgif-rest-problem-java-ee artifact targets Java EE (javax package namespace).
A secondary artifact that targets Jakarta EE 9+ (jakarta package namespace) is available with `jakarta`.
-[[belgif-rest-problem-spring-boot-3]]
-=== belgif-rest-problem-spring-boot-3
+[[belgif-rest-problem-spring]]
+=== belgif-rest-problem-spring
-This module provides auto-configuration for components that handle Spring Boot 3 integration with the belgif-rest-problem library:
+This module provides base components for Spring integration with the belgif-rest-problem library, without Spring Boot dependencies:
* *SpringProblemTypeRegistry:* ProblemTypeRegistry implementation that uses classpath scanning to detect @ProblemType annotations.
By default, only package `io.github.belgif.rest.problem` is scanned for @ProblemType annotations.
@@ -898,20 +903,27 @@ io.github.belgif.rest.problem.scan-additional-problem-packages=com.acme.custom
* *ProblemExceptionHandler:* an exception handler for RestControllers that handles the response serialization for Problem exceptions, and converts all other uncaught exceptions to an InternalServerErrorProblem.
* *BeanValidationExceptionsHandler:* an exception handler for RestControllers that converts bean validation related exceptions to HTTP 400 BadRequestProblem.
* *InvalidRequestExceptionHandler:* an exception handler for the link:https://bitbucket.org/atlassian/swagger-request-validator/src/master/[Atlassian swagger-request-validator] that converts InvalidRequestException to the correct Problem type.
-* *RoutingExceptionsHandler:* an exception handler for RestControllers that converts routing related validation exceptions to HTTP 400 BadRequestProblem.
+* *RoutingExceptionsHandler:* an exception handler for RestControllers that converts request handling exceptions to HTTP 4XX problems.
+* *ProblemResponseErrorHandler:* a RestTemplate and RestClient error handler that converts problem responses to Problem exceptions.
+* *AnnotationParameterNameProvider:* a bean validation ParameterNameProvider that retrieves parameter names from Spring MVC annotations
+
+In general, these components make it possible to use standard java exception handling (throw and try-catch) for dealing with problems in Spring Boot REST APIs.
+
+[[belgif-rest-problem-spring-boot-3]]
+=== belgif-rest-problem-spring-boot-3
+
+This module provides auto-configuration for the `belgif-rest-problem-spring` components that handle Spring Boot 3 integration with the belgif-rest-problem library:
+
* *ProblemWebClientCustomizer:* a WebClientCustomizer that registers a filter that converts problem responses to Problem exceptions.
This handles integration with the https://docs.spring.io/spring-framework/reference/web/webflux-webclient.html[Reactive WebClient].
-* *ProblemResponseErrorHandler:* a RestTemplate and RestClient error handler that converts problem responses to Problem exceptions.
* *ProblemRestTemplateCustomizer:* a RestTemplateCustomizer that registers the ProblemResponseErrorHandler.
-* *NoResourceFoundExceptionHandler:* an exception handler for RestControllers that converts NoResourceFoundException to HTTP 404 ResourceNotFoundProblem.
* *ProblemRestClientCustomizer:* a RestClientCustomizer that registers the ProblemResponseErrorHandler.
-* *AnnotationParameterNameProvider:* a bean validation ParameterNameProvider that retrieves parameter names from Spring MVC annotations
* *ProblemValidationConfigurationCustomizer:* a ValidationConfigurationCustomizer that registers the AnnotationParameterNameProvider
In general, these components make it possible to use standard java exception handling (throw and try-catch) for dealing with problems in Spring Boot REST APIs.
-[[belgif-rest-problem-spring-boot-4]]
-=== belgif-rest-problem-spring-boot-4
+[[belgif-rest-problem-spring-boot-4-starter]]
+=== belgif-rest-problem-spring-boot-4-starter
This module provides auto-configuration for components that handle Spring Boot 4 integration with the belgif-rest-problem library.
In general, this is very similar to the Spring Boot 3 module.
diff --git a/src/main/asciidoc/release-notes.adoc b/src/main/asciidoc/release-notes.adoc
index c2ef2ca0..c1afdc00 100644
--- a/src/main/asciidoc/release-notes.adoc
+++ b/src/main/asciidoc/release-notes.adoc
@@ -20,21 +20,41 @@
*belgif-rest-problem-spring-boot-3:*
+[WARNING]
+====
+*Breaking change:* Some classes were moved to `client`- and `server`-specific packages
+====
+
Provide separate modules in case you specifically only want to use problems either client-side or server-side.
-* belgif-rest-problem-spring-boot-3-client
-* belgif-rest-problem-spring-boot-3-server
+* belgif-rest-problem-spring-boot-3-client-starter
+* belgif-rest-problem-spring-boot-3-server-starter
Note that you can keep using `belgif-rest-problem-spring-boot-3` as before if you want both client-side and server-side integration.
-*belgif-rest-problem-spring-boot-4:*
+*belgif-rest-problem-spring-boot-4-starter:*
+
+[WARNING]
+====
+*Breaking changes:*
+
+* Users of `belgif-rest-problem-spring-boot-4` from version should now depend on the `belgif-rest-problem-spring-boot-4-starter` module.
+* Some classes were moved to `client`- and `server`-specific packages
+====
Provide separate modules in case you specifically only want to use problems either client-side or server-side.
-* belgif-rest-problem-spring-boot-4-client
-* belgif-rest-problem-spring-boot-4-server
+* belgif-rest-problem-spring-boot-4-client-starter
+* belgif-rest-problem-spring-boot-4-server-starter
+
+Note that you can use `belgif-rest-problem-spring-boot-4-starter` when you want both client-side and server-side integration.
+
+*belgif-rest-problem-spring:*
+
+Depend on this module to integrate with Spring without depending on Spring Boot.
+When using one of the spring boot modules, it is added as transitive dependency.
-Note that you can keep using `belgif-rest-problem-spring-boot-4` as before when you want both client-side and server-side integration.
+It provides support for both Jackson 2 and 3.
*belgif-rest-problem-java-ee:*