WIP
[demos/kafka/outbox] / src / main / java / de / juplo / kafka / outbox / polling / UserController.java
1 package de.juplo.kafka.outbox.polling;
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.util.StreamUtils;
10 import org.springframework.web.bind.annotation.*;
11 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
12 import org.springframework.web.util.UriComponents;
13
14 import javax.servlet.http.HttpServletRequest;
15 import java.io.IOException;
16 import java.nio.charset.Charset;
17 import java.time.LocalDateTime;
18
19 import static de.juplo.kafka.outbox.polling.UserEvent.Type.CREATED;
20 import static de.juplo.kafka.outbox.polling.UserEvent.Type.DELETED;
21
22
23 @RestController
24 @Transactional
25 @RequestMapping("/users")
26 public class UserController {
27
28     private static final Logger LOG = LoggerFactory.getLogger(UserController.class);
29
30
31     private final UserRepository repository;
32     private final ApplicationEventPublisher publisher;
33
34
35     public UserController(
36             UserRepository repository,
37             ApplicationEventPublisher publisher)
38     {
39         this.repository = repository;
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         // Triggering a unique-error for username prevents persistence
52         repository.save(user);
53         publisher.publishEvent(new UserEvent(this, CREATED, sanitizedUsername));
54         user = repository.findByUsername(sanitizedUsername);
55
56         UriComponents uri =
57             builder
58                 .fromCurrentRequest()
59                 .pathSegment("{username}")
60                 .buildAndExpand(sanitizedUsername);
61         return ResponseEntity.created(uri.toUri()).build();
62     }
63
64     @GetMapping("{username}")
65     public ResponseEntity<User> getUser(@PathVariable String username) {
66         User user = repository.findByUsername(UserController.sanitize(username));
67
68         if (user == null)
69             return ResponseEntity.notFound().build();
70
71         return ResponseEntity.ok(user);
72     }
73
74     @DeleteMapping("{username}")
75     public ResponseEntity<User> removeUser(@PathVariable String username) {
76         User user = repository.findByUsername(UserController.sanitize(username));
77
78         if (user == null)
79             return ResponseEntity.notFound().build();
80
81         repository.delete(user);
82         publisher.publishEvent(new UserEvent(this, DELETED, username));
83
84         return ResponseEntity.ok(user);
85     }
86
87     @GetMapping()
88     public ResponseEntity<Iterable<User>> getUsers() {
89         return ResponseEntity.ok(repository.findAll());
90     }
91
92
93     private static String sanitize(String string) {
94         if (string == null)
95             return "";
96
97         return string.trim().toLowerCase();
98     }
99
100     @ExceptionHandler
101     public ResponseEntity<?> incorrectResultSizeDataAccessException(
102         HttpServletRequest request,
103         IncorrectResultSizeDataAccessException e
104         )
105     {
106       String username;
107       try {
108           username = StreamUtils.copyToString(request.getInputStream(), Charset.defaultCharset());
109       }
110       catch (IOException ioe)
111       {
112         username = e.getMessage() + " -> " + ioe.getMessage();
113       }
114       LOG.info("User {} already exists!", username);
115       return ResponseEntity.badRequest().build();
116     }
117 }