1 package de.juplo.kafka.chat.backend.api;
3 import de.juplo.kafka.chat.backend.domain.exceptions.InvalidUsernameException;
4 import de.juplo.kafka.chat.backend.domain.exceptions.MessageMutationException;
5 import de.juplo.kafka.chat.backend.domain.exceptions.ShardNotOwnedException;
6 import de.juplo.kafka.chat.backend.domain.exceptions.UnknownChatroomException;
7 import org.springframework.beans.factory.annotation.Value;
8 import org.springframework.http.HttpStatus;
9 import org.springframework.http.ProblemDetail;
10 import org.springframework.web.bind.annotation.ControllerAdvice;
11 import org.springframework.web.bind.annotation.ExceptionHandler;
12 import org.springframework.web.server.ServerWebExchange;
13 import org.springframework.web.util.UriComponentsBuilder;
15 import java.util.Date;
19 public class ChatBackendControllerAdvice
21 @Value("${server.context-path:/}")
24 @ExceptionHandler(UnknownChatroomException.class)
25 public final ProblemDetail handleException(
26 UnknownChatroomException e,
27 ServerWebExchange exchange,
28 UriComponentsBuilder uriComponentsBuilder)
30 final HttpStatus status = HttpStatus.NOT_FOUND;
31 ProblemDetail problem = ProblemDetail.forStatus(status);
33 problem.setProperty("timestamp", new Date());
35 problem.setProperty("requestId", exchange.getRequest().getId());
37 problem.setType(uriComponentsBuilder.replacePath(contextPath).path("/problem/unknown-chatroom").build().toUri());
38 StringBuilder stringBuilder = new StringBuilder();
39 stringBuilder.append(status.getReasonPhrase());
40 stringBuilder.append(" - ");
41 stringBuilder.append(e.getMessage());
42 problem.setTitle(stringBuilder.toString());
44 stringBuilder.setLength(0);
45 stringBuilder.append("Chatroom unknown: ");
46 stringBuilder.append(e.getChatroomId());
47 problem.setDetail(stringBuilder.toString());
49 problem.setProperty("chatroomId", e.getChatroomId());
50 problem.setProperty("shard", e.getShard());
51 problem.setProperty("ownedShards", e.getOwnedShards());
56 @ExceptionHandler(ShardNotOwnedException.class)
57 public final ProblemDetail handleException(
58 ShardNotOwnedException e,
59 ServerWebExchange exchange,
60 UriComponentsBuilder uriComponentsBuilder)
62 final HttpStatus status = HttpStatus.NOT_FOUND;
63 ProblemDetail problem = ProblemDetail.forStatus(status);
65 problem.setProperty("timestamp", new Date());
67 problem.setProperty("requestId", exchange.getRequest().getId());
69 problem.setType(uriComponentsBuilder.replacePath(contextPath).path("/problem/shard-not-owned").build().toUri());
70 StringBuilder stringBuilder = new StringBuilder();
71 stringBuilder.append(status.getReasonPhrase());
72 stringBuilder.append(" - ");
73 stringBuilder.append(e.getMessage());
74 problem.setTitle(stringBuilder.toString());
76 stringBuilder.setLength(0);
77 stringBuilder.append("Shard not owned: ");
78 stringBuilder.append(e.getShard());
79 problem.setDetail(stringBuilder.toString());
81 problem.setProperty("shard", e.getShard());
86 @ExceptionHandler(MessageMutationException.class)
87 public final ProblemDetail handleException(
88 MessageMutationException e,
89 ServerWebExchange exchange,
90 UriComponentsBuilder uriComponentsBuilder)
92 final HttpStatus status = HttpStatus.BAD_REQUEST;
93 ProblemDetail problem = ProblemDetail.forStatus(status);
95 problem.setProperty("timestamp", new Date());
97 problem.setProperty("requestId", exchange.getRequest().getId());
99 problem.setType(uriComponentsBuilder.replacePath(contextPath).path("/problem/message-mutation").build().toUri());
100 StringBuilder stringBuilder = new StringBuilder();
101 stringBuilder.append(status.getReasonPhrase());
102 stringBuilder.append(" - ");
103 stringBuilder.append(e.getMessage());
104 problem.setTitle(stringBuilder.toString());
106 stringBuilder.setLength(0);
107 stringBuilder.append("The existing message with user=");
108 stringBuilder.append(e.getExisting().getUsername());
109 stringBuilder.append(" and id=");
110 stringBuilder.append(e.getExisting().getId());
111 stringBuilder.append(" cannot be mutated!");
112 problem.setDetail(stringBuilder.toString());
114 problem.setProperty("existingMessage", MessageTo.from(e.getExisting()));
116 problem.setProperty("mutatedText", e.getMutatedText());
121 @ExceptionHandler(InvalidUsernameException.class)
122 public final ProblemDetail handleException(
123 InvalidUsernameException e,
124 ServerWebExchange exchange,
125 UriComponentsBuilder uriComponentsBuilder)
127 final HttpStatus status = HttpStatus.BAD_REQUEST;
128 ProblemDetail problem = ProblemDetail.forStatus(status);
130 problem.setProperty("timestamp", new Date());
132 problem.setProperty("requestId", exchange.getRequest().getId());
134 problem.setType(uriComponentsBuilder.replacePath(contextPath).path("/problem/invalid-username").build().toUri());
135 StringBuilder stringBuilder = new StringBuilder();
136 stringBuilder.append(status.getReasonPhrase());
137 stringBuilder.append(" - ");
138 stringBuilder.append(e.getMessage());
139 problem.setTitle(stringBuilder.toString());
141 stringBuilder.setLength(0);
142 stringBuilder.append("Invalid username: ");
143 stringBuilder.append(e.getUsername());
144 stringBuilder.append(
145 "! A valid username must consist of at at least two letters and " +
146 "must only contain lower case letters a-z, numbers and dashes");
147 problem.setDetail(stringBuilder.toString());
149 problem.setProperty("username", e.getUsername());