Skip to content

Commit 62004e5

Browse files
committed
Update README.md
1 parent cc70701 commit 62004e5

File tree

2 files changed

+66
-78
lines changed

2 files changed

+66
-78
lines changed

README.md

Lines changed: 17 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -4,74 +4,39 @@
44
[![Sonatype](https://img.shields.io/maven-central/v/io.github.malczuuu.problem4j/problem4j-spring-bom)](https://central.sonatype.com/artifact/io.github.malczuuu.problem4j/problem4j-spring-bom)
55
[![License](https://img.shields.io/github/license/malczuuu/problem4j-spring)](https://github.com/malczuuu/problem4j-spring/blob/main/LICENSE)
66

7-
Spring integration module for [`problem4j-core`][problem4j-core]. library that integrates the RFC Problem Details model
8-
with exception handling in Spring Boot.
7+
Designing clear and consistent error responses in a REST API is often harder than it looks. Without a shared standard,
8+
each application ends up inventing its own ad-hoc format, which quickly leads to inconsistency and confusion.
9+
[RFC 7807 - Problem Details for HTTP APIs][rfc7807] solves this by defining a simple, extensible JSON structure for
10+
error messages.
11+
12+
**Problem4J** brings this specification into the Spring ecosystem, offering a practical way to model, throw, and handle
13+
API errors using `Problem` objects. It helps you enforce a consistent error contract across your services, while staying
14+
flexible enough for custom exceptions and business-specific details.
915

1016
## Table of Contents
1117

1218
- [Features](#features)
13-
- [Example](#example)
1419
- [Usage](#usage)
1520
- [Configuration](#configuration)
1621
- [Problem4J Links](#problem4j-links)
1722

1823
## Features
1924

25+
This module provides Spring integration for [`problem4j-core`][problem4j-core]. library that integrates the RFC Problem
26+
Details model with exception handling in Spring Boot.
27+
2028
- ✅ Automatic mapping of exceptions to responses with `Problem` objects compliant with [RFC 7807][rfc7807].
2129
- ✅ Mapping of exceptions extending `ProblemException` to responses with `Problem` objects.
30+
- ✅ Mapping of exceptions annotated with `@ProblemMapping` to responses with `Problem` objects.
2231
- ✅ Fallback mapping of `Exception` to `Problem` objects representing `500 Internal Server Error`.
2332
- ✅ Simple configuration thanks to Spring Boot autoconfiguration.
2433

25-
## Example
34+
## Usage
2635

2736
The library provides two ways to convert exceptions into RFC 7807-compliant `Problem` responses. You can either extend
2837
`ProblemException` or use `@ProblemMapping` annotation on your own exception if modifying inheritance tree is not an
2938
option for. For more details and examples visit [`problem4j-spring-web/README.md`][problem4j-spring-web-readme].
3039

31-
If that's not possible for your application, add a custom `@RestControllerAdvice` that returns a `Problem` object, but
32-
take note at `@Order` as explained in [Usage](#usage) chapter.
33-
34-
```java
35-
import io.github.malczuuu.problem4j.core.Problem;
36-
import org.springframework.core.Ordered;
37-
import org.springframework.core.annotation.Order;
38-
import org.springframework.http.HttpHeaders;
39-
import org.springframework.http.HttpStatus;
40-
import org.springframework.http.MediaType;
41-
import org.springframework.http.ResponseEntity;
42-
import org.springframework.stereotype.Component;
43-
import org.springframework.web.bind.annotation.ExceptionHandler;
44-
import org.springframework.web.bind.annotation.RestControllerAdvice;
45-
import org.springframework.web.context.request.WebRequest;
46-
47-
@Order(Ordered.LOWEST_PRECEDENCE - 20)
48-
@Component
49-
@RestControllerAdvice
50-
public class ExampleExceptionAdvice {
51-
52-
@ExceptionHandler(ExampleException.class)
53-
public ResponseEntity<Problem> method(ExampleException ex, WebRequest request) {
54-
Problem problem =
55-
Problem.builder()
56-
.type("http://example.com/errors/example-error")
57-
.title("Example Title")
58-
.status(400)
59-
.detail(ex.getMessage())
60-
.instance("https://example.com/instances/example-instance")
61-
.build();
62-
63-
HttpHeaders headers = new HttpHeaders();
64-
headers.setContentType(MediaType.APPLICATION_PROBLEM_JSON);
65-
66-
HttpStatus status = HttpStatus.valueOf(problem.getStatus());
67-
68-
return new ResponseEntity<>(problem, headers, status);
69-
}
70-
}
71-
```
72-
73-
## Usage
74-
7540
Add library as dependency to Maven or Gradle. See the actual versions on [Maven Central][maven-central]. Add it along
7641
with repository in your dependency manager. **Java 17** or higher is required to use this library.
7742

@@ -81,55 +46,29 @@ compatible down to `3.0.0`. Integration with Spring Boot 4 (once its released) w
8146

8247
1. Maven:
8348
```xml
84-
<dependencyManagement>
85-
<dependencies>
86-
<dependency>
87-
<groupId>io.github.malczuuu.problem4j</groupId>
88-
<artifactId>problem4j-spring-bom</artifactId>
89-
<version>${problem4j-spring-bom.version}</version>
90-
<type>pom</type>
91-
<scope>import</scope>
92-
</dependency>
93-
</dependencies>
94-
</dependencyManagement>
9549
<dependencies>
9650
<!-- pick the one for your project -->
9751
<dependency>
9852
<groupId>io.github.malczuuu.problem4j</groupId>
9953
<artifactId>problem4j-spring-webflux</artifactId>
54+
<version>1.0.0-alpha1</version>
10055
</dependency>
10156
<dependency>
10257
<groupId>io.github.malczuuu.problem4j</groupId>
10358
<artifactId>problem4j-spring-webmvc</artifactId>
59+
<version>1.0.0-alpha1</version>
10460
</dependency>
10561
</dependencies>
10662
```
10763
2. Gradle (Groovy or Kotlin DSL):
10864
```groovy
10965
dependencies {
110-
implementation(platform("io.github.malczuuu.problem4j:problem4j-spring-bom:${problem4j-spring-bom.version}"))
111-
11266
// pick the one for your project
113-
implementation("io.github.malczuuu.problem4j:problem4j-spring-webflux")
114-
implementation("io.github.malczuuu.problem4j:problem4j-spring-webmvc")
67+
implementation("io.github.malczuuu.problem4j:problem4j-spring-webflux:1.0.0-alpha1")
68+
implementation("io.github.malczuuu.problem4j:problem4j-spring-webmvc:1.0.0-alpha1")
11569
}
11670
```
11771

118-
Details on library usability can be found in [`problem4j-spring-web/README.md`][problem4j-spring-web-readme].
119-
120-
While creating your own `@RestControllerAdvice`, make sure to position it with right `@Order`. In order for your custom
121-
implementation to work seamlessly, make sure to position it on at least **`Ordered.LOWEST_PRECEDENCE - 1`** (the lower
122-
the value, the higher the priority), as **`ExceptionAdvice`** covers the most generic **`Exception`** class. You may
123-
browse existing advices for inspiration to implement a matching behaviour.
124-
125-
| <center>covered exceptions</center> | <center>`@Order(...)`</center> |
126-
|-------------------------------------|----------------------------------|
127-
| Spring's internal exceptions | `Ordered.LOWEST_PRECEDENCE - 10` |
128-
| `ConstraintViolationException` | `Ordered.LOWEST_PRECEDENCE - 10` |
129-
| `DecodingException` | `Ordered.LOWEST_PRECEDENCE - 10` |
130-
| `ProblemException` | `Ordered.LOWEST_PRECEDENCE - 10` |
131-
| `Exception` | `Ordered.LOWEST_PRECEDENCE` |
132-
13372
## Configuration
13473

13574
Library can be configured with following properties.

problem4j-spring-web/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
2. [Returning response bodies from custom exceptions](#returning-response-bodies-from-custom-exceptions)
55
1. [Extending `ProblemException`](#extending-problemexception)
66
2. [Annotating `@ProblemMapping`](#annotating-problemmapping)
7+
3. [Custom `@RestControllerAdvice`](#custom-restcontrolleradvice)
78
3. [Validation](#validation)
89
4. [Occurrences of `TypeMismatchException`](#occurrences-of-typemismatchexception)
910
5. [Occurrences of `ErrorResponseException`](#occurrences-of-errorresponseexception)
@@ -113,6 +114,54 @@ public class ExampleException extends RuntimeException {
113114
**Note** that the main reason behind this project is to make `ProblemException` a base class for all custom exception in
114115
your application code.
115116

117+
### Custom `RestControllerAdvice`
118+
119+
For exceptions, you can't modify, add a custom `@RestControllerAdvice` that returns a `Problem` object, but take note at
120+
`@Order`.
121+
122+
While creating your own `@RestControllerAdvice`, make sure to position it with right `@Order`. In order for your custom
123+
implementation to work seamlessly, make sure to position it on at least **`Ordered.LOWEST_PRECEDENCE - 11`** (the lower
124+
the value, the higher the priority). All `@RestControllerAdvice` provided by `problem4j-spring` library use ordering
125+
from `Ordered.LOWEST_PRECEDENCE` to `Ordered.LOWEST_PRECEDENCE - 10`. By setting at lest `-11`, you make sure that your
126+
exception will not fall into predefined advices.
127+
128+
But let's be honest, you'll probably use `Ordered.HIGHEST_PRECEDENCE` :D.
129+
130+
| <center>covered exceptions</center> | <center>`@Order(...)`</center> |
131+
|-------------------------------------|----------------------------------|
132+
| Spring's internal exceptions | `Ordered.LOWEST_PRECEDENCE - 10` |
133+
| `ConstraintViolationException` | `Ordered.LOWEST_PRECEDENCE - 10` |
134+
| `DecodingException` | `Ordered.LOWEST_PRECEDENCE - 10` |
135+
| `ProblemException` | `Ordered.LOWEST_PRECEDENCE - 10` |
136+
| `Exception` | `Ordered.LOWEST_PRECEDENCE` |
137+
138+
```java
139+
@Order(Ordered.LOWEST_PRECEDENCE - 20)
140+
@Component
141+
@RestControllerAdvice
142+
public class ExampleExceptionAdvice {
143+
144+
@ExceptionHandler(ExampleException.class)
145+
public ResponseEntity<Problem> method(ExampleException ex, WebRequest request) {
146+
Problem problem =
147+
Problem.builder()
148+
.type("http://example.com/errors/example-error")
149+
.title("Example Title")
150+
.status(400)
151+
.detail(ex.getMessage())
152+
.instance("https://example.com/instances/example-instance")
153+
.build();
154+
155+
HttpHeaders headers = new HttpHeaders();
156+
headers.setContentType(MediaType.APPLICATION_PROBLEM_JSON);
157+
158+
HttpStatus status = HttpStatus.valueOf(problem.getStatus());
159+
160+
return new ResponseEntity<>(problem, headers, status);
161+
}
162+
}
163+
```
164+
116165
## Validation
117166

118167
Library overrides default responses for `jakarta.validation` exceptions for both `@RequestBody` and any other

0 commit comments

Comments
 (0)