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
Copy file name to clipboardExpand all lines: docs/asciidoc/problem-details.adoc
+35-44Lines changed: 35 additions & 44 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,52 +10,44 @@ Thankfully, there’s a standard called https://www.rfc-editor.org/rfc/rfc7807[I
10
10
By adopting `RFC 7807`, API designers don’t have to spend time creating a custom solution, and users benefit by recognizing a familiar format across different APIs.
11
11
If it suits the API’s needs, using this standard benefits both designers and users alike.
12
12
13
-
`Jooby` provides built-in support for `Problem Details`. There are two main entities to work with:
13
+
`Jooby` provides built-in support for `Problem Details`.
14
14
15
-
1. `HttpProblem` - representation of the `RFC 7807` model and the way to instantiate the problem.
15
+
=== Set up ProblemDetails
16
16
17
-
2. `ProblemDetailsHandler` - global error handler that catches all exceptions, transforms them into `Problem Details` compliant format and renders the response based on the `Accept` header value.
18
-
It also sets the appropriate content-type in response (e.g. application/problem+json, application/problem+xml)
17
+
To enable the `ProblemDetails`, simply add the following line to your configuration:
19
18
20
-
=== Set up handler
19
+
.application.conf
20
+
[source, properties]
21
+
----
22
+
problem.details.enabled = true
23
+
----
21
24
22
-
The bare minimal requirement is to set up an error handler:
25
+
This is the bare minimal configuration you need.
26
+
It enables a global error handler that catches all exceptions, transforms them into Problem Details compliant format and renders the response based on the Accept header value. It also sets the appropriate content-type in response (e.g. application/problem+json, application/problem+xml)
<1> By default, only server errors (5xx) will be logged. You can optionally enable the logging of client errors (4xx). If `DEBUG` logging level is enabled, the log will contain a stacktrace as well.
43
+
<2> You can optionally mute some status codes completely.
44
+
<3> You can optionally mute some exceptions logging completely.
51
45
52
-
<1> Enable `Problem Details` handler.
53
-
Keep in mind, order matters (WYSIWYG), so if you have some specific exception handlers, they should be placed above this line.
54
-
<2> By default, only server errors (5xx) will be logged. You can optionally enable the logging of client errors (4xx). If `DEBUG` logging level is enabled, the log will contain a stacktrace as well.
55
-
<3> You can optionally mute some status codes or exceptions logging completely.
56
46
57
47
=== Creating problems
58
48
49
+
`HttpProblem` class represents the `RFC 7807` model. It is the main entity you need to work with to produce the problem.
50
+
59
51
==== Static helpers
60
52
61
53
There are several handy static methods to produce a simple `HttpProblem`:
@@ -70,6 +62,8 @@ Don't overuse it, the problem should have meaningful `title` and `detail` when p
70
62
.Java
71
63
[source,java,role="primary"]
72
64
----
65
+
import io.jooby.problem.HttpProblem;
66
+
73
67
get("/users/{userId}", ctx -> {
74
68
var userId = ctx.path("userId").value();
75
69
User user = userRepository.findUser(userId);
@@ -87,6 +81,8 @@ get("/users/{userId}", ctx -> {
87
81
.Kotlin
88
82
[source,kt,role="secondary"]
89
83
----
84
+
import io.jooby.problem.HttpProblem
85
+
90
86
get("/users/{userId}") { ctx ->
91
87
val userId = ctx.path("userId").value()
92
88
val user = userRepository.findUser(userId)
@@ -117,7 +113,7 @@ Resulting response:
117
113
118
114
==== Builder
119
115
120
-
Use builder to create rich problem instance with all properties:
116
+
Use builder to create a rich problem instance with all properties:
121
117
122
118
[source,java]
123
119
----
@@ -190,8 +186,8 @@ It is basically another extension `errors` on a root level. Adding errors is str
190
186
----
191
187
throw HttpProblem.builder()
192
188
...
193
-
.error(new HttpProblem.Error("First name cannot be blank", "#/firstName"))
194
-
.error(new HttpProblem.Error("Last name is required", "#/lastName"))
189
+
.error(new HttpProblem.Error("First name cannot be blank", "/firstName"))
190
+
.error(new HttpProblem.Error("Last name is required", "/lastName"))
195
191
.build();
196
192
----
197
193
@@ -203,11 +199,11 @@ In response:
203
199
"errors": [
204
200
{
205
201
"detail": "First name cannot be blank",
206
-
"pointer": "#/firstName"
202
+
"pointer": "/firstName"
207
203
},
208
204
{
209
205
"detail": "Last name is required",
210
-
"pointer": "#/lastName"
206
+
"pointer": "/lastName"
211
207
}
212
208
]
213
209
}
@@ -261,8 +257,7 @@ public class OutOfStockProblem extends HttpProblem {
261
257
262
258
=== Custom Exception Handlers
263
259
264
-
All the features described above should give you ability to rely solely on `ProblemDetailsHandler`.
265
-
But, in case you still need custom exception handler for some reason, you still can do it:
260
+
All the features described above should give you ability to rely solely on built-in global error handler. But, in case you still need custom exception handler for some reason, you still can do it:
266
261
267
262
[source,java]
268
263
----
@@ -275,20 +270,16 @@ But, in case you still need custom exception handler for some reason, you still
<2> Propagate the problem to `ProblemDetailsHandler`. It will handle the rest.
286
-
<3> `ProblemDetailsHandler` should always go below your custom exception handlers
287
278
288
279
[IMPORTANT]
289
280
====
290
281
Do not attempt to render `HttpProblem` manually, it is strongly discouraged.
291
282
`HttpProblem` is derived from the `RuntimeException` to enable ease of `HttpProblem` throwing.
292
283
Thus, thrown `HttpProblem` will also contain a stacktrace, if you render `HttpProblem` as is -
293
-
it will be rendered together with stacktrace. It is strongly advised not to expose the stacktrace to the client. Propagate the problem to `ProblemDetailsHandler` and let him take care of the rest.
284
+
it will be rendered together with stacktrace. It is strongly advised not to expose the stacktrace to the client system. Propagate the problem to global error handler and let him take care of the rest.
0 commit comments