From 5ba1c93816a49cfb0886b72f32a8a83203228a61 Mon Sep 17 00:00:00 2001
From: Kai Moritz <kai@juplo.de>
Date: Mon, 26 Dec 2022 14:50:51 +0100
Subject: [PATCH] feat: Added problem-details [RFC-7807] for a message mutation
 error

---
 .../api/ChatroomControllerAdvice.java         | 26 +++++++++++++++++++
 .../juplo/kafka/chatroom/domain/Chatroom.java |  2 +-
 .../domain/MessageMutationException.java      | 19 ++++++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 src/main/java/de/juplo/kafka/chatroom/api/ChatroomControllerAdvice.java
 create mode 100644 src/main/java/de/juplo/kafka/chatroom/domain/MessageMutationException.java

diff --git a/src/main/java/de/juplo/kafka/chatroom/api/ChatroomControllerAdvice.java b/src/main/java/de/juplo/kafka/chatroom/api/ChatroomControllerAdvice.java
new file mode 100644
index 00000000..d98abbbb
--- /dev/null
+++ b/src/main/java/de/juplo/kafka/chatroom/api/ChatroomControllerAdvice.java
@@ -0,0 +1,26 @@
+package de.juplo.kafka.chatroom.api;
+
+import de.juplo.kafka.chatroom.domain.MessageMutationException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ProblemDetail;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.reactive.result.method.annotation.ResponseEntityExceptionHandler;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+
+@ControllerAdvice
+public class ChatroomControllerAdvice extends ResponseEntityExceptionHandler
+{
+  @ExceptionHandler(MessageMutationException.class)
+  public final Mono<ResponseEntity<Object>> handleException(MessageMutationException e, ServerWebExchange exchange)
+  {
+    final HttpStatus status = HttpStatus.BAD_REQUEST;
+    ProblemDetail body = ProblemDetail.forStatusAndDetail(status, e.getMessage());
+    body.setProperty("new", e.getToAdd());
+    body.setProperty("existing", e.getExisting());
+    return handleExceptionInternal(e, body, null, status, exchange);
+  }
+}
diff --git a/src/main/java/de/juplo/kafka/chatroom/domain/Chatroom.java b/src/main/java/de/juplo/kafka/chatroom/domain/Chatroom.java
index 1d7ee2af..62d33f27 100644
--- a/src/main/java/de/juplo/kafka/chatroom/domain/Chatroom.java
+++ b/src/main/java/de/juplo/kafka/chatroom/domain/Chatroom.java
@@ -48,7 +48,7 @@ public class Chatroom
     {
       log.info("Message with key {} already exists; {}", key, existing);
       if (!message.equals(existing))
-        throw new IllegalArgumentException("Messages are imutable!");
+        throw new MessageMutationException(message, existing);
       return Mono.empty();
     }
 
diff --git a/src/main/java/de/juplo/kafka/chatroom/domain/MessageMutationException.java b/src/main/java/de/juplo/kafka/chatroom/domain/MessageMutationException.java
new file mode 100644
index 00000000..ceeea240
--- /dev/null
+++ b/src/main/java/de/juplo/kafka/chatroom/domain/MessageMutationException.java
@@ -0,0 +1,19 @@
+package de.juplo.kafka.chatroom.domain;
+
+import lombok.Getter;
+
+
+public class MessageMutationException extends RuntimeException
+{
+  @Getter
+  private final Message toAdd;
+  @Getter
+  private final Message existing;
+
+  public MessageMutationException(Message toAdd, Message existing)
+  {
+    super("Messages are imutable!");
+    this.toAdd = toAdd;
+    this.existing = existing;
+  }
+}
-- 
2.20.1