Skip to content

Commit 730926f

Browse files
committed
finished readme
1 parent f982582 commit 730926f

File tree

1 file changed

+69
-2
lines changed

1 file changed

+69
-2
lines changed

README.md

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
This library provides several useful utilities helping to implement REST controllers for React Admin-based frontend.
44

55
## Compatibility
6-
The library works as a Spring Boot starter. Current version is compatible with Spring Boot **3.2.x**.
6+
`react-admin-utils` works as a Spring Boot starter. Current version is compatible with Spring Boot **3.2.x**.
77

8+
The library is a part of the [Amplicode](https://amplicode.io/) project, however it does not bring additional dependencies and can be used in any Spring Boot project.
89

9-
## Usage
10+
The implementation heavily depends on Jackson (version used by the Spring Web).
11+
12+
## Adding library to the project
1013
Maven:
1114
```
1215
<dependency>
@@ -24,3 +27,67 @@ dependencies {
2427
```
2528

2629
## ObjectPatcher
30+
#### Patching
31+
The `io.amplicode.rautils.patch.ObjectPatcher` bean helps to implement `PATCH` REST endpoints.
32+
33+
The bean performs patching the passed object under the following set of conditions:
34+
* Real [PATCH](https://datatracker.ietf.org/doc/html/rfc5789) semantics is needed:
35+
* patch contains a subset of object attributes to modify
36+
* attributes not included into the patch are not modified
37+
* attributes can be reset to null
38+
* Data transfer object is an **immutable** class (POJO with all-args constructor, or a Java 17 record).
39+
40+
Usage:
41+
```java
42+
import com.fasterxml.jackson.databind.JsonNode;
43+
44+
@Autowired
45+
private ObjectPatcher objectPatcher;
46+
47+
@PatchMapping("/{id}")
48+
public ResponseEntity<FooDto> patch(@PathVariable Integer id, @RequestBody JsonNode fooDtoPatch) {
49+
FooDto fooDto; // load current state of the entity
50+
FooDto patchedDto = objectPatcher.patch(fooDto, fooDtoPatch);
51+
52+
// save patchedDto to the data store
53+
}
54+
```
55+
56+
**Note** that if DTO used in the endpoint is **mutable** (e.g. has setters for all attributes), then an existing method from the Jackson library can be used instead of the `ObjectPatcher`:
57+
```java
58+
import com.fasterxml.jackson.databind.JsonNode;
59+
60+
@Autowired
61+
private ObjectMapper objectMapper;
62+
63+
@PatchMapping("/{id}")
64+
public ResponseEntity<FooDto> patch(@PathVariable Integer id, @RequestBody JsonNode fooDtoPatch) throws IOException {
65+
FooDto fooDto; // load current state of the entity
66+
FooDto patchedDto = objectMapper.readerForUpdating(fooDto).readValue(fooDtoPatch);
67+
68+
// save patchedDto to the data store
69+
}
70+
```
71+
72+
#### Validation
73+
`PATCH` REST endpoints, unlike endpoints for other HTTP methods, cannot put `@Valid` on the request body argument, because the request body does not contain the full set of attributes that constitute the object to be validated.
74+
75+
Therefore, it is required to validate patched object in the endpoint code. Unfortunately, Spring doesn't provide one-liner API to perform such validation. As a shortcut to perform the validation, `ObjectPatcher` provides several methods:
76+
77+
```java
78+
@Autowired
79+
private ObjectMapper objectMapper;
80+
81+
// just validate
82+
// public void ObjectPatcher#validate(Object target);
83+
objectPatcher.validate(patchedDto);
84+
85+
// patch and validate right away
86+
// public <T> T ObjectPatcher#patchAndValidate(T target, JsonNode patchJson)
87+
patchedDto = objectPatcher.patchAndValidate(sourceDto, patchJsonNode);
88+
89+
// public <T> T ObjectPatcher#patchAndValidate(T target, String patchJson)
90+
patchedDto = objectPatcher.patchAndValidate(sourceDto, patchString);
91+
```
92+
93+
In case of validation failure, these methods throw non-checked exception `io.amplicode.rautils.patch.PatchValidationException` that contains validation errors and is automatically processed by the Spring `org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver` (resulting in `400 Bad Request` response code).

0 commit comments

Comments
 (0)