|
2 | 2 | [](https://sonarcloud.io/dashboard?id=hrytsenko_json-data-spring-boot) |
3 | 3 | [](https://jitpack.io/#hrytsenko/json-data-spring-boot) |
4 | 4 |
|
5 | | -# Summary |
| 5 | +# JSON data for Spring Boot |
6 | 6 |
|
7 | | -This library enables [json-data] for [Spring Boot] including serialization, validation and error handling for HTTP requests and responses that use JSON entities. |
8 | | - |
9 | | -# Example |
10 | | - |
11 | | -The following example illustrates: |
12 | | -* Use of JSON entities with [Spring Boot]. |
13 | | -* Use of JSON entities with [Spring Feign]. |
14 | | -* Use of JSON errors with [Spring Boot] and [Spring Sleuth]. |
| 7 | +This library enables [json-data] for [Spring Boot] including serialization, validation and error handling. |
| 8 | +The following example illustrates integration with [Spring Boot], [Spring Feign] and [Spring Sleuth]: |
15 | 9 |
|
16 | 10 | ```java |
17 | 11 | @EnableFeignClients |
18 | 12 | @SpringBootApplication |
19 | 13 | class Application { |
20 | 14 |
|
21 | | - static class Request extends JsonEntity<Request> { |
22 | | - String getOwner() { |
23 | | - return getString("owner"); |
24 | | - } |
| 15 | + static class Request extends JsonEntity<Request> { |
| 16 | + String getOwner() { |
| 17 | + return getString("owner"); |
25 | 18 | } |
26 | | - |
27 | | - static class Response extends JsonEntity<Response> { |
| 19 | + } |
| 20 | + |
| 21 | + static class Response extends JsonEntity<Response> { |
| 22 | + } |
| 23 | + |
| 24 | + @RestController |
| 25 | + @AllArgsConstructor |
| 26 | + static class GithubController { |
| 27 | + |
| 28 | + static JsonMapper<Response> TO_RESPONSE = JsonMapper.create( |
| 29 | + JsonResources.readResource("/response-projection.json"), Response::new); |
| 30 | + |
| 31 | + GithubClient githubClient; |
| 32 | + |
| 33 | + @PostMapping( |
| 34 | + value = "/list-repositories", |
| 35 | + consumes = MediaType.APPLICATION_JSON_VALUE, |
| 36 | + produces = MediaType.APPLICATION_JSON_VALUE) |
| 37 | + @ValidateRequest("/request-schema.json") |
| 38 | + @ValidateResponse("/response-schema.json") |
| 39 | + @WrapErrors("CANNOT_LIST_REPOSITORIES") |
| 40 | + public Response listRepositories(@RequestBody Request request) { |
| 41 | + var repositories = githubClient.listRepositories(request.getOwner()); |
| 42 | + return TO_RESPONSE.map(repositories); |
28 | 43 | } |
29 | 44 |
|
30 | | - @RestController |
31 | | - @AllArgsConstructor |
32 | | - static class GithubController { |
33 | | - |
34 | | - static JsonMapper<Response> TO_RESPONSE = JsonMapper.create( |
35 | | - JsonResources.readResource("/response-projection.json"), Response::new); |
36 | | - |
37 | | - GithubClient githubClient; |
38 | | - |
39 | | - @PostMapping( |
40 | | - value = "/list-repositories", |
41 | | - consumes = MediaType.APPLICATION_JSON_VALUE, |
42 | | - produces = MediaType.APPLICATION_JSON_VALUE) |
43 | | - @ValidateRequest("/request-schema.json") |
44 | | - @ValidateResponse("/response-schema.json") |
45 | | - @WrapErrors("CANNOT_LIST_REPOSITORIES") |
46 | | - public Response listRepositories(@RequestBody Request request) { |
47 | | - val repositories = githubClient.listRepositories(request.getOwner()); |
48 | | - return TO_RESPONSE.map(repositories); |
49 | | - } |
50 | | - |
51 | | - @FeignClient( |
52 | | - name = "github-client", |
53 | | - url = "${github.url}") |
54 | | - interface GithubClient { |
55 | | - @GetMapping( |
56 | | - value = "/users/{owner}/repos", |
57 | | - produces = MediaType.APPLICATION_JSON_VALUE) |
58 | | - List<JsonBean> listRepositories(@PathVariable("owner") String owner); |
59 | | - } |
60 | | - |
| 45 | + @FeignClient(name = "github-client", url = "${github.url}") |
| 46 | + interface GithubClient { |
| 47 | + @GetMapping( |
| 48 | + value = "/users/{owner}/repos", |
| 49 | + produces = MediaType.APPLICATION_JSON_VALUE) |
| 50 | + List<JsonBean> listRepositories(@PathVariable("owner") String owner); |
61 | 51 | } |
62 | 52 |
|
63 | | - @Bean |
64 | | - public CorrelationSource sleuthSource(Tracer tracer) { |
65 | | - return () -> tracer.currentSpan().context().traceIdString(); |
66 | | - } |
| 53 | + } |
67 | 54 |
|
68 | | - public static void main(String[] args) { |
69 | | - SpringApplication.run(Application.class, args); |
70 | | - } |
| 55 | + @Bean |
| 56 | + CorrelationSource sleuthSource(Tracer tracer) { |
| 57 | + return () -> tracer.currentSpan().context().traceId(); |
| 58 | + } |
| 59 | + |
| 60 | + public static void main(String[] args) { |
| 61 | + SpringApplication.run(Application.class, args); |
| 62 | + } |
71 | 63 |
|
72 | 64 | } |
73 | 65 | ``` |
74 | 66 |
|
75 | | -# Usage |
76 | | - |
77 | | -Use JSON entities with Spring Web and Spring Feign. |
78 | | - |
79 | | -Use `ValidateRequest` to validate a JSON entity (the first argument) via JSON Schema. Use `ValidateResponse` to validate a JSON entity (the return value) via JSON Schema. |
80 | | - |
81 | | -Use `WrapErrors` to wrap all exceptions in `ServiceException.InternalError` with a given error code, except those that are `ServiceException`. |
| 67 | +Use `ValidateRequest` to validate an input JSON entity (the first argument). |
| 68 | +Use `ValidateResponse` to validate an output JSON entity (the return value). |
| 69 | +Provide `ValidatorSource` to configure a resource manager for validators. |
82 | 70 |
|
| 71 | +Use `WrapErrors` to wrap all unhandled exceptions into `ServiceException.InternalError`. |
83 | 72 | Provide `CorrelationSource` to enable correlations for error responses. |
84 | 73 |
|
85 | | -Provide `ValidatorSource` to configure a resource manager for validators. |
86 | | - |
87 | | -[json-data]: https://github.com/hrytsenko/json-data |
| 74 | +[json-data]: https://github.com/hrytsenko/json-data |
88 | 75 | [Spring Boot]: https://spring.io/projects/spring-boot |
89 | 76 | [Spring Feign]: https://spring.io/projects/spring-cloud-openfeign |
90 | 77 | [Spring Sleuth]: https://spring.io/projects/spring-cloud-sleuth |
0 commit comments