You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -126,18 +130,82 @@ public static ExceptionHandler defaultExceptionHandler(TypeMapper jsonMapper) {
126
130
127
131
Rationale: the exception path runs before a `Request` is necessarily built (e.g. a malformed URI in `RequestPreparationFilter` itself), so the handler signature cannot take `Request` — the simplest pre-`Request` signature is the right one.
128
132
129
-
### 4a. `ProblemDetail` record replaces `ProblemDetailRenderer`
133
+
### 4a. New public `BadRequestException`
134
+
135
+
User handlers need a way to reject a syntactically-valid-but-semantically-wrong request (e.g. "email already taken" → 422 Unprocessable Content, "stale ETag" → 412 Precondition Failed) and have the framework render a problem+json response — without each handler re-implementing the problem-detail wire shape.
-**Optional status, default 400.** The no-status constructor preserves the common "client sent something bad" case at zero ceremony; the overload accepts any 4xx for 409/412/422/429 etc.
177
+
-**4xx range enforced.** Throwing at construction prevents accidentally surfacing a 500 through a "bad request" path. 5xx errors should propagate as ordinary `RuntimeException` and hit the default 500 branch.
178
+
-**Optional pointer/keyword** mirror `ValidationError` so the problem+json document shape is consistent whether the body was rejected by the OpenAPI validator (`ValidationException`) or by handler-level domain rules (`BadRequestException`).
179
+
-**`detail`** uses `super(message)` so standard exception machinery (logging, stack traces) sees the human-readable reason.
180
+
181
+
### 4b. `ProblemDetail` record replaces `ProblemDetailRenderer`
130
182
131
183
New `internal/ProblemDetail` record (or public if we want users to be able to return problem+json from handlers — TBD; start internal):
132
184
133
185
```java
134
186
record ProblemDetail(
135
187
String type, String title, int status, String detail,
// Small map of common 4xx codes to RFC-7231 reason phrases.
206
+
// Unknown 4xx falls back to "Bad Request" — the type field is "about:blank",
207
+
// so per RFC 7807 the title is advisory; the precise meaning rides on status.
208
+
privatestaticString titleFor(int status) { ... }
141
209
}
142
210
```
143
211
@@ -182,11 +250,12 @@ returns no results.
182
250
2. Introduce `ExtraRouteAdapter`; switch `OpenApiServer` extras wiring to it.
183
251
3. Change `Builder.extraRoute` signature; update `HandlerConfig` and tests.
184
252
4. Change `ExceptionHandler` signature; update `ExceptionFilter` to accept a `ResponseRenderer`; rewrite `Handlers.defaultExceptionHandler(TypeMapper)` and wire it from `Builder.build()`.
0 commit comments