Wiredly enforcing uniqe-users with an exception
[demos/kafka/outbox] / src / main / java / de / juplo / boot / data / jdbc / UserController.java
1 package de.juplo.boot.data.jdbc;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.springframework.context.ApplicationEventPublisher;
6 import org.springframework.dao.IncorrectResultSizeDataAccessException;
7 import org.springframework.http.ResponseEntity;
8 import org.springframework.transaction.annotation.Transactional;
9 import org.springframework.web.bind.annotation.*;
10 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
11 import org.springframework.web.util.UriComponents;
12
13 import java.time.LocalDateTime;
14
15 import static de.juplo.boot.data.jdbc.UserEvent.Type.CREATED;
16 import static de.juplo.boot.data.jdbc.UserEvent.Type.DELETED;
17
18 @RestController
19 @Transactional
20 @RequestMapping("/users")
21 public class UserController {
22
23     private static final Logger LOG = LoggerFactory.getLogger(UserController.class);
24
25
26     private final UserRepository repository;
27     private final ApplicationEventPublisher publisher;
28
29
30     public UserController(
31             UserRepository repository,
32             ApplicationEventPublisher publisher)
33     {
34         this.repository = repository;
35         this.publisher = publisher;
36     }
37
38
39     @PostMapping
40     public ResponseEntity<Void> createUser(
41             ServletUriComponentsBuilder builder,
42             @RequestBody String username) {
43         String sanitizedUsername = UserController.sanitize(username);
44         User user = new User(sanitizedUsername, LocalDateTime.now(), false);
45
46         // Triggering a unique-error for username prevents persistence
47         repository.save(user);
48         publisher.publishEvent(new UserEvent(this, CREATED, sanitizedUsername));
49         user = repository.findByUsername(sanitizedUsername);
50
51         UriComponents uri =
52             builder
53                 .fromCurrentRequest()
54                 .pathSegment("{username}")
55                 .buildAndExpand(sanitizedUsername);
56         return ResponseEntity.created(uri.toUri()).build();
57     }
58
59     @GetMapping("{username}")
60     public ResponseEntity<User> getUser(@PathVariable String username) {
61         User user = repository.findByUsername(UserController.sanitize(username));
62
63         if (user == null)
64             return ResponseEntity.notFound().build();
65
66         return ResponseEntity.ok(user);
67     }
68
69     @DeleteMapping("{username}")
70     public ResponseEntity<User> removeUser(@PathVariable String username) {
71         User user = repository.findByUsername(UserController.sanitize(username));
72
73         if (user == null)
74             return ResponseEntity.notFound().build();
75
76         repository.delete(user);
77         publisher.publishEvent(new UserEvent(this, DELETED, username));
78
79         return ResponseEntity.ok(user);
80     }
81
82     @GetMapping()
83     public ResponseEntity<Iterable<User>> getUsers() {
84         return ResponseEntity.ok(repository.findAll());
85     }
86
87
88     private static String sanitize(String string) {
89         if (string == null)
90             return "";
91
92         return string.trim().toLowerCase();
93     }
94
95     @ExceptionHandler
96     public ResponseEntity<?> incorrectResultSizeDataAccessException(
97         IncorrectResultSizeDataAccessException e
98         )
99     {
100       LOG.info("User already exists!");
101       return ResponseEntity.badRequest().build();
102     }
103 }