Wiredly enforcing uniqe-users with an exception
[demos/spring/data-jdbc] / 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.Clock;
14 import java.time.LocalDateTime;
15 import java.time.ZonedDateTime;
16
17 import static de.juplo.boot.data.jdbc.UserStatus.CREATED;
18 import static de.juplo.boot.data.jdbc.UserStatus.DELETED;
19
20 @RestController
21 @Transactional
22 @RequestMapping("/users")
23 public class UserController {
24
25     private static final Logger LOG = LoggerFactory.getLogger(UserController.class);
26
27
28     private final UserRepository repository;
29     private final Clock clock;
30     private final ApplicationEventPublisher publisher;
31
32
33     public UserController(
34             UserRepository repository,
35             Clock clock,
36             ApplicationEventPublisher publisher)
37     {
38         this.repository = repository;
39         this.clock = clock;
40         this.publisher = publisher;
41     }
42
43
44     @PostMapping
45     public ResponseEntity<Void> createUser(
46             ServletUriComponentsBuilder builder,
47             @RequestBody String username) {
48         String sanitizedUsername = UserController.sanitize(username);
49         User user = new User(sanitizedUsername, LocalDateTime.now(), false);
50
51         LOG.info("Request to create user: {}", user);
52
53         repository.save(user);
54         publisher.publishEvent(
55             new UserEvent(
56                 this,
57                 sanitizedUsername,
58                 CREATED,
59                 ZonedDateTime.now(clock)));
60
61         // Triggers an IncorrectResultSizeDataAccessException, if the user already existed!
62         user = repository.findByUsername(sanitizedUsername);
63
64         UriComponents uri =
65             builder
66                 .fromCurrentRequest()
67                 .pathSegment("{username}")
68                 .buildAndExpand(sanitizedUsername);
69         return ResponseEntity.created(uri.toUri()).build();
70     }
71
72     @GetMapping("{username}")
73     public ResponseEntity<User> getUser(@PathVariable String username) {
74         User user = repository.findByUsername(UserController.sanitize(username));
75
76         if (user == null)
77             return ResponseEntity.notFound().build();
78
79         return ResponseEntity.ok(user);
80     }
81
82     @DeleteMapping("{username}")
83     public ResponseEntity<User> removeUser(@PathVariable String username) {
84         User user = repository.findByUsername(UserController.sanitize(username));
85
86         if (user == null)
87             return ResponseEntity.notFound().build();
88
89         repository.delete(user);
90         publisher.publishEvent(
91             new UserEvent(
92                 this,
93                 user.getUsername(),
94                 DELETED,
95                 ZonedDateTime.now(clock)));
96
97         return ResponseEntity.ok(user);
98     }
99
100     @GetMapping()
101     public ResponseEntity<Iterable<User>> getUsers() {
102         return ResponseEntity.ok(repository.findAll());
103     }
104
105
106     private static String sanitize(String string) {
107         if (string == null)
108             return "";
109
110         return string.trim().toLowerCase();
111     }
112
113     @ExceptionHandler
114     public ResponseEntity<?> incorrectResultSizeDataAccessException(
115         IncorrectResultSizeDataAccessException e
116         )
117     {
118       LOG.info("User already exists!");
119       return ResponseEntity.badRequest().build();
120     }
121 }