From 58bd98b016d1cc6e0c7bfb42ffc333389a8d158a Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 9 Apr 2024 13:19:30 +0900 Subject: [PATCH 01/24] =?UTF-8?q?refactor:=20=EB=A9=94=EC=8B=9C=EC=A7=80?= =?UTF-8?q?=20=EC=A0=84=EC=86=A1=20=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChatWebSocketHandleTextMessageProvider.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index d9f69098d..2e4c1da4b 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -30,6 +30,8 @@ @RequiredArgsConstructor public class ChatWebSocketHandleTextMessageProvider implements WebSocketHandleTextMessageProvider { + private static final String CHATROOM_ID_KEY = "chatRoomId"; + private final WebSocketChatSessions sessions; private final ObjectMapper objectMapper; private final MessageService messageService; @@ -47,10 +49,19 @@ public List handleCreateSendMessage( final Map data ) throws JsonProcessingException { final SessionAttributeDto sessionAttribute = getSessionAttributes(session); - final ChatMessageDataDto messageData = objectMapper.convertValue(data, ChatMessageDataDto.class); - sessions.add(session, messageData.chatRoomId()); + final long chatRoomId = getChatRoomId(data); + sessions.add(session, chatRoomId); + + return createSendMessageResponse(data, sessionAttribute); + } + private long getChatRoomId(final Map data) { + return Long.parseLong(data.get(CHATROOM_ID_KEY)); + } + + private List createSendMessageResponse(final Map data, final SessionAttributeDto sessionAttribute) throws JsonProcessingException { final Long writerId = sessionAttribute.userId(); + final ChatMessageDataDto messageData = objectMapper.convertValue(data, ChatMessageDataDto.class); final CreateMessageDto createMessageDto = createMessageDto(messageData, writerId); final Message message = messageService.create(createMessageDto); sendNotificationIfReceiverNotInSession(message, sessionAttribute); From 1d2ba164c150d290c0727ce0f2d199b5e8aa0d63 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 9 Apr 2024 13:20:33 +0900 Subject: [PATCH 02/24] =?UTF-8?q?refactor:=20PING=20response=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...hatWebSocketHandleTextMessageProvider.java | 29 +++++++++++++++++++ .../chat/handler/dto/ChatPingDataDto.java | 4 +++ .../handler/dto/HandleMessageResponse.java | 6 ++++ .../chat/handler/dto/SendMessageStatus.java | 9 ++++++ 4 files changed, 48 insertions(+) create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDataDto.java create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendMessageStatus.java diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index 2e4c1da4b..18fc5b75d 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -2,13 +2,18 @@ import com.ddang.ddang.chat.application.MessageService; import com.ddang.ddang.chat.application.dto.CreateMessageDto; +import com.ddang.ddang.chat.application.dto.ReadMessageDto; import com.ddang.ddang.chat.application.event.MessageNotificationEvent; import com.ddang.ddang.chat.application.event.UpdateReadMessageLogEvent; import com.ddang.ddang.chat.domain.Message; import com.ddang.ddang.chat.domain.WebSocketChatSessions; import com.ddang.ddang.chat.handler.dto.ChatMessageDataDto; +import com.ddang.ddang.chat.handler.dto.ChatPingDataDto; +import com.ddang.ddang.chat.handler.dto.HandleMessageResponse; import com.ddang.ddang.chat.handler.dto.MessageDto; +import com.ddang.ddang.chat.handler.dto.SendMessageStatus; import com.ddang.ddang.chat.presentation.dto.request.CreateMessageRequest; +import com.ddang.ddang.chat.presentation.dto.request.ReadMessageRequest; import com.ddang.ddang.websocket.handler.WebSocketHandleTextMessageProvider; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; @@ -52,6 +57,9 @@ public List handleCreateSendMessage( final long chatRoomId = getChatRoomId(data); sessions.add(session, chatRoomId); + if (isPing(data)) { + return createPingResponse(sessionAttribute, data, session); + } return createSendMessageResponse(data, sessionAttribute); } @@ -59,6 +67,27 @@ private long getChatRoomId(final Map data) { return Long.parseLong(data.get(CHATROOM_ID_KEY)); } + private boolean isPing(final Map data) { + return data.get("type").equals("ping"); + } + + private List createPingResponse(final SessionAttributeDto sessionAttribute, final Map data, final WebSocketSession userSession) throws JsonProcessingException { + final ChatPingDataDto pingData = objectMapper.convertValue(data, ChatPingDataDto.class); + final ReadMessageRequest readMessageRequest = new ReadMessageRequest(sessionAttribute.userId(), pingData.chatRoomId(), pingData.lastMessageId()); + final List readMessageDtos = messageService.readAllByLastMessageId(readMessageRequest); + + final List textMessages = convertToMessageDto(readMessageDtos, userSession); + final HandleMessageResponse handleMessageResponse = new HandleMessageResponse(SendMessageStatus.SUCCESS, textMessages); + // 메서드 분리 + return List.of(new SendMessageDto(userSession, new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)))); + } + + private List convertToMessageDto(final List readMessageDtos, final WebSocketSession session) { + return readMessageDtos.stream() + .map(readMessageDto -> new MessageDto(readMessageDto.id(), readMessageDto.createdTime(), isMyMessage(session, readMessageDto.writerId()), readMessageDto.contents())) + .toList(); + } + private List createSendMessageResponse(final Map data, final SessionAttributeDto sessionAttribute) throws JsonProcessingException { final Long writerId = sessionAttribute.userId(); final ChatMessageDataDto messageData = objectMapper.convertValue(data, ChatMessageDataDto.class); diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDataDto.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDataDto.java new file mode 100644 index 000000000..845982b30 --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDataDto.java @@ -0,0 +1,4 @@ +package com.ddang.ddang.chat.handler.dto; + +public record ChatPingDataDto(Long chatRoomId, Long lastMessageId) { +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java new file mode 100644 index 000000000..d624e782e --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java @@ -0,0 +1,6 @@ +package com.ddang.ddang.chat.handler.dto; + +import java.util.List; + +public record HandleMessageResponse(SendMessageStatus sendMessageStatus, List messages) { +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendMessageStatus.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendMessageStatus.java new file mode 100644 index 000000000..0a7b7ba1f --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendMessageStatus.java @@ -0,0 +1,9 @@ +package com.ddang.ddang.chat.handler.dto; + +public enum SendMessageStatus { + + SUCCESS, + DISCONNECTED, + FORBIDDEN, + ; +} From c03ddef4a663c7c0dd71e65ec2ba89b58a46e0f6 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 9 Apr 2024 13:21:16 +0900 Subject: [PATCH 03/24] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...hatWebSocketHandleTextMessageProvider.java | 31 +++++++++---------- .../ddang/chat/handler/dto/MessageDto.java | 10 ++++++ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index 18fc5b75d..dfe2149b9 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -67,6 +67,12 @@ private long getChatRoomId(final Map data) { return Long.parseLong(data.get(CHATROOM_ID_KEY)); } + private SessionAttributeDto getSessionAttributes(final WebSocketSession session) { + final Map attributes = session.getAttributes(); + + return objectMapper.convertValue(attributes, SessionAttributeDto.class); + } + private boolean isPing(final Map data) { return data.get("type").equals("ping"); } @@ -76,15 +82,14 @@ private List createPingResponse(final SessionAttributeDto sessio final ReadMessageRequest readMessageRequest = new ReadMessageRequest(sessionAttribute.userId(), pingData.chatRoomId(), pingData.lastMessageId()); final List readMessageDtos = messageService.readAllByLastMessageId(readMessageRequest); - final List textMessages = convertToMessageDto(readMessageDtos, userSession); - final HandleMessageResponse handleMessageResponse = new HandleMessageResponse(SendMessageStatus.SUCCESS, textMessages); - // 메서드 분리 + final List messageDtos = convertToMessageDto(readMessageDtos, userSession); + final HandleMessageResponse handleMessageResponse = new HandleMessageResponse(SendMessageStatus.SUCCESS, messageDtos); return List.of(new SendMessageDto(userSession, new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)))); } private List convertToMessageDto(final List readMessageDtos, final WebSocketSession session) { return readMessageDtos.stream() - .map(readMessageDto -> new MessageDto(readMessageDto.id(), readMessageDto.createdTime(), isMyMessage(session, readMessageDto.writerId()), readMessageDto.contents())) + .map(readMessageDto -> MessageDto.of(readMessageDto, isMyMessage(session, readMessageDto.writerId()))) .toList(); } @@ -98,12 +103,6 @@ private List createSendMessageResponse(final Map return createSendMessages(message, writerId, createMessageDto.chatRoomId()); } - private SessionAttributeDto getSessionAttributes(final WebSocketSession session) { - final Map attributes = session.getAttributes(); - - return objectMapper.convertValue(attributes, SessionAttributeDto.class); - } - private CreateMessageDto createMessageDto(final ChatMessageDataDto messageData, final Long userId) { final CreateMessageRequest request = new CreateMessageRequest( messageData.receiverId(), @@ -135,7 +134,8 @@ private List createSendMessages( final List sendMessageDtos = new ArrayList<>(); for (final WebSocketSession currentSession : groupSessions) { - final TextMessage textMessage = createTextMessage(message, writerId, currentSession); + final MessageDto messageDto = MessageDto.of(message, isMyMessage(currentSession, writerId)); + final TextMessage textMessage = createTextMessage(messageDto); sendMessageDtos.add(new SendMessageDto(currentSession, textMessage)); updateReadMessageLog(currentSession, chatRoomId, message); } @@ -144,14 +144,11 @@ private List createSendMessages( } private TextMessage createTextMessage( - final Message message, - final Long writerId, - final WebSocketSession session + final MessageDto messageDto ) throws JsonProcessingException { - final boolean isMyMessage = isMyMessage(session, writerId); - final MessageDto messageDto = MessageDto.of(message, isMyMessage); + final HandleMessageResponse handleMessageResponse = new HandleMessageResponse(SendMessageStatus.SUCCESS, List.of(messageDto)); - return new TextMessage(objectMapper.writeValueAsString(messageDto)); + return new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)); } private boolean isMyMessage(final WebSocketSession session, final Long writerId) { diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/MessageDto.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/MessageDto.java index 30e7e5512..4cb12590c 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/MessageDto.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/MessageDto.java @@ -1,5 +1,6 @@ package com.ddang.ddang.chat.handler.dto; +import com.ddang.ddang.chat.application.dto.ReadMessageDto; import com.ddang.ddang.chat.domain.Message; import com.fasterxml.jackson.annotation.JsonFormat; @@ -24,4 +25,13 @@ public static MessageDto of(final Message message, final boolean isMyMessage) { message.getContents() ); } + + public static MessageDto of(final ReadMessageDto readMessageDto, final boolean isMyMessage) { + return new MessageDto( + readMessageDto.id(), + readMessageDto.createdTime(), + isMyMessage, + readMessageDto.contents() + ); + } } From 81f6c2d6c50735a40a514262258228afe5c1e4d8 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 9 Apr 2024 13:23:26 +0900 Subject: [PATCH 04/24] =?UTF-8?q?test:=20=EC=8B=A4=ED=8C=A8=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChatWebSocketHandleTextMessageProviderTestFixture.java | 2 +- .../application/fixture/NotificationEventListenerFixture.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java index 3d9d288ac..07aecd76e 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java @@ -10,7 +10,6 @@ import com.ddang.ddang.chat.application.event.CreateReadMessageLogEvent; import com.ddang.ddang.chat.domain.ChatRoom; import com.ddang.ddang.chat.domain.repository.ChatRoomRepository; -import com.ddang.ddang.chat.domain.repository.ReadMessageLogRepository; import com.ddang.ddang.image.domain.ProfileImage; import com.ddang.ddang.user.domain.Reliability; import com.ddang.ddang.user.domain.User; @@ -89,6 +88,7 @@ void setUpFixture() { 발신자_세션_attribute_정보 = new HashMap<>(Map.of("userId", 발신자.getId(), "baseUrl", "/images")); 수신자_세션_attribute_정보 = new HashMap<>(Map.of("userId", 수신자.getId(), "baseUrl", "/images")); 메시지_전송_데이터 = Map.of( + "type", "message", "chatRoomId", String.valueOf(채팅방.getId()), "receiverId", String.valueOf(수신자.getId()), "contents", "메시지 내용" diff --git a/backend/ddang/src/test/java/com/ddang/ddang/notification/application/fixture/NotificationEventListenerFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/notification/application/fixture/NotificationEventListenerFixture.java index 847fbcb40..4ff226ba4 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/notification/application/fixture/NotificationEventListenerFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/notification/application/fixture/NotificationEventListenerFixture.java @@ -121,6 +121,7 @@ void setUpFixture() { "baseUrl", 이미지_절대_경로 )); 메시지_전송_데이터 = Map.of( + "type", "message", "chatRoomId", String.valueOf(채팅방.getId()), "receiverId", String.valueOf(수신자_겸_기존_입찰자.getId()), "contents", "메시지 내용" From 76b9b218ce12f6fdfafcebe9f3fd2c9170167521 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 9 Apr 2024 13:24:21 +0900 Subject: [PATCH 05/24] =?UTF-8?q?refactor:=20=EC=B1=84=ED=8C=85=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20enum=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...hatWebSocketHandleTextMessageProvider.java | 8 +++--- .../websocket/handler/dto/ChattingType.java | 26 +++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index dfe2149b9..9f7872211 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -15,6 +15,7 @@ import com.ddang.ddang.chat.presentation.dto.request.CreateMessageRequest; import com.ddang.ddang.chat.presentation.dto.request.ReadMessageRequest; import com.ddang.ddang.websocket.handler.WebSocketHandleTextMessageProvider; +import com.ddang.ddang.websocket.handler.dto.ChattingType; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; import com.ddang.ddang.websocket.handler.dto.TextMessageType; @@ -57,7 +58,8 @@ public List handleCreateSendMessage( final long chatRoomId = getChatRoomId(data); sessions.add(session, chatRoomId); - if (isPing(data)) { + final ChattingType type = ChattingType.findValue(data); + if (ChattingType.PING == type) { return createPingResponse(sessionAttribute, data, session); } return createSendMessageResponse(data, sessionAttribute); @@ -73,10 +75,6 @@ private SessionAttributeDto getSessionAttributes(final WebSocketSession session) return objectMapper.convertValue(attributes, SessionAttributeDto.class); } - private boolean isPing(final Map data) { - return data.get("type").equals("ping"); - } - private List createPingResponse(final SessionAttributeDto sessionAttribute, final Map data, final WebSocketSession userSession) throws JsonProcessingException { final ChatPingDataDto pingData = objectMapper.convertValue(data, ChatPingDataDto.class); final ReadMessageRequest readMessageRequest = new ReadMessageRequest(sessionAttribute.userId(), pingData.chatRoomId(), pingData.lastMessageId()); diff --git a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java new file mode 100644 index 000000000..c9a1ee043 --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java @@ -0,0 +1,26 @@ +package com.ddang.ddang.websocket.handler.dto; + +import java.util.Arrays; +import java.util.Map; + +public enum ChattingType { + + CHATTING_TYPE_KEY("type"), + MESSAGE("message"), + PING("ping"), + ; + + private String value; + + ChattingType(final String value) { + this.value = value; + } + + public static ChattingType findValue(final Map data) { + final String value = data.get(CHATTING_TYPE_KEY.value); + return Arrays.stream(ChattingType.values()) + .filter(chattingType -> chattingType.value.equals(value)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("잘못된 채팅 타입입니다.")); + } +} From 0d108cbc33e7939c3e296780a8e691a6f7d7a008 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 9 Apr 2024 13:25:46 +0900 Subject: [PATCH 06/24] =?UTF-8?q?refactor:=20=EC=B1=84=ED=8C=85=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=83=81=EC=88=98=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...hatWebSocketHandleTextMessageProvider.java | 3 +- .../websocket/handler/dto/ChattingType.java | 5 +-- .../handler/dto/ChattingTypeTest.java | 33 +++++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index 9f7872211..d6902c8bc 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -37,6 +37,7 @@ public class ChatWebSocketHandleTextMessageProvider implements WebSocketHandleTextMessageProvider { private static final String CHATROOM_ID_KEY = "chatRoomId"; + private static final String CHATTTING_TYPE_KEY = "type"; private final WebSocketChatSessions sessions; private final ObjectMapper objectMapper; @@ -58,7 +59,7 @@ public List handleCreateSendMessage( final long chatRoomId = getChatRoomId(data); sessions.add(session, chatRoomId); - final ChattingType type = ChattingType.findValue(data); + final ChattingType type = ChattingType.findValue(data.get(CHATTTING_TYPE_KEY)); if (ChattingType.PING == type) { return createPingResponse(sessionAttribute, data, session); } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java index c9a1ee043..92d62a35b 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java @@ -1,11 +1,9 @@ package com.ddang.ddang.websocket.handler.dto; import java.util.Arrays; -import java.util.Map; public enum ChattingType { - CHATTING_TYPE_KEY("type"), MESSAGE("message"), PING("ping"), ; @@ -16,8 +14,7 @@ public enum ChattingType { this.value = value; } - public static ChattingType findValue(final Map data) { - final String value = data.get(CHATTING_TYPE_KEY.value); + public static ChattingType findValue(final String value) { return Arrays.stream(ChattingType.values()) .filter(chattingType -> chattingType.value.equals(value)) .findFirst() diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java new file mode 100644 index 000000000..52604aa02 --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java @@ -0,0 +1,33 @@ +package com.ddang.ddang.websocket.handler.dto; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class ChattingTypeTest { + + @Test + void 타입에_해당하는_enum을_반환한다() { + // given + final Map data = Map.of("type", "message"); + + // when + final ChattingType actual = ChattingType.findValue(data.get("type")); + + // then + assertThat(actual).isEqualTo(ChattingType.MESSAGE); + } + + + @Test + void 해당하는_타입이_없는_경우_예외를_던진다() { + // given + final Map data = Map.of("type", "wrong type"); + + // when & then + assertThatThrownBy(() -> ChattingType.findValue(data.get("type"))).isInstanceOf(IllegalArgumentException.class); + } +} From 7c2aa4fc4717226c8e9cac253b3b5fcb33b07076 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 9 Apr 2024 13:26:50 +0900 Subject: [PATCH 07/24] =?UTF-8?q?test:=20=EC=B1=84=ED=8C=85=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=ED=83=80=EC=9E=85=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ChatWebSocketHandleTextMessageProviderTest.java | 14 ++++++++++++++ ...SocketHandleTextMessageProviderTestFixture.java | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java index dd7c99cd9..ef8873bf1 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java @@ -28,6 +28,7 @@ import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.willDoNothing; @@ -173,6 +174,19 @@ class ChatWebSocketHandleTextMessageProviderTest extends ChatWebSocketHandleText assertThat(actual).hasSize(1); } + @Test + void 잘못된_데이터_타입_전달시_예외가_발생한다() throws JsonProcessingException { + // given + given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); + willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); + willReturn(false).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); + willReturn(Set.of(writerSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + + // when + assertThatThrownBy(() -> provider.handleCreateSendMessage(writerSession, 잘못된_메시지_전송_데이터)) + .isInstanceOf(IllegalArgumentException.class); + } + @Test void 세션을_삭제한다() { // given diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java index 07aecd76e..a1fc31506 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java @@ -46,6 +46,7 @@ public class ChatWebSocketHandleTextMessageProviderTestFixture { protected Map 발신자_세션_attribute_정보; protected Map 수신자_세션_attribute_정보; protected Map 메시지_전송_데이터; + protected Map 잘못된_메시지_전송_데이터; protected CreateReadMessageLogEvent 메시지_로그_생성_이벤트; @@ -93,6 +94,9 @@ void setUpFixture() { "receiverId", String.valueOf(수신자.getId()), "contents", "메시지 내용" ); + 잘못된_메시지_전송_데이터 = Map.of( + "type", "wrong message type" + ); 메시지_로그_생성_이벤트 = new CreateReadMessageLogEvent(채팅방); } From fc0259ef1321b47b27f299a0010a9bd1e68f2ba2 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 9 Apr 2024 13:28:38 +0900 Subject: [PATCH 08/24] =?UTF-8?q?test:=20warning=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ddang/ddang/chat/handler/dto/SendMessageStatus.java | 3 +-- .../com/ddang/ddang/websocket/handler/dto/ChattingType.java | 2 +- .../ddang/ddang/websocket/handler/dto/ChattingTypeTest.java | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendMessageStatus.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendMessageStatus.java index 0a7b7ba1f..d030f4801 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendMessageStatus.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendMessageStatus.java @@ -4,6 +4,5 @@ public enum SendMessageStatus { SUCCESS, DISCONNECTED, - FORBIDDEN, - ; + FORBIDDEN } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java index 92d62a35b..8a8e7a361 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java @@ -8,7 +8,7 @@ public enum ChattingType { PING("ping"), ; - private String value; + private final String value; ChattingType(final String value) { this.value = value; diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java index 52604aa02..db0da73ac 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java @@ -7,6 +7,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@SuppressWarnings("NonAsciiCharacters") class ChattingTypeTest { @Test From 9aa8fab2a05939fd9a6bdb46ab81869d7be262c9 Mon Sep 17 00:00:00 2001 From: swonny Date: Mon, 15 Apr 2024 21:41:34 +0900 Subject: [PATCH 09/24] =?UTF-8?q?style:=20=EA=B0=9C=ED=96=89=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=88=9C?= =?UTF-8?q?=EC=84=9C=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...hatWebSocketHandleTextMessageProvider.java | 80 ++++++++++++------- ...tHandleTextMessageProviderTestFixture.java | 38 +++++---- 2 files changed, 71 insertions(+), 47 deletions(-) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index d6902c8bc..8ad61f81a 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -66,33 +66,55 @@ public List handleCreateSendMessage( return createSendMessageResponse(data, sessionAttribute); } - private long getChatRoomId(final Map data) { - return Long.parseLong(data.get(CHATROOM_ID_KEY)); - } - private SessionAttributeDto getSessionAttributes(final WebSocketSession session) { final Map attributes = session.getAttributes(); return objectMapper.convertValue(attributes, SessionAttributeDto.class); } - private List createPingResponse(final SessionAttributeDto sessionAttribute, final Map data, final WebSocketSession userSession) throws JsonProcessingException { + private long getChatRoomId(final Map data) { + return Long.parseLong(data.get(CHATROOM_ID_KEY)); + } + + private List createPingResponse( + final SessionAttributeDto sessionAttribute, + final Map data, + final WebSocketSession userSession + ) throws JsonProcessingException { final ChatPingDataDto pingData = objectMapper.convertValue(data, ChatPingDataDto.class); - final ReadMessageRequest readMessageRequest = new ReadMessageRequest(sessionAttribute.userId(), pingData.chatRoomId(), pingData.lastMessageId()); + final ReadMessageRequest readMessageRequest = new ReadMessageRequest( + sessionAttribute.userId(), + pingData.chatRoomId(), + pingData.lastMessageId() + ); final List readMessageDtos = messageService.readAllByLastMessageId(readMessageRequest); final List messageDtos = convertToMessageDto(readMessageDtos, userSession); - final HandleMessageResponse handleMessageResponse = new HandleMessageResponse(SendMessageStatus.SUCCESS, messageDtos); - return List.of(new SendMessageDto(userSession, new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)))); + final HandleMessageResponse handleMessageResponse = new HandleMessageResponse( + SendMessageStatus.SUCCESS, + messageDtos + ); + return List.of(new SendMessageDto( + userSession, + new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)) + )); } - private List convertToMessageDto(final List readMessageDtos, final WebSocketSession session) { + private List convertToMessageDto( + final List readMessageDtos, + final WebSocketSession session + ) { return readMessageDtos.stream() - .map(readMessageDto -> MessageDto.of(readMessageDto, isMyMessage(session, readMessageDto.writerId()))) - .toList(); + .map(readMessageDto -> MessageDto.of(readMessageDto, + isMyMessage(session, readMessageDto.writerId()) + )) + .toList(); } - private List createSendMessageResponse(final Map data, final SessionAttributeDto sessionAttribute) throws JsonProcessingException { + private List createSendMessageResponse( + final Map data, + final SessionAttributeDto sessionAttribute + ) throws JsonProcessingException { final Long writerId = sessionAttribute.userId(); final ChatMessageDataDto messageData = objectMapper.convertValue(data, ChatMessageDataDto.class); final CreateMessageDto createMessageDto = createMessageDto(messageData, writerId); @@ -102,11 +124,11 @@ private List createSendMessageResponse(final Map return createSendMessages(message, writerId, createMessageDto.chatRoomId()); } - private CreateMessageDto createMessageDto(final ChatMessageDataDto messageData, final Long userId) { - final CreateMessageRequest request = new CreateMessageRequest( - messageData.receiverId(), - messageData.contents() - ); + private CreateMessageDto createMessageDto( + final ChatMessageDataDto messageData, + final Long userId + ) { + final CreateMessageRequest request = new CreateMessageRequest(messageData.receiverId(), messageData.contents()); return CreateMessageDto.of(userId, messageData.chatRoomId(), request); } @@ -119,8 +141,8 @@ private void sendNotificationIfReceiverNotInSession( final String profileImageAbsoluteUrl = String.valueOf(sessionAttribute.baseUrl()); messageNotificationEventPublisher.publishEvent(new MessageNotificationEvent( message, - profileImageAbsoluteUrl - )); + profileImageAbsoluteUrl) + ); } } @@ -142,18 +164,22 @@ private List createSendMessages( return sendMessageDtos; } - private TextMessage createTextMessage( - final MessageDto messageDto - ) throws JsonProcessingException { - final HandleMessageResponse handleMessageResponse = new HandleMessageResponse(SendMessageStatus.SUCCESS, List.of(messageDto)); + private boolean isMyMessage( + final WebSocketSession session, + final Long writerId + ) { + final long userId = Long.parseLong(String.valueOf(session.getAttributes().get("userId"))); - return new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)); + return writerId.equals(userId); } - private boolean isMyMessage(final WebSocketSession session, final Long writerId) { - final long userId = Long.parseLong(String.valueOf(session.getAttributes().get("userId"))); + private TextMessage createTextMessage(final MessageDto messageDto) throws JsonProcessingException { + final HandleMessageResponse handleMessageResponse = new HandleMessageResponse( + SendMessageStatus.SUCCESS, + List.of(messageDto) + ); - return writerId.equals(userId); + return new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)); } private void updateReadMessageLog( diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java index a1fc31506..f348e2720 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java @@ -53,17 +53,17 @@ public class ChatWebSocketHandleTextMessageProviderTestFixture { @BeforeEach void setUpFixture() { 발신자 = User.builder() - .name("발신자") - .profileImage(new ProfileImage("upload.png", "store.png")) - .reliability(new Reliability(4.7d)) - .oauthId("12345") - .build(); + .name("발신자") + .profileImage(new ProfileImage("upload.png", "store.png")) + .reliability(new Reliability(4.7d)) + .oauthId("12345") + .build(); 수신자 = User.builder() - .name("수신자") - .profileImage(new ProfileImage("upload.png", "store.png")) - .reliability(new Reliability(4.7d)) - .oauthId("12346") - .build(); + .name("수신자") + .profileImage(new ProfileImage("upload.png", "store.png")) + .reliability(new Reliability(4.7d)) + .oauthId("12346") + .build(); userRepository.save(발신자); userRepository.save(수신자); @@ -73,13 +73,13 @@ void setUpFixture() { categoryRepository.save(전자기기); final Auction 경매 = Auction.builder() - .title("경매") - .seller(수신자) - .description("description") - .bidUnit(new BidUnit(1_000)) - .startPrice(new Price(10_000)) - .closingTime(LocalDateTime.now().plusDays(3L)) - .build(); + .title("경매") + .seller(수신자) + .description("description") + .bidUnit(new BidUnit(1_000)) + .startPrice(new Price(10_000)) + .closingTime(LocalDateTime.now().plusDays(3L)) + .build(); auctionRepository.save(경매); 채팅방 = new ChatRoom(경매, 발신자); @@ -94,9 +94,7 @@ void setUpFixture() { "receiverId", String.valueOf(수신자.getId()), "contents", "메시지 내용" ); - 잘못된_메시지_전송_데이터 = Map.of( - "type", "wrong message type" - ); + 잘못된_메시지_전송_데이터 = Map.of("type", "wrong message type"); 메시지_로그_생성_이벤트 = new CreateReadMessageLogEvent(채팅방); } From 90fea1422252ed5094dcae49208ac2afa6c521d4 Mon Sep 17 00:00:00 2001 From: swonny Date: Mon, 15 Apr 2024 22:53:43 +0900 Subject: [PATCH 10/24] =?UTF-8?q?refactor:=20Ping=EA=B3=BC=20Chat=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EB=B3=84=20provider=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/handler/ChatHandleTypeProvider.java | 146 ++++++++++++++++ .../ChatHandleTypeProviderComposite.java | 23 +++ ...hatWebSocketHandleTextMessageProvider.java | 160 +----------------- .../chat/handler/PingHandleTypeProvider.java | 88 ++++++++++ .../chat/handler/TypeHandleProvider.java | 16 ++ ...andleTextMessageProviderCompositeTest.java | 3 - 6 files changed, 277 insertions(+), 159 deletions(-) create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProvider.java create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProviderComposite.java create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandleTypeProvider.java create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/TypeHandleProvider.java diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProvider.java new file mode 100644 index 000000000..b29dcbe12 --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProvider.java @@ -0,0 +1,146 @@ +package com.ddang.ddang.chat.handler; + +import com.ddang.ddang.chat.application.MessageService; +import com.ddang.ddang.chat.application.dto.CreateMessageDto; +import com.ddang.ddang.chat.application.event.MessageNotificationEvent; +import com.ddang.ddang.chat.application.event.UpdateReadMessageLogEvent; +import com.ddang.ddang.chat.domain.Message; +import com.ddang.ddang.chat.domain.WebSocketChatSessions; +import com.ddang.ddang.chat.handler.dto.ChatMessageDataDto; +import com.ddang.ddang.chat.handler.dto.HandleMessageResponse; +import com.ddang.ddang.chat.handler.dto.MessageDto; +import com.ddang.ddang.chat.handler.dto.SendMessageStatus; +import com.ddang.ddang.chat.presentation.dto.request.CreateMessageRequest; +import com.ddang.ddang.websocket.handler.dto.ChattingType; +import com.ddang.ddang.websocket.handler.dto.SendMessageDto; +import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Component +@RequiredArgsConstructor +public class ChatHandleTypeProvider implements TypeHandleProvider { + + private final WebSocketChatSessions sessions; + private final ObjectMapper objectMapper; + private final MessageService messageService; + private final ApplicationEventPublisher messageLogEventPublisher; + private final ApplicationEventPublisher messageNotificationEventPublisher; + + @Override + public ChattingType supportsChatType() { + return ChattingType.MESSAGE; + } + + @Override + public List createResponse( + final WebSocketSession session, + final Map data + ) throws JsonProcessingException { + final SessionAttributeDto sessionAttributes = getSessionAttributes(session); + + return createSendMessageResponse(data, sessionAttributes); + } + + + private SessionAttributeDto getSessionAttributes(final WebSocketSession session) { + final Map attributes = session.getAttributes(); + + return objectMapper.convertValue(attributes, SessionAttributeDto.class); + } + + private List createSendMessageResponse( + final Map data, + final SessionAttributeDto sessionAttribute + ) throws JsonProcessingException { + final Long writerId = sessionAttribute.userId(); + final ChatMessageDataDto messageData = objectMapper.convertValue(data, ChatMessageDataDto.class); + final CreateMessageDto createMessageDto = createMessageDto(messageData, writerId); + final Message message = messageService.create(createMessageDto); + sendNotificationIfReceiverNotInSession(message, sessionAttribute); + + return createSendMessages(message, writerId, createMessageDto.chatRoomId()); + } + + private void sendNotificationIfReceiverNotInSession( + final Message message, + final SessionAttributeDto sessionAttribute + ) { + if (!sessions.containsByUserId(message.getChatRoom().getId(), message.getReceiver().getId())) { + final String profileImageAbsoluteUrl = String.valueOf(sessionAttribute.baseUrl()); + messageNotificationEventPublisher.publishEvent(new MessageNotificationEvent( + message, + profileImageAbsoluteUrl) + ); + } + } + + private List createSendMessages( + final Message message, + final Long writerId, + final Long chatRoomId + ) throws JsonProcessingException { + final Set groupSessions = sessions.getSessionsByChatRoomId(message.getChatRoom().getId()); + + final List sendMessageDtos = new ArrayList<>(); + for (final WebSocketSession currentSession : groupSessions) { + final MessageDto messageDto = MessageDto.of(message, isMyMessage(currentSession, writerId)); + final TextMessage textMessage = createTextMessage(messageDto); + sendMessageDtos.add(new SendMessageDto(currentSession, textMessage)); + updateReadMessageLog(currentSession, chatRoomId, message); + } + + return sendMessageDtos; + } + + private CreateMessageDto createMessageDto( + final ChatMessageDataDto messageData, + final Long userId + ) { + final CreateMessageRequest request = new CreateMessageRequest(messageData.receiverId(), messageData.contents()); + + return CreateMessageDto.of(userId, messageData.chatRoomId(), request); + } + + private boolean isMyMessage( + final WebSocketSession session, + final Long writerId + ) { + final long userId = Long.parseLong(String.valueOf(session.getAttributes().get("userId"))); + + return writerId.equals(userId); + } + + private TextMessage createTextMessage(final MessageDto messageDto) throws JsonProcessingException { + final HandleMessageResponse handleMessageResponse = new HandleMessageResponse( + SendMessageStatus.SUCCESS, + List.of(messageDto) + ); + + return new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)); + } + + private void updateReadMessageLog( + final WebSocketSession currentSession, + final Long chatRoomId, + final Message message + ) { + final SessionAttributeDto sessionAttributes = getSessionAttributes(currentSession); + final UpdateReadMessageLogEvent updateReadMessageLogEvent = new UpdateReadMessageLogEvent( + sessionAttributes.userId(), + chatRoomId, + message.getId() + ); + messageLogEventPublisher.publishEvent(updateReadMessageLogEvent); + } +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProviderComposite.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProviderComposite.java new file mode 100644 index 000000000..93ee34434 --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProviderComposite.java @@ -0,0 +1,23 @@ +package com.ddang.ddang.chat.handler; + +import com.ddang.ddang.websocket.handler.dto.ChattingType; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +@Component +public class ChatHandleTypeProviderComposite { + + private final Map mappings; + + public ChatHandleTypeProviderComposite(final Set providers) { + this.mappings = providers.stream() + .collect(Collectors.toMap(TypeHandleProvider::supportsChatType, provider -> provider)); + } + + public TypeHandleProvider findProvider(final ChattingType chattingType) { + return mappings.get(chattingType); + } +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index 8ad61f81a..ede73e86c 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -1,36 +1,17 @@ package com.ddang.ddang.chat.handler; -import com.ddang.ddang.chat.application.MessageService; -import com.ddang.ddang.chat.application.dto.CreateMessageDto; -import com.ddang.ddang.chat.application.dto.ReadMessageDto; -import com.ddang.ddang.chat.application.event.MessageNotificationEvent; -import com.ddang.ddang.chat.application.event.UpdateReadMessageLogEvent; -import com.ddang.ddang.chat.domain.Message; import com.ddang.ddang.chat.domain.WebSocketChatSessions; -import com.ddang.ddang.chat.handler.dto.ChatMessageDataDto; -import com.ddang.ddang.chat.handler.dto.ChatPingDataDto; -import com.ddang.ddang.chat.handler.dto.HandleMessageResponse; -import com.ddang.ddang.chat.handler.dto.MessageDto; -import com.ddang.ddang.chat.handler.dto.SendMessageStatus; -import com.ddang.ddang.chat.presentation.dto.request.CreateMessageRequest; -import com.ddang.ddang.chat.presentation.dto.request.ReadMessageRequest; import com.ddang.ddang.websocket.handler.WebSocketHandleTextMessageProvider; import com.ddang.ddang.websocket.handler.dto.ChattingType; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; -import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; import com.ddang.ddang.websocket.handler.dto.TextMessageType; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; -import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; -import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; @Component @RequiredArgsConstructor @@ -40,10 +21,7 @@ public class ChatWebSocketHandleTextMessageProvider implements WebSocketHandleTe private static final String CHATTTING_TYPE_KEY = "type"; private final WebSocketChatSessions sessions; - private final ObjectMapper objectMapper; - private final MessageService messageService; - private final ApplicationEventPublisher messageNotificationEventPublisher; - private final ApplicationEventPublisher messageLogEventPublisher; + private final ChatHandleTypeProviderComposite chatHandleTypeProviderComposite; @Override public TextMessageType supportTextMessageType() { @@ -52,150 +30,20 @@ public TextMessageType supportTextMessageType() { @Override public List handleCreateSendMessage( - final WebSocketSession session, - final Map data + final WebSocketSession session, final Map data ) throws JsonProcessingException { - final SessionAttributeDto sessionAttribute = getSessionAttributes(session); final long chatRoomId = getChatRoomId(data); sessions.add(session, chatRoomId); final ChattingType type = ChattingType.findValue(data.get(CHATTTING_TYPE_KEY)); - if (ChattingType.PING == type) { - return createPingResponse(sessionAttribute, data, session); - } - return createSendMessageResponse(data, sessionAttribute); - } - - private SessionAttributeDto getSessionAttributes(final WebSocketSession session) { - final Map attributes = session.getAttributes(); - - return objectMapper.convertValue(attributes, SessionAttributeDto.class); + final TypeHandleProvider provider = chatHandleTypeProviderComposite.findProvider(type); + return provider.createResponse(session, data); } private long getChatRoomId(final Map data) { return Long.parseLong(data.get(CHATROOM_ID_KEY)); } - private List createPingResponse( - final SessionAttributeDto sessionAttribute, - final Map data, - final WebSocketSession userSession - ) throws JsonProcessingException { - final ChatPingDataDto pingData = objectMapper.convertValue(data, ChatPingDataDto.class); - final ReadMessageRequest readMessageRequest = new ReadMessageRequest( - sessionAttribute.userId(), - pingData.chatRoomId(), - pingData.lastMessageId() - ); - final List readMessageDtos = messageService.readAllByLastMessageId(readMessageRequest); - - final List messageDtos = convertToMessageDto(readMessageDtos, userSession); - final HandleMessageResponse handleMessageResponse = new HandleMessageResponse( - SendMessageStatus.SUCCESS, - messageDtos - ); - return List.of(new SendMessageDto( - userSession, - new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)) - )); - } - - private List convertToMessageDto( - final List readMessageDtos, - final WebSocketSession session - ) { - return readMessageDtos.stream() - .map(readMessageDto -> MessageDto.of(readMessageDto, - isMyMessage(session, readMessageDto.writerId()) - )) - .toList(); - } - - private List createSendMessageResponse( - final Map data, - final SessionAttributeDto sessionAttribute - ) throws JsonProcessingException { - final Long writerId = sessionAttribute.userId(); - final ChatMessageDataDto messageData = objectMapper.convertValue(data, ChatMessageDataDto.class); - final CreateMessageDto createMessageDto = createMessageDto(messageData, writerId); - final Message message = messageService.create(createMessageDto); - sendNotificationIfReceiverNotInSession(message, sessionAttribute); - - return createSendMessages(message, writerId, createMessageDto.chatRoomId()); - } - - private CreateMessageDto createMessageDto( - final ChatMessageDataDto messageData, - final Long userId - ) { - final CreateMessageRequest request = new CreateMessageRequest(messageData.receiverId(), messageData.contents()); - - return CreateMessageDto.of(userId, messageData.chatRoomId(), request); - } - - private void sendNotificationIfReceiverNotInSession( - final Message message, - final SessionAttributeDto sessionAttribute - ) { - if (!sessions.containsByUserId(message.getChatRoom().getId(), message.getReceiver().getId())) { - final String profileImageAbsoluteUrl = String.valueOf(sessionAttribute.baseUrl()); - messageNotificationEventPublisher.publishEvent(new MessageNotificationEvent( - message, - profileImageAbsoluteUrl) - ); - } - } - - private List createSendMessages( - final Message message, - final Long writerId, - final Long chatRoomId - ) throws JsonProcessingException { - final Set groupSessions = sessions.getSessionsByChatRoomId(message.getChatRoom().getId()); - - final List sendMessageDtos = new ArrayList<>(); - for (final WebSocketSession currentSession : groupSessions) { - final MessageDto messageDto = MessageDto.of(message, isMyMessage(currentSession, writerId)); - final TextMessage textMessage = createTextMessage(messageDto); - sendMessageDtos.add(new SendMessageDto(currentSession, textMessage)); - updateReadMessageLog(currentSession, chatRoomId, message); - } - - return sendMessageDtos; - } - - private boolean isMyMessage( - final WebSocketSession session, - final Long writerId - ) { - final long userId = Long.parseLong(String.valueOf(session.getAttributes().get("userId"))); - - return writerId.equals(userId); - } - - private TextMessage createTextMessage(final MessageDto messageDto) throws JsonProcessingException { - final HandleMessageResponse handleMessageResponse = new HandleMessageResponse( - SendMessageStatus.SUCCESS, - List.of(messageDto) - ); - - return new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)); - } - - private void updateReadMessageLog( - final WebSocketSession currentSession, - final Long chatRoomId, - final Message message - ) { - final SessionAttributeDto sessionAttributes = getSessionAttributes(currentSession); - final UpdateReadMessageLogEvent updateReadMessageLogEvent = new UpdateReadMessageLogEvent( - sessionAttributes.userId(), - chatRoomId, - message.getId() - ); - messageLogEventPublisher.publishEvent(updateReadMessageLogEvent); - } - @Override public void remove(final WebSocketSession session) { sessions.remove(session); diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandleTypeProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandleTypeProvider.java new file mode 100644 index 000000000..9425652b9 --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandleTypeProvider.java @@ -0,0 +1,88 @@ +package com.ddang.ddang.chat.handler; + +import com.ddang.ddang.chat.application.MessageService; +import com.ddang.ddang.chat.application.dto.ReadMessageDto; +import com.ddang.ddang.chat.handler.dto.ChatPingDataDto; +import com.ddang.ddang.chat.handler.dto.HandleMessageResponse; +import com.ddang.ddang.chat.handler.dto.MessageDto; +import com.ddang.ddang.chat.handler.dto.SendMessageStatus; +import com.ddang.ddang.chat.presentation.dto.request.ReadMessageRequest; +import com.ddang.ddang.websocket.handler.dto.ChattingType; +import com.ddang.ddang.websocket.handler.dto.SendMessageDto; +import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.util.List; +import java.util.Map; + +@Component +@RequiredArgsConstructor +public class PingHandleTypeProvider implements TypeHandleProvider { + + private final ObjectMapper objectMapper; + private final MessageService messageService; + + @Override + public ChattingType supportsChatType() { + return ChattingType.PING; + } + + // TODO: 2024/04/15 예외 처리 + @Override + public List createResponse( + final WebSocketSession session, final Map data + ) throws JsonProcessingException { + final SessionAttributeDto sessionAttribute = getSessionAttributes(session); + + return createPingResponse(sessionAttribute, data, session); + } + + private SessionAttributeDto getSessionAttributes(final WebSocketSession session) { + final Map attributes = session.getAttributes(); + + return objectMapper.convertValue(attributes, SessionAttributeDto.class); + } + + private List createPingResponse( + final SessionAttributeDto sessionAttribute, final Map data, + final WebSocketSession userSession + ) throws JsonProcessingException { + final ChatPingDataDto pingData = objectMapper.convertValue(data, ChatPingDataDto.class); + final ReadMessageRequest readMessageRequest = new ReadMessageRequest(sessionAttribute.userId(), + pingData.chatRoomId(), + pingData.lastMessageId() + ); + final List readMessageDtos = messageService.readAllByLastMessageId(readMessageRequest); + + final List messageDtos = convertToMessageDto(readMessageDtos, userSession); + final HandleMessageResponse handleMessageResponse = new HandleMessageResponse(SendMessageStatus.SUCCESS, + messageDtos + ); + return List.of(new SendMessageDto(userSession, + new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)) + )); + } + + private List convertToMessageDto( + final List readMessageDtos, final WebSocketSession session + ) { + return readMessageDtos.stream() + .map(readMessageDto -> MessageDto.of(readMessageDto, + isMyMessage(session, readMessageDto.writerId()) + )) + .toList(); + } + + private boolean isMyMessage( + final WebSocketSession session, final Long writerId + ) { + final long userId = Long.parseLong(String.valueOf(session.getAttributes().get("userId"))); + + return writerId.equals(userId); + } +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/TypeHandleProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/TypeHandleProvider.java new file mode 100644 index 000000000..574348f0a --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/TypeHandleProvider.java @@ -0,0 +1,16 @@ +package com.ddang.ddang.chat.handler; + +import com.ddang.ddang.websocket.handler.dto.ChattingType; +import com.ddang.ddang.websocket.handler.dto.SendMessageDto; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.springframework.web.socket.WebSocketSession; + +import java.util.List; +import java.util.Map; + +public interface TypeHandleProvider { + + List createResponse(final WebSocketSession session, final Map data) throws JsonProcessingException; + + ChattingType supportsChatType(); +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandleTextMessageProviderCompositeTest.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandleTextMessageProviderCompositeTest.java index bde1854a7..9d854509d 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandleTextMessageProviderCompositeTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandleTextMessageProviderCompositeTest.java @@ -20,9 +20,6 @@ class WebSocketHandleTextMessageProviderCompositeTest { void 지원하는_웹소켓_메시지_타입을_전달하면_해당_웹소켓_메시지_핸들러_provider를_반환한다() { // given final ChatWebSocketHandleTextMessageProvider provider = new ChatWebSocketHandleTextMessageProvider( - null, - null, - null, null, null ); From 909d028800a5fe6e12d1bf95b9680eb060657416 Mon Sep 17 00:00:00 2001 From: swonny Date: Mon, 15 Apr 2024 23:04:40 +0900 Subject: [PATCH 11/24] =?UTF-8?q?refactor:=20provider=EB=AA=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ndleProvider.java => ChatHandleProvider.java} | 6 +++--- .../handler/ChatHandleTypeProviderComposite.java | 12 ++++++------ .../ChatWebSocketHandleTextMessageProvider.java | 16 +++++++++------- ...TypeProvider.java => MessageTypeHandler.java} | 8 ++++---- ...gHandleTypeProvider.java => PingHandler.java} | 8 ++++---- .../{ChattingType.java => ChatMessageType.java} | 8 ++++---- ...ingTypeTest.java => ChatMessageTypeTest.java} | 8 ++++---- 7 files changed, 34 insertions(+), 32 deletions(-) rename backend/ddang/src/main/java/com/ddang/ddang/chat/handler/{TypeHandleProvider.java => ChatHandleProvider.java} (74%) rename backend/ddang/src/main/java/com/ddang/ddang/chat/handler/{ChatHandleTypeProvider.java => MessageTypeHandler.java} (96%) rename backend/ddang/src/main/java/com/ddang/ddang/chat/handler/{PingHandleTypeProvider.java => PingHandler.java} (94%) rename backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/{ChattingType.java => ChatMessageType.java} (67%) rename backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/{ChattingTypeTest.java => ChatMessageTypeTest.java} (68%) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/TypeHandleProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleProvider.java similarity index 74% rename from backend/ddang/src/main/java/com/ddang/ddang/chat/handler/TypeHandleProvider.java rename to backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleProvider.java index 574348f0a..7ee3cef96 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/TypeHandleProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleProvider.java @@ -1,6 +1,6 @@ package com.ddang.ddang.chat.handler; -import com.ddang.ddang.websocket.handler.dto.ChattingType; +import com.ddang.ddang.websocket.handler.dto.ChatMessageType; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; import com.fasterxml.jackson.core.JsonProcessingException; import org.springframework.web.socket.WebSocketSession; @@ -8,9 +8,9 @@ import java.util.List; import java.util.Map; -public interface TypeHandleProvider { +public interface ChatHandleProvider { List createResponse(final WebSocketSession session, final Map data) throws JsonProcessingException; - ChattingType supportsChatType(); + ChatMessageType supportsChatType(); } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProviderComposite.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProviderComposite.java index 93ee34434..443a9c4d0 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProviderComposite.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProviderComposite.java @@ -1,6 +1,6 @@ package com.ddang.ddang.chat.handler; -import com.ddang.ddang.websocket.handler.dto.ChattingType; +import com.ddang.ddang.websocket.handler.dto.ChatMessageType; import org.springframework.stereotype.Component; import java.util.Map; @@ -10,14 +10,14 @@ @Component public class ChatHandleTypeProviderComposite { - private final Map mappings; + private final Map mappings; - public ChatHandleTypeProviderComposite(final Set providers) { + public ChatHandleTypeProviderComposite(final Set providers) { this.mappings = providers.stream() - .collect(Collectors.toMap(TypeHandleProvider::supportsChatType, provider -> provider)); + .collect(Collectors.toMap(ChatHandleProvider::supportsChatType, provider -> provider)); } - public TypeHandleProvider findProvider(final ChattingType chattingType) { - return mappings.get(chattingType); + public ChatHandleProvider findProvider(final ChatMessageType chatMessageType) { + return mappings.get(chatMessageType); } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index ede73e86c..225820fd2 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -2,7 +2,7 @@ import com.ddang.ddang.chat.domain.WebSocketChatSessions; import com.ddang.ddang.websocket.handler.WebSocketHandleTextMessageProvider; -import com.ddang.ddang.websocket.handler.dto.ChattingType; +import com.ddang.ddang.websocket.handler.dto.ChatMessageType; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; import com.ddang.ddang.websocket.handler.dto.TextMessageType; import com.fasterxml.jackson.core.JsonProcessingException; @@ -18,7 +18,7 @@ public class ChatWebSocketHandleTextMessageProvider implements WebSocketHandleTextMessageProvider { private static final String CHATROOM_ID_KEY = "chatRoomId"; - private static final String CHATTTING_TYPE_KEY = "type"; + private static final String TYPE_KEY = "type"; private final WebSocketChatSessions sessions; private final ChatHandleTypeProviderComposite chatHandleTypeProviderComposite; @@ -30,14 +30,16 @@ public TextMessageType supportTextMessageType() { @Override public List handleCreateSendMessage( - final WebSocketSession session, final Map data + final WebSocketSession session, + final Map chatMessageData ) throws JsonProcessingException { - final long chatRoomId = getChatRoomId(data); + final long chatRoomId = getChatRoomId(chatMessageData); sessions.add(session, chatRoomId); - final ChattingType type = ChattingType.findValue(data.get(CHATTTING_TYPE_KEY)); - final TypeHandleProvider provider = chatHandleTypeProviderComposite.findProvider(type); - return provider.createResponse(session, data); + final ChatMessageType type = ChatMessageType.findMessageType(chatMessageData.get(TYPE_KEY)); + final ChatHandleProvider provider = chatHandleTypeProviderComposite.findProvider(type); + + return provider.createResponse(session, chatMessageData); } private long getChatRoomId(final Map data) { diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java similarity index 96% rename from backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProvider.java rename to backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java index b29dcbe12..20d5d8302 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleTypeProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java @@ -11,7 +11,7 @@ import com.ddang.ddang.chat.handler.dto.MessageDto; import com.ddang.ddang.chat.handler.dto.SendMessageStatus; import com.ddang.ddang.chat.presentation.dto.request.CreateMessageRequest; -import com.ddang.ddang.websocket.handler.dto.ChattingType; +import com.ddang.ddang.websocket.handler.dto.ChatMessageType; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; import com.fasterxml.jackson.core.JsonProcessingException; @@ -29,7 +29,7 @@ @Component @RequiredArgsConstructor -public class ChatHandleTypeProvider implements TypeHandleProvider { +public class MessageTypeHandler implements ChatHandleProvider { private final WebSocketChatSessions sessions; private final ObjectMapper objectMapper; @@ -38,8 +38,8 @@ public class ChatHandleTypeProvider implements TypeHandleProvider { private final ApplicationEventPublisher messageNotificationEventPublisher; @Override - public ChattingType supportsChatType() { - return ChattingType.MESSAGE; + public ChatMessageType supportsChatType() { + return ChatMessageType.MESSAGE; } @Override diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandleTypeProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandler.java similarity index 94% rename from backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandleTypeProvider.java rename to backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandler.java index 9425652b9..a64d6cd20 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandleTypeProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandler.java @@ -7,7 +7,7 @@ import com.ddang.ddang.chat.handler.dto.MessageDto; import com.ddang.ddang.chat.handler.dto.SendMessageStatus; import com.ddang.ddang.chat.presentation.dto.request.ReadMessageRequest; -import com.ddang.ddang.websocket.handler.dto.ChattingType; +import com.ddang.ddang.websocket.handler.dto.ChatMessageType; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; import com.fasterxml.jackson.core.JsonProcessingException; @@ -22,14 +22,14 @@ @Component @RequiredArgsConstructor -public class PingHandleTypeProvider implements TypeHandleProvider { +public class PingHandler implements ChatHandleProvider { private final ObjectMapper objectMapper; private final MessageService messageService; @Override - public ChattingType supportsChatType() { - return ChattingType.PING; + public ChatMessageType supportsChatType() { + return ChatMessageType.PING; } // TODO: 2024/04/15 예외 처리 diff --git a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChatMessageType.java similarity index 67% rename from backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java rename to backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChatMessageType.java index 8a8e7a361..5e2689c5d 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChattingType.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChatMessageType.java @@ -2,7 +2,7 @@ import java.util.Arrays; -public enum ChattingType { +public enum ChatMessageType { MESSAGE("message"), PING("ping"), @@ -10,12 +10,12 @@ public enum ChattingType { private final String value; - ChattingType(final String value) { + ChatMessageType(final String value) { this.value = value; } - public static ChattingType findValue(final String value) { - return Arrays.stream(ChattingType.values()) + public static ChatMessageType findMessageType(final String value) { + return Arrays.stream(ChatMessageType.values()) .filter(chattingType -> chattingType.value.equals(value)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("잘못된 채팅 타입입니다.")); diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChatMessageTypeTest.java similarity index 68% rename from backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java rename to backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChatMessageTypeTest.java index db0da73ac..4db0b4c73 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChattingTypeTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChatMessageTypeTest.java @@ -8,7 +8,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; @SuppressWarnings("NonAsciiCharacters") -class ChattingTypeTest { +class ChatMessageTypeTest { @Test void 타입에_해당하는_enum을_반환한다() { @@ -16,10 +16,10 @@ class ChattingTypeTest { final Map data = Map.of("type", "message"); // when - final ChattingType actual = ChattingType.findValue(data.get("type")); + final ChatMessageType actual = ChatMessageType.findMessageType(data.get("type")); // then - assertThat(actual).isEqualTo(ChattingType.MESSAGE); + assertThat(actual).isEqualTo(ChatMessageType.MESSAGE); } @@ -29,6 +29,6 @@ class ChattingTypeTest { final Map data = Map.of("type", "wrong type"); // when & then - assertThatThrownBy(() -> ChattingType.findValue(data.get("type"))).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> ChatMessageType.findMessageType(data.get("type"))).isInstanceOf(IllegalArgumentException.class); } } From 2c5a43eb4348e79a1d3dcfea7118ad77063801fe Mon Sep 17 00:00:00 2001 From: swonny Date: Mon, 15 Apr 2024 23:26:44 +0900 Subject: [PATCH 12/24] =?UTF-8?q?fix:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=EC=97=90=20=EB=A7=9E=EC=B6=B0=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EB=B3=80=EC=88=98=EB=AA=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java index d624e782e..68d31dc20 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java @@ -2,5 +2,5 @@ import java.util.List; -public record HandleMessageResponse(SendMessageStatus sendMessageStatus, List messages) { +public record HandleMessageResponse(SendMessageStatus status, List messages) { } From 193c332f7c7309ae1c8b7cf431247d85ce8b5cc5 Mon Sep 17 00:00:00 2001 From: swonny Date: Mon, 15 Apr 2024 23:32:15 +0900 Subject: [PATCH 13/24] =?UTF-8?q?refactor:=20ping=20handler=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/handler/MessageTypeHandler.java | 6 +- ...{PingHandler.java => PingTypeHandler.java} | 63 +++++++++++-------- .../chat/handler/dto/ChatPingDataDto.java | 4 -- .../ddang/chat/handler/dto/ChatPingDto.java | 4 ++ .../handler/dto/HandleMessageResponse.java | 6 -- .../chat/handler/dto/SendChatResponse.java | 6 ++ 6 files changed, 50 insertions(+), 39 deletions(-) rename backend/ddang/src/main/java/com/ddang/ddang/chat/handler/{PingHandler.java => PingTypeHandler.java} (55%) delete mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDataDto.java create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDto.java delete mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendChatResponse.java diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java index 20d5d8302..394bd6d63 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java @@ -7,7 +7,7 @@ import com.ddang.ddang.chat.domain.Message; import com.ddang.ddang.chat.domain.WebSocketChatSessions; import com.ddang.ddang.chat.handler.dto.ChatMessageDataDto; -import com.ddang.ddang.chat.handler.dto.HandleMessageResponse; +import com.ddang.ddang.chat.handler.dto.SendChatResponse; import com.ddang.ddang.chat.handler.dto.MessageDto; import com.ddang.ddang.chat.handler.dto.SendMessageStatus; import com.ddang.ddang.chat.presentation.dto.request.CreateMessageRequest; @@ -122,12 +122,12 @@ private boolean isMyMessage( } private TextMessage createTextMessage(final MessageDto messageDto) throws JsonProcessingException { - final HandleMessageResponse handleMessageResponse = new HandleMessageResponse( + final SendChatResponse sendChatResponse = new SendChatResponse( SendMessageStatus.SUCCESS, List.of(messageDto) ); - return new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)); + return new TextMessage(objectMapper.writeValueAsString(sendChatResponse)); } private void updateReadMessageLog( diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandler.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingTypeHandler.java similarity index 55% rename from backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandler.java rename to backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingTypeHandler.java index a64d6cd20..fe24e04a3 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingHandler.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingTypeHandler.java @@ -2,8 +2,8 @@ import com.ddang.ddang.chat.application.MessageService; import com.ddang.ddang.chat.application.dto.ReadMessageDto; -import com.ddang.ddang.chat.handler.dto.ChatPingDataDto; -import com.ddang.ddang.chat.handler.dto.HandleMessageResponse; +import com.ddang.ddang.chat.handler.dto.ChatPingDto; +import com.ddang.ddang.chat.handler.dto.SendChatResponse; import com.ddang.ddang.chat.handler.dto.MessageDto; import com.ddang.ddang.chat.handler.dto.SendMessageStatus; import com.ddang.ddang.chat.presentation.dto.request.ReadMessageRequest; @@ -22,7 +22,7 @@ @Component @RequiredArgsConstructor -public class PingHandler implements ChatHandleProvider { +public class PingTypeHandler implements ChatHandleProvider { private final ObjectMapper objectMapper; private final MessageService messageService; @@ -32,44 +32,46 @@ public ChatMessageType supportsChatType() { return ChatMessageType.PING; } - // TODO: 2024/04/15 예외 처리 @Override public List createResponse( - final WebSocketSession session, final Map data + final WebSocketSession session, + final Map chatPingData ) throws JsonProcessingException { - final SessionAttributeDto sessionAttribute = getSessionAttributes(session); + final ReadMessageRequest readMessageRequest = createReadMessageRequest(session, chatPingData); + final List readMessageDtos = messageService.readAllByLastMessageId(readMessageRequest); + final SendChatResponse sendChatResponse = createSendChatResponse(readMessageDtos, session); + + return List.of(createSendMessageDto(session, sendChatResponse)); + } - return createPingResponse(sessionAttribute, data, session); + private ReadMessageRequest createReadMessageRequest( + final WebSocketSession session, + final Map chatPingData + ) { + final SessionAttributeDto sessionAttribute = convertToSessionAttributes(session); + final ChatPingDto pingDto = objectMapper.convertValue(chatPingData, ChatPingDto.class); + + return new ReadMessageRequest(sessionAttribute.userId(), pingDto.chatRoomId(), pingDto.lastMessageId()); } - private SessionAttributeDto getSessionAttributes(final WebSocketSession session) { + private SessionAttributeDto convertToSessionAttributes(final WebSocketSession session) { final Map attributes = session.getAttributes(); return objectMapper.convertValue(attributes, SessionAttributeDto.class); } - private List createPingResponse( - final SessionAttributeDto sessionAttribute, final Map data, - final WebSocketSession userSession - ) throws JsonProcessingException { - final ChatPingDataDto pingData = objectMapper.convertValue(data, ChatPingDataDto.class); - final ReadMessageRequest readMessageRequest = new ReadMessageRequest(sessionAttribute.userId(), - pingData.chatRoomId(), - pingData.lastMessageId() - ); - final List readMessageDtos = messageService.readAllByLastMessageId(readMessageRequest); + private SendChatResponse createSendChatResponse( + final List readMessageDtos, + final WebSocketSession session + ) { + final List messageDtos = convertToMessageDto(readMessageDtos, session); - final List messageDtos = convertToMessageDto(readMessageDtos, userSession); - final HandleMessageResponse handleMessageResponse = new HandleMessageResponse(SendMessageStatus.SUCCESS, - messageDtos - ); - return List.of(new SendMessageDto(userSession, - new TextMessage(objectMapper.writeValueAsString(handleMessageResponse)) - )); + return new SendChatResponse(SendMessageStatus.SUCCESS, messageDtos); } private List convertToMessageDto( - final List readMessageDtos, final WebSocketSession session + final List readMessageDtos, + final WebSocketSession session ) { return readMessageDtos.stream() .map(readMessageDto -> MessageDto.of(readMessageDto, @@ -85,4 +87,13 @@ private boolean isMyMessage( return writerId.equals(userId); } + + private SendMessageDto createSendMessageDto( + final WebSocketSession session, + final SendChatResponse sendChatResponse + ) throws JsonProcessingException { + final TextMessage textMessage = new TextMessage(objectMapper.writeValueAsString(sendChatResponse)); + + return new SendMessageDto(session, textMessage); + } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDataDto.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDataDto.java deleted file mode 100644 index 845982b30..000000000 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDataDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.ddang.ddang.chat.handler.dto; - -public record ChatPingDataDto(Long chatRoomId, Long lastMessageId) { -} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDto.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDto.java new file mode 100644 index 000000000..8778550b3 --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/ChatPingDto.java @@ -0,0 +1,4 @@ +package com.ddang.ddang.chat.handler.dto; + +public record ChatPingDto(Long chatRoomId, Long lastMessageId) { +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java deleted file mode 100644 index 68d31dc20..000000000 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/HandleMessageResponse.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.ddang.ddang.chat.handler.dto; - -import java.util.List; - -public record HandleMessageResponse(SendMessageStatus status, List messages) { -} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendChatResponse.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendChatResponse.java new file mode 100644 index 000000000..a963247f9 --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/SendChatResponse.java @@ -0,0 +1,6 @@ +package com.ddang.ddang.chat.handler.dto; + +import java.util.List; + +public record SendChatResponse(SendMessageStatus status, List messages) { +} From 514e0ac7956b6172052510f8f58da59af16808e7 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 16 Apr 2024 01:09:23 +0900 Subject: [PATCH 14/24] =?UTF-8?q?refactor:=20ping=EA=B3=BC=20message=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=EC=8B=9C=20=EC=82=AC=EC=9A=A9=EB=90=98?= =?UTF-8?q?=EB=8A=94=20data=EB=A5=BC=20Dto=EB=A1=9C=20=EB=B3=80=ED=99=98?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/domain/WebSocketChatSessions.java | 7 +- .../ddang/chat/domain/WebSocketSessions.java | 7 ++ .../chat/handler/ChatHandleProvider.java | 7 +- ...hatWebSocketHandleTextMessageProvider.java | 11 ++- .../chat/handler/MessageTypeHandler.java | 79 +++++++++---------- .../ddang/chat/handler/PingTypeHandler.java | 56 ++++++------- .../chat/handler/dto/MessageDataDto.java | 18 +++++ .../ddang/chat/handler/dto/PingDataDto.java | 15 ++++ ...ebSocketHandleTextMessageProviderTest.java | 30 ++++--- ...tHandleTextMessageProviderTestFixture.java | 16 +++- ...andleTextMessageProviderCompositeTest.java | 1 + 11 files changed, 154 insertions(+), 93 deletions(-) create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/MessageDataDto.java create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/PingDataDto.java diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketChatSessions.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketChatSessions.java index 196903d31..05d6bc2bf 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketChatSessions.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketChatSessions.java @@ -5,7 +5,6 @@ import org.springframework.web.socket.WebSocketSession; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import static com.ddang.ddang.chat.domain.WebSocketSessions.CHAT_ROOM_ID_KEY; @@ -22,10 +21,8 @@ public void add(final WebSocketSession session, final Long chatRoomId) { webSocketSessions.putIfAbsent(session, chatRoomId); } - public Set getSessionsByChatRoomId(final Long chatRoomId) { - final WebSocketSessions webSocketSessions = chatRoomSessions.get(chatRoomId); - - return webSocketSessions.getSessions(); + public WebSocketSessions findSessionsByChatRoomId(final Long chatRoomId) { + return chatRoomSessions.get(chatRoomId); } public boolean containsByUserId(final Long chatRoomId, final Long userId) { diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java index 7619377a5..4a3fb23a7 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java @@ -4,6 +4,7 @@ import org.springframework.web.socket.WebSocketSession; import java.util.Collections; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -27,6 +28,12 @@ public boolean contains(final Long userId) { .anyMatch(session -> session.getAttributes().get(USER_ID_KEY) == userId); } + public Optional findByUserId(final long userId) { + return sessions.stream() + .filter(session -> session.getAttributes().get(USER_ID_KEY).equals(userId)) + .findFirst(); + } + public void remove(final WebSocketSession session) { sessions.remove(session); } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleProvider.java index 7ee3cef96..3cff1686a 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatHandleProvider.java @@ -2,15 +2,18 @@ import com.ddang.ddang.websocket.handler.dto.ChatMessageType; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; +import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; import com.fasterxml.jackson.core.JsonProcessingException; -import org.springframework.web.socket.WebSocketSession; import java.util.List; import java.util.Map; public interface ChatHandleProvider { - List createResponse(final WebSocketSession session, final Map data) throws JsonProcessingException; + List createResponse( + final SessionAttributeDto sessionAttributeDto, + final Map data + ) throws JsonProcessingException; ChatMessageType supportsChatType(); } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index 225820fd2..922896220 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -4,8 +4,10 @@ import com.ddang.ddang.websocket.handler.WebSocketHandleTextMessageProvider; import com.ddang.ddang.websocket.handler.dto.ChatMessageType; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; +import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; import com.ddang.ddang.websocket.handler.dto.TextMessageType; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.web.socket.WebSocketSession; @@ -20,6 +22,7 @@ public class ChatWebSocketHandleTextMessageProvider implements WebSocketHandleTe private static final String CHATROOM_ID_KEY = "chatRoomId"; private static final String TYPE_KEY = "type"; + private final ObjectMapper objectMapper; private final WebSocketChatSessions sessions; private final ChatHandleTypeProviderComposite chatHandleTypeProviderComposite; @@ -39,7 +42,13 @@ public List handleCreateSendMessage( final ChatMessageType type = ChatMessageType.findMessageType(chatMessageData.get(TYPE_KEY)); final ChatHandleProvider provider = chatHandleTypeProviderComposite.findProvider(type); - return provider.createResponse(session, chatMessageData); + return provider.createResponse(convertToSessionAttributeDto(session), chatMessageData); + } + + private SessionAttributeDto convertToSessionAttributeDto(final WebSocketSession session) { + final Map attributes = session.getAttributes(); + + return objectMapper.convertValue(attributes, SessionAttributeDto.class); } private long getChatRoomId(final Map data) { diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java index 394bd6d63..58813632f 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java @@ -6,9 +6,11 @@ import com.ddang.ddang.chat.application.event.UpdateReadMessageLogEvent; import com.ddang.ddang.chat.domain.Message; import com.ddang.ddang.chat.domain.WebSocketChatSessions; +import com.ddang.ddang.chat.domain.WebSocketSessions; import com.ddang.ddang.chat.handler.dto.ChatMessageDataDto; -import com.ddang.ddang.chat.handler.dto.SendChatResponse; +import com.ddang.ddang.chat.handler.dto.MessageDataDto; import com.ddang.ddang.chat.handler.dto.MessageDto; +import com.ddang.ddang.chat.handler.dto.SendChatResponse; import com.ddang.ddang.chat.handler.dto.SendMessageStatus; import com.ddang.ddang.chat.presentation.dto.request.CreateMessageRequest; import com.ddang.ddang.websocket.handler.dto.ChatMessageType; @@ -25,7 +27,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; @Component @RequiredArgsConstructor @@ -44,32 +45,24 @@ public ChatMessageType supportsChatType() { @Override public List createResponse( - final WebSocketSession session, + final SessionAttributeDto sessionAttributeDto, final Map data ) throws JsonProcessingException { - final SessionAttributeDto sessionAttributes = getSessionAttributes(session); - - return createSendMessageResponse(data, sessionAttributes); - } + final Long writerId = sessionAttributeDto.userId(); + final MessageDataDto messageDataDto = MessageDataDto.from(data); + final Message message = createMessage(data, writerId); - private SessionAttributeDto getSessionAttributes(final WebSocketSession session) { - final Map attributes = session.getAttributes(); + sendNotificationIfReceiverNotInSession(message, sessionAttributeDto); - return objectMapper.convertValue(attributes, SessionAttributeDto.class); + return createSendMessages(message, writerId, messageDataDto.chatRoomId()); } - private List createSendMessageResponse( - final Map data, - final SessionAttributeDto sessionAttribute - ) throws JsonProcessingException { - final Long writerId = sessionAttribute.userId(); + private Message createMessage(final Map data, final long writerId) { final ChatMessageDataDto messageData = objectMapper.convertValue(data, ChatMessageDataDto.class); final CreateMessageDto createMessageDto = createMessageDto(messageData, writerId); - final Message message = messageService.create(createMessageDto); - sendNotificationIfReceiverNotInSession(message, sessionAttribute); - return createSendMessages(message, writerId, createMessageDto.chatRoomId()); + return messageService.create(createMessageDto); } private void sendNotificationIfReceiverNotInSession( @@ -80,8 +73,8 @@ private void sendNotificationIfReceiverNotInSession( final String profileImageAbsoluteUrl = String.valueOf(sessionAttribute.baseUrl()); messageNotificationEventPublisher.publishEvent(new MessageNotificationEvent( message, - profileImageAbsoluteUrl) - ); + profileImageAbsoluteUrl + )); } } @@ -90,10 +83,10 @@ private List createSendMessages( final Long writerId, final Long chatRoomId ) throws JsonProcessingException { - final Set groupSessions = sessions.getSessionsByChatRoomId(message.getChatRoom().getId()); + final WebSocketSessions groupSessions = sessions.findSessionsByChatRoomId(message.getChatRoom().getId()); final List sendMessageDtos = new ArrayList<>(); - for (final WebSocketSession currentSession : groupSessions) { + for (final WebSocketSession currentSession : groupSessions.getSessions()) { final MessageDto messageDto = MessageDto.of(message, isMyMessage(currentSession, writerId)); final TextMessage textMessage = createTextMessage(messageDto); sendMessageDtos.add(new SendMessageDto(currentSession, textMessage)); @@ -103,10 +96,27 @@ private List createSendMessages( return sendMessageDtos; } - private CreateMessageDto createMessageDto( - final ChatMessageDataDto messageData, - final Long userId + private void updateReadMessageLog( + final WebSocketSession currentSession, + final Long chatRoomId, + final Message message ) { + final SessionAttributeDto sessionAttributes = convertToSessionAttributeDto(currentSession); + final UpdateReadMessageLogEvent updateReadMessageLogEvent = new UpdateReadMessageLogEvent( + sessionAttributes.userId(), + chatRoomId, + message.getId() + ); + messageLogEventPublisher.publishEvent(updateReadMessageLogEvent); + } + + private SessionAttributeDto convertToSessionAttributeDto(final WebSocketSession session) { + final Map attributes = session.getAttributes(); + + return objectMapper.convertValue(attributes, SessionAttributeDto.class); + } + + private CreateMessageDto createMessageDto(final ChatMessageDataDto messageData, final Long userId) { final CreateMessageRequest request = new CreateMessageRequest(messageData.receiverId(), messageData.contents()); return CreateMessageDto.of(userId, messageData.chatRoomId(), request); @@ -122,25 +132,8 @@ private boolean isMyMessage( } private TextMessage createTextMessage(final MessageDto messageDto) throws JsonProcessingException { - final SendChatResponse sendChatResponse = new SendChatResponse( - SendMessageStatus.SUCCESS, - List.of(messageDto) - ); + final SendChatResponse sendChatResponse = new SendChatResponse(SendMessageStatus.SUCCESS, List.of(messageDto)); return new TextMessage(objectMapper.writeValueAsString(sendChatResponse)); } - - private void updateReadMessageLog( - final WebSocketSession currentSession, - final Long chatRoomId, - final Message message - ) { - final SessionAttributeDto sessionAttributes = getSessionAttributes(currentSession); - final UpdateReadMessageLogEvent updateReadMessageLogEvent = new UpdateReadMessageLogEvent( - sessionAttributes.userId(), - chatRoomId, - message.getId() - ); - messageLogEventPublisher.publishEvent(updateReadMessageLogEvent); - } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingTypeHandler.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingTypeHandler.java index fe24e04a3..fd91e1d4e 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingTypeHandler.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/PingTypeHandler.java @@ -2,9 +2,12 @@ import com.ddang.ddang.chat.application.MessageService; import com.ddang.ddang.chat.application.dto.ReadMessageDto; +import com.ddang.ddang.chat.domain.WebSocketChatSessions; +import com.ddang.ddang.chat.domain.WebSocketSessions; import com.ddang.ddang.chat.handler.dto.ChatPingDto; -import com.ddang.ddang.chat.handler.dto.SendChatResponse; import com.ddang.ddang.chat.handler.dto.MessageDto; +import com.ddang.ddang.chat.handler.dto.PingDataDto; +import com.ddang.ddang.chat.handler.dto.SendChatResponse; import com.ddang.ddang.chat.handler.dto.SendMessageStatus; import com.ddang.ddang.chat.presentation.dto.request.ReadMessageRequest; import com.ddang.ddang.websocket.handler.dto.ChatMessageType; @@ -19,11 +22,13 @@ import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; @Component @RequiredArgsConstructor public class PingTypeHandler implements ChatHandleProvider { + private final WebSocketChatSessions sessions; private final ObjectMapper objectMapper; private final MessageService messageService; @@ -34,35 +39,29 @@ public ChatMessageType supportsChatType() { @Override public List createResponse( - final WebSocketSession session, + final SessionAttributeDto sessionAttributeDto, final Map chatPingData ) throws JsonProcessingException { - final ReadMessageRequest readMessageRequest = createReadMessageRequest(session, chatPingData); + final PingDataDto pingDataDto = PingDataDto.from(chatPingData); + final ReadMessageRequest readMessageRequest = createReadMessageRequest(sessionAttributeDto, pingDataDto); final List readMessageDtos = messageService.readAllByLastMessageId(readMessageRequest); - final SendChatResponse sendChatResponse = createSendChatResponse(readMessageDtos, session); + final SendChatResponse sendChatResponse = createSendChatResponse(readMessageDtos, sessionAttributeDto); - return List.of(createSendMessageDto(session, sendChatResponse)); + return List.of(createSendMessageDto(sessionAttributeDto, pingDataDto, sendChatResponse)); } private ReadMessageRequest createReadMessageRequest( - final WebSocketSession session, - final Map chatPingData + final SessionAttributeDto sessionAttributeDto, + final PingDataDto chatPingData ) { - final SessionAttributeDto sessionAttribute = convertToSessionAttributes(session); final ChatPingDto pingDto = objectMapper.convertValue(chatPingData, ChatPingDto.class); - return new ReadMessageRequest(sessionAttribute.userId(), pingDto.chatRoomId(), pingDto.lastMessageId()); - } - - private SessionAttributeDto convertToSessionAttributes(final WebSocketSession session) { - final Map attributes = session.getAttributes(); - - return objectMapper.convertValue(attributes, SessionAttributeDto.class); + return new ReadMessageRequest(sessionAttributeDto.userId(), pingDto.chatRoomId(), pingDto.lastMessageId()); } private SendChatResponse createSendChatResponse( final List readMessageDtos, - final WebSocketSession session + final SessionAttributeDto session ) { final List messageDtos = convertToMessageDto(readMessageDtos, session); @@ -71,29 +70,32 @@ private SendChatResponse createSendChatResponse( private List convertToMessageDto( final List readMessageDtos, - final WebSocketSession session + final SessionAttributeDto sessionAttributeDto ) { return readMessageDtos.stream() - .map(readMessageDto -> MessageDto.of(readMessageDto, - isMyMessage(session, readMessageDto.writerId()) - )) - .toList(); + .map(readMessageDto -> MessageDto.of(readMessageDto, isMyMessage(sessionAttributeDto, + readMessageDto.writerId() + ))).toList(); } - private boolean isMyMessage( - final WebSocketSession session, final Long writerId - ) { - final long userId = Long.parseLong(String.valueOf(session.getAttributes().get("userId"))); + private boolean isMyMessage(final SessionAttributeDto session, final Long writerId) { + final long userId = session.userId(); return writerId.equals(userId); } private SendMessageDto createSendMessageDto( - final WebSocketSession session, + final SessionAttributeDto sessionAttributeDto, + final PingDataDto chatPingData, final SendChatResponse sendChatResponse ) throws JsonProcessingException { final TextMessage textMessage = new TextMessage(objectMapper.writeValueAsString(sendChatResponse)); + final WebSocketSessions sessions = this.sessions.findSessionsByChatRoomId(chatPingData.chatRoomId()); + final WebSocketSession userSession = sessions.findByUserId(sessionAttributeDto.userId()) + .orElseThrow(() -> new NoSuchElementException( + "웹소켓에 연결된 사용자가 존재하지 않습니다." + )); - return new SendMessageDto(session, textMessage); + return new SendMessageDto(userSession, textMessage); } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/MessageDataDto.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/MessageDataDto.java new file mode 100644 index 000000000..c4846904a --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/MessageDataDto.java @@ -0,0 +1,18 @@ +package com.ddang.ddang.chat.handler.dto; + +import java.util.Map; + +public record MessageDataDto(long chatRoomId, long receiverId, String contents) { + + private static final String CHAT_ROOM_ID_KEY = "chatRoomId"; + private static final String RECEIVER_ID_KEY = "receiverId"; + private static final String CONTENTS_ID_KEY = "contents"; + + public static MessageDataDto from(final Map data) { + return new MessageDataDto( + Long.parseLong(data.get(CHAT_ROOM_ID_KEY)), + Long.parseLong(data.get(RECEIVER_ID_KEY)), + data.get(CONTENTS_ID_KEY) + ); + } +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/PingDataDto.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/PingDataDto.java new file mode 100644 index 000000000..315cd199e --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/dto/PingDataDto.java @@ -0,0 +1,15 @@ +package com.ddang.ddang.chat.handler.dto; + +import java.util.Map; + +public record PingDataDto(long chatRoomId, long lastMessageId) { + + private static final String CHAT_ROOM_ID_KEY = "chatRoomId"; + private static final String LAST_MESSAGE_ID = "lastMessageId"; + + public static PingDataDto from(final Map chatPingData) { + return new PingDataDto(Long.parseLong(chatPingData.get(CHAT_ROOM_ID_KEY)), + Long.parseLong(chatPingData.get(LAST_MESSAGE_ID)) + ); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java index ef8873bf1..c9e10150d 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java @@ -25,7 +25,6 @@ import org.springframework.web.socket.WebSocketSession; import java.util.List; -import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -80,7 +79,9 @@ class ChatWebSocketHandleTextMessageProviderTest extends ChatWebSocketHandleText given(receiverSession.getAttributes()).willReturn(수신자_세션_attribute_정보); willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); willReturn(true).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); - willReturn(Set.of(writerSession, receiverSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + 채팅방에_해당하는_세션.putIfAbsent(writerSession, 채팅방.getId()); + 채팅방에_해당하는_세션.putIfAbsent(receiverSession, 채팅방.getId()); + willReturn(채팅방에_해당하는_세션).given(sessions).findSessionsByChatRoomId(채팅방.getId()); // when final List actual = provider.handleCreateSendMessage(writerSession, 메시지_전송_데이터); @@ -98,7 +99,9 @@ class ChatWebSocketHandleTextMessageProviderTest extends ChatWebSocketHandleText given(receiverSession.getAttributes()).willReturn(수신자_세션_attribute_정보); willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); willReturn(true).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); - willReturn(Set.of(writerSession, receiverSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + 채팅방에_해당하는_세션.putIfAbsent(writerSession, 채팅방.getId()); + 채팅방에_해당하는_세션.putIfAbsent(receiverSession, 채팅방.getId()); + willReturn(채팅방에_해당하는_세션).given(sessions).findSessionsByChatRoomId(채팅방.getId()); // when provider.handleCreateSendMessage(writerSession, 메시지_전송_데이터); @@ -116,7 +119,8 @@ class ChatWebSocketHandleTextMessageProviderTest extends ChatWebSocketHandleText given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); willReturn(false).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); - willReturn(Set.of(writerSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + 채팅방에_해당하는_세션.putIfAbsent(writerSession, 채팅방.getId()); + willReturn(채팅방에_해당하는_세션).given(sessions).findSessionsByChatRoomId(채팅방.getId()); // when provider.handleCreateSendMessage(writerSession, 메시지_전송_데이터); @@ -132,7 +136,8 @@ class ChatWebSocketHandleTextMessageProviderTest extends ChatWebSocketHandleText given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); willReturn(false).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); - willReturn(Set.of(writerSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + 채팅방에_해당하는_세션.putIfAbsent(writerSession, 채팅방.getId()); + willReturn(채팅방에_해당하는_세션).given(sessions).findSessionsByChatRoomId(채팅방.getId()); // when final List actual = provider.handleCreateSendMessage(writerSession, 메시지_전송_데이터); @@ -147,7 +152,8 @@ class ChatWebSocketHandleTextMessageProviderTest extends ChatWebSocketHandleText given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); willReturn(false).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); - willReturn(Set.of(writerSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + 채팅방에_해당하는_세션.putIfAbsent(writerSession, 채팅방.getId()); + willReturn(채팅방에_해당하는_세션).given(sessions).findSessionsByChatRoomId(채팅방.getId()); given(notificationService.send(any(CreateNotificationDto.class))).willReturn(NotificationStatus.SUCCESS); // when @@ -164,7 +170,8 @@ class ChatWebSocketHandleTextMessageProviderTest extends ChatWebSocketHandleText given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); willReturn(false).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); - willReturn(Set.of(writerSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + 채팅방에_해당하는_세션.putIfAbsent(writerSession, 채팅방.getId()); + willReturn(채팅방에_해당하는_세션).given(sessions).findSessionsByChatRoomId(채팅방.getId()); given(notificationService.send(any(CreateNotificationDto.class))).willReturn(NotificationStatus.FAIL); // when @@ -175,16 +182,17 @@ class ChatWebSocketHandleTextMessageProviderTest extends ChatWebSocketHandleText } @Test - void 잘못된_데이터_타입_전달시_예외가_발생한다() throws JsonProcessingException { + void 잘못된_데이터_타입_전달시_예외가_발생한다() { // given given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); willReturn(false).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); - willReturn(Set.of(writerSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + 채팅방에_해당하는_세션.putIfAbsent(writerSession, 채팅방.getId()); + willReturn(채팅방에_해당하는_세션).given(sessions).findSessionsByChatRoomId(채팅방.getId()); // when - assertThatThrownBy(() -> provider.handleCreateSendMessage(writerSession, 잘못된_메시지_전송_데이터)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> provider.handleCreateSendMessage(writerSession, 잘못된_메시지_전송_데이터)).isInstanceOf( + IllegalArgumentException.class); } @Test diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java index f348e2720..fc24c782c 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java @@ -9,6 +9,7 @@ import com.ddang.ddang.chat.application.LastReadMessageLogService; import com.ddang.ddang.chat.application.event.CreateReadMessageLogEvent; import com.ddang.ddang.chat.domain.ChatRoom; +import com.ddang.ddang.chat.domain.WebSocketSessions; import com.ddang.ddang.chat.domain.repository.ChatRoomRepository; import com.ddang.ddang.image.domain.ProfileImage; import com.ddang.ddang.user.domain.Reliability; @@ -47,6 +48,7 @@ public class ChatWebSocketHandleTextMessageProviderTestFixture { protected Map 수신자_세션_attribute_정보; protected Map 메시지_전송_데이터; protected Map 잘못된_메시지_전송_데이터; + protected WebSocketSessions 채팅방에_해당하는_세션; protected CreateReadMessageLogEvent 메시지_로그_생성_이벤트; @@ -89,14 +91,20 @@ void setUpFixture() { 발신자_세션_attribute_정보 = new HashMap<>(Map.of("userId", 발신자.getId(), "baseUrl", "/images")); 수신자_세션_attribute_정보 = new HashMap<>(Map.of("userId", 수신자.getId(), "baseUrl", "/images")); 메시지_전송_데이터 = Map.of( - "type", "message", - "chatRoomId", String.valueOf(채팅방.getId()), - "receiverId", String.valueOf(수신자.getId()), - "contents", "메시지 내용" + "type", + "message", + "chatRoomId", + String.valueOf(채팅방.getId()), + "receiverId", + String.valueOf(수신자.getId()), + "contents", + "메시지 내용" ); 잘못된_메시지_전송_데이터 = Map.of("type", "wrong message type"); 메시지_로그_생성_이벤트 = new CreateReadMessageLogEvent(채팅방); + + 채팅방에_해당하는_세션 = new WebSocketSessions(); } protected void 메시지_로그를_생성한다() { diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandleTextMessageProviderCompositeTest.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandleTextMessageProviderCompositeTest.java index 9d854509d..1a524a3e0 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandleTextMessageProviderCompositeTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandleTextMessageProviderCompositeTest.java @@ -20,6 +20,7 @@ class WebSocketHandleTextMessageProviderCompositeTest { void 지원하는_웹소켓_메시지_타입을_전달하면_해당_웹소켓_메시지_핸들러_provider를_반환한다() { // given final ChatWebSocketHandleTextMessageProvider provider = new ChatWebSocketHandleTextMessageProvider( + null, null, null ); From 0e56a7d834440e8cb73f8b22d32120dfeec03eb9 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 16 Apr 2024 02:13:22 +0900 Subject: [PATCH 15/24] =?UTF-8?q?test:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EB=94=94=EC=97=90=20=ED=95=B4=EB=8B=B9?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=9B=B9=EC=86=8C=EC=BC=93=EC=84=B8?= =?UTF-8?q?=EC=85=98=20=EB=B0=98=ED=99=98=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ddang/chat/domain/WebSocketSessionsTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/WebSocketSessionsTest.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/WebSocketSessionsTest.java index 15fe5846a..b3dc381c5 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/WebSocketSessionsTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/WebSocketSessionsTest.java @@ -8,6 +8,8 @@ import org.junit.jupiter.api.Test; import org.springframework.web.socket.WebSocketSession; +import java.util.Optional; + import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -84,6 +86,19 @@ void setUp() { assertThat(actual).isFalse(); } + @Test + void 유저아이디에_해당하는_웹소켓세션을_반환한다() { + // given + given(session.getAttributes()).willReturn(세션_attribute_정보); + sessions.putIfAbsent(session, 채팅방_아이디); + + // when + final Optional actual = sessions.findByUserId(사용자_아이디); + + // then + assertThat(actual.get()).isEqualTo(session); + } + @Test void 세션을_제거한다() { // given From b8f6d516ee1eb35b583d0fae0a9b81b4f018faa5 Mon Sep 17 00:00:00 2001 From: swonny Date: Tue, 16 Apr 2024 14:31:15 +0900 Subject: [PATCH 16/24] =?UTF-8?q?fix:=20MockitoJunitRunner=20=ED=99=9C?= =?UTF-8?q?=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ddang/websocket/handler/WebSocketHandlerTest.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java index 40b7cca3e..bfd48fec1 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java @@ -1,5 +1,6 @@ package com.ddang.ddang.websocket.handler; +import com.ddang.ddang.chat.handler.ChatHandleTypeProviderComposite; import com.ddang.ddang.chat.handler.ChatWebSocketHandleTextMessageProvider; import com.ddang.ddang.configuration.IsolateDatabase; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; @@ -9,9 +10,12 @@ import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; @@ -23,6 +27,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +@ExtendWith({MockitoExtension.class}) @IsolateDatabase @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SuppressWarnings("NonAsciiCharacters") @@ -34,6 +39,9 @@ class WebSocketHandlerTest extends WebSocketHandlerTestFixture { @MockBean WebSocketHandleTextMessageProviderComposite providerComposite; + @MockBean + ChatHandleTypeProviderComposite chatHandleTypeProviderComposite; + @Autowired WebSocketHandler webSocketHandler; @@ -64,7 +72,7 @@ class WebSocketHandlerTest extends WebSocketHandlerTestFixture { given(session.getAttributes()).willReturn(세션_attribute_정보); // when - webSocketHandler.afterConnectionClosed(session, null); + webSocketHandler.afterConnectionClosed(session, CloseStatus.NORMAL); // then verify(provider, times(1)).remove(any(WebSocketSession.class)); From 4247351f608384abb348241e7ba5ab84cc4586e0 Mon Sep 17 00:00:00 2001 From: JJ503 <63184334+JJ503@users.noreply.github.com> Date: Thu, 11 Apr 2024 23:19:04 +0900 Subject: [PATCH 17/24] =?UTF-8?q?refactor:=20=EB=A9=94=EC=8B=9C=EC=A7=80?= =?UTF-8?q?=EC=99=80=20=EC=B1=84=ED=8C=85=20=ED=83=80=EC=9E=85=EC=9D=B4=20?= =?UTF-8?q?=EB=8C=80=EC=86=8C=EB=AC=B8=EC=9E=90=20=EA=B5=AC=EB=B6=84?= =?UTF-8?q?=EC=97=86=EC=9D=B4=20=EB=A7=A4=ED=95=91=EB=90=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalExceptionHandler.java | 22 +++++++++++++++++++ .../handler/dto/ChatMessageType.java | 19 ++++++---------- .../handler/dto/TextMessageType.java | 15 ++++++++++++- .../UnsupportedChattingTypeException.java | 7 ++++++ 4 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/exception/UnsupportedChattingTypeException.java diff --git a/backend/ddang/src/main/java/com/ddang/ddang/exception/GlobalExceptionHandler.java b/backend/ddang/src/main/java/com/ddang/ddang/exception/GlobalExceptionHandler.java index 5831faf10..835daeb4b 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/exception/GlobalExceptionHandler.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/exception/GlobalExceptionHandler.java @@ -42,6 +42,8 @@ import com.ddang.ddang.review.application.exception.ReviewNotFoundException; import com.ddang.ddang.user.application.exception.AlreadyExistsNameException; import com.ddang.ddang.user.application.exception.UserNotFoundException; +import com.ddang.ddang.websocket.handler.exception.UnsupportedChattingTypeException; +import com.ddang.ddang.websocket.handler.exception.UnsupportedTextMessageTypeException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; @@ -436,6 +438,26 @@ public ResponseEntity handleWithdrawalNotAllowedException(fin .body(new ExceptionResponse(ex.getMessage())); } + @ExceptionHandler(UnsupportedTextMessageTypeException.class) + public ResponseEntity handleUnsupportedTextMessageTypeException( + final UnsupportedTextMessageTypeException ex + ) { + logger.warn(String.format(LOG_MESSAGE_FORMAT, ex.getClass().getSimpleName(), ex.getMessage())); + + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(new ExceptionResponse(ex.getMessage())); + } + + @ExceptionHandler(UnsupportedChattingTypeException.class) + public ResponseEntity handleUnsupportedChattingTypeException( + final UnsupportedChattingTypeException ex + ) { + logger.warn(String.format(LOG_MESSAGE_FORMAT, ex.getClass().getSimpleName(), ex.getMessage())); + + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(new ExceptionResponse(ex.getMessage())); + } + @Override protected ResponseEntity handleMethodArgumentNotValid( final MethodArgumentNotValidException ex, diff --git a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChatMessageType.java b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChatMessageType.java index 5e2689c5d..15161a2a6 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChatMessageType.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/ChatMessageType.java @@ -1,23 +1,18 @@ package com.ddang.ddang.websocket.handler.dto; +import com.ddang.ddang.websocket.handler.exception.UnsupportedChattingTypeException; + import java.util.Arrays; public enum ChatMessageType { - MESSAGE("message"), - PING("ping"), - ; - - private final String value; - - ChatMessageType(final String value) { - this.value = value; - } + MESSAGE, + PING; public static ChatMessageType findMessageType(final String value) { return Arrays.stream(ChatMessageType.values()) - .filter(chattingType -> chattingType.value.equals(value)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("잘못된 채팅 타입입니다.")); + .filter(chattingType -> chattingType.name().equalsIgnoreCase(value)) + .findFirst() + .orElseThrow(() -> new UnsupportedChattingTypeException("잘못된 채팅 타입입니다.")); } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/TextMessageType.java b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/TextMessageType.java index 70fc40615..69405820e 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/TextMessageType.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/dto/TextMessageType.java @@ -1,7 +1,20 @@ package com.ddang.ddang.websocket.handler.dto; +import com.ddang.ddang.websocket.handler.exception.UnsupportedTextMessageTypeException; +import com.fasterxml.jackson.annotation.JsonCreator; + +import java.util.Arrays; + public enum TextMessageType { CHATTINGS, - BIDS + BIDS; + + @JsonCreator + public static TextMessageType fromString(String value) { + return Arrays.stream(TextMessageType.values()) + .filter(messageType -> messageType.name().equalsIgnoreCase(value)) + .findFirst() + .orElseThrow(() -> new UnsupportedTextMessageTypeException("잘못된 메시지 타입입니다.")); + } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/exception/UnsupportedChattingTypeException.java b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/exception/UnsupportedChattingTypeException.java new file mode 100644 index 000000000..d7b842b8e --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/websocket/handler/exception/UnsupportedChattingTypeException.java @@ -0,0 +1,7 @@ +package com.ddang.ddang.websocket.handler.exception; + +public class UnsupportedChattingTypeException extends IllegalStateException { + public UnsupportedChattingTypeException(final String message) { + super(message); + } +} From c4bc7ef35fd6fdd4558d3154449eeb6e01d7236c Mon Sep 17 00:00:00 2001 From: swonny Date: Thu, 18 Apr 2024 00:14:29 +0900 Subject: [PATCH 18/24] =?UTF-8?q?test:=20=EC=9B=B9=EC=86=8C=EC=BC=93=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=A0=84=EC=86=A1=EC=8B=9C=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=A0=84=EC=86=A1,=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EB=A1=9C=EA=B7=B8=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=ED=98=B8=EC=B6=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/handler/MessageTypeHandlerTest.java | 74 ++++++++++++++ .../MessageTypeHandlerTestFixture.java | 99 +++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 backend/ddang/src/test/java/com/ddang/ddang/chat/handler/MessageTypeHandlerTest.java create mode 100644 backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/MessageTypeHandlerTestFixture.java diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/MessageTypeHandlerTest.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/MessageTypeHandlerTest.java new file mode 100644 index 000000000..3619d1bff --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/MessageTypeHandlerTest.java @@ -0,0 +1,74 @@ +package com.ddang.ddang.chat.handler; + +import com.ddang.ddang.chat.application.event.MessageNotificationEvent; +import com.ddang.ddang.chat.application.event.UpdateReadMessageLogEvent; +import com.ddang.ddang.chat.domain.WebSocketChatSessions; +import com.ddang.ddang.chat.handler.fixture.MessageTypeHandlerTestFixture; +import com.ddang.ddang.configuration.IsolateDatabase; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.event.ApplicationEvents; +import org.springframework.test.context.event.RecordApplicationEvents; +import org.springframework.web.socket.WebSocketSession; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.willReturn; + +@IsolateDatabase +@RecordApplicationEvents +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class MessageTypeHandlerTest extends MessageTypeHandlerTestFixture { + + @Autowired + MessageTypeHandler messageTypeHandler; + + @MockBean + WebSocketChatSessions webSocketChatSessions; + + @Mock + WebSocketSession writerSession; + + @Mock + WebSocketSession receiverSession; + + @Autowired + ApplicationEvents events; + + @Test + void 웹소켓으로_메시지_전송시_사용자가_웹소켓에_접속하지_않은_경우_알림을_전송한다() throws JsonProcessingException { + // given + willReturn(false).given(webSocketChatSessions).containsByUserId(채팅방.getId(), 수신자.getId()); + willReturn(발신자만_존재하는_웹소켓_세션들).given(webSocketChatSessions).findSessionsByChatRoomId(채팅방.getId()); + + // when + messageTypeHandler.createResponse(발신자_세션_속성_dto, 메시지_데이터); + final long actual = events.stream(MessageNotificationEvent.class).count(); + + // then + assertThat(actual).isEqualTo(1); + } + + @Test + void 웹소켓으로_메시지_전송시_메시지_수신자_모두의_메시지_로그_업데이트_이벤트를_호출한다() throws JsonProcessingException { + // given + willReturn(true).given(webSocketChatSessions).containsByUserId(채팅방.getId(), 발신자.getId()); + 발신자와_수신자가_존재하는_웹소켓_세션들.putIfAbsent(writerSession, 채팅방.getId()); + 발신자와_수신자가_존재하는_웹소켓_세션들.putIfAbsent(receiverSession, 채팅방.getId()); + willReturn(발신자와_수신자가_존재하는_웹소켓_세션들).given(webSocketChatSessions).findSessionsByChatRoomId(채팅방.getId()); + willReturn(발신자_세션_attribute_정보).given(writerSession).getAttributes(); + willReturn(수신자_세션_attribute_정보).given(receiverSession).getAttributes(); + + // when + messageTypeHandler.createResponse(발신자_세션_속성_dto, 메시지_데이터); + final long actual = events.stream(UpdateReadMessageLogEvent.class).count(); + + // then + assertThat(actual).isEqualTo(2); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/MessageTypeHandlerTestFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/MessageTypeHandlerTestFixture.java new file mode 100644 index 000000000..a464c5464 --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/MessageTypeHandlerTestFixture.java @@ -0,0 +1,99 @@ +package com.ddang.ddang.chat.handler.fixture; + +import com.ddang.ddang.auction.domain.Auction; +import com.ddang.ddang.auction.domain.BidUnit; +import com.ddang.ddang.auction.domain.Price; +import com.ddang.ddang.auction.domain.repository.AuctionRepository; +import com.ddang.ddang.category.domain.Category; +import com.ddang.ddang.category.infrastructure.persistence.JpaCategoryRepository; +import com.ddang.ddang.chat.domain.ChatRoom; +import com.ddang.ddang.chat.domain.WebSocketSessions; +import com.ddang.ddang.chat.domain.repository.ChatRoomRepository; +import com.ddang.ddang.image.domain.ProfileImage; +import com.ddang.ddang.user.domain.Reliability; +import com.ddang.ddang.user.domain.User; +import com.ddang.ddang.user.domain.repository.UserRepository; +import com.ddang.ddang.websocket.handler.dto.SessionAttributeDto; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("NonAsciiCharacters") +public class MessageTypeHandlerTestFixture { + + @Autowired + private AuctionRepository auctionRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private ChatRoomRepository chatRoomRepository; + + @Autowired + private JpaCategoryRepository categoryRepository; + + protected User 발신자; + protected User 수신자; + protected SessionAttributeDto 발신자_세션_속성_dto; + protected Map 메시지_데이터; + protected ChatRoom 채팅방; + protected WebSocketSessions 발신자만_존재하는_웹소켓_세션들; + protected WebSocketSessions 발신자와_수신자가_존재하는_웹소켓_세션들; + protected Map 발신자_세션_attribute_정보; + protected Map 수신자_세션_attribute_정보; + + @BeforeEach + void setUpFixture() { + final Category 전자기기 = new Category("전자기기"); + final Category 전자기기_하위_노트북 = new Category("노트북"); + 전자기기.addSubCategory(전자기기_하위_노트북); + categoryRepository.save(전자기기); + + final Auction 경매 = Auction.builder() + .title("경매") + .description("description") + .bidUnit(new BidUnit(1_000)) + .startPrice(new Price(10_000)) + .closingTime(LocalDateTime.now().plusDays(3L)) + .build(); + auctionRepository.save(경매); + + 발신자 = User.builder() + .name("발신자") + .profileImage(new ProfileImage("upload.png", "store.png")) + .reliability(new Reliability(4.7d)) + .oauthId("12345") + .build(); + 수신자 = User.builder() + .name("수신자") + .profileImage(new ProfileImage("upload.png", "store.png")) + .reliability(new Reliability(4.7d)) + .oauthId("12346") + .build(); + final User 탈퇴한_사용자 = User.builder() + .name("탈퇴한 사용자") + .profileImage(new ProfileImage("upload.png", "store.png")) + .reliability(new Reliability(4.7d)) + .oauthId("12347") + .build(); + 탈퇴한_사용자.withdrawal(); + userRepository.save(발신자); + userRepository.save(수신자); + + 채팅방 = new ChatRoom(경매, 발신자); + chatRoomRepository.save(채팅방); + + 발신자_세션_속성_dto = new SessionAttributeDto(발신자.getId(), "/image.png"); + 메시지_데이터 = new HashMap<>(Map.of("chatRoomId", "1", "receiverId", "1", "contents", "메시지 내용")); + + 발신자만_존재하는_웹소켓_세션들 = new WebSocketSessions(); + 발신자와_수신자가_존재하는_웹소켓_세션들 = new WebSocketSessions(); + + 발신자_세션_attribute_정보 = new HashMap<>(Map.of("userId", 발신자.getId(), "baseUrl", "/images")); + 수신자_세션_attribute_정보 = new HashMap<>(Map.of("userId", 수신자.getId(), "baseUrl", "/images")); + } +} From 6a0a63f82c4cbd0b5add7ac44d9cd1d24cbc9e2d Mon Sep 17 00:00:00 2001 From: swonny Date: Thu, 18 Apr 2024 01:01:07 +0900 Subject: [PATCH 19/24] =?UTF-8?q?test:=20=EC=8B=A4=ED=8C=A8=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ddang/websocket/handler/dto/ChatMessageTypeTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChatMessageTypeTest.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChatMessageTypeTest.java index 4db0b4c73..9a34259fc 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChatMessageTypeTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/dto/ChatMessageTypeTest.java @@ -1,5 +1,6 @@ package com.ddang.ddang.websocket.handler.dto; +import com.ddang.ddang.websocket.handler.exception.UnsupportedChattingTypeException; import org.junit.jupiter.api.Test; import java.util.Map; @@ -29,6 +30,7 @@ class ChatMessageTypeTest { final Map data = Map.of("type", "wrong type"); // when & then - assertThatThrownBy(() -> ChatMessageType.findMessageType(data.get("type"))).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> ChatMessageType.findMessageType(data.get("type"))) + .isInstanceOf(UnsupportedChattingTypeException.class); } } From f20d6b83c36cef95488294ba7d86c16d9e51b7ea Mon Sep 17 00:00:00 2001 From: swonny Date: Thu, 18 Apr 2024 14:34:11 +0900 Subject: [PATCH 20/24] =?UTF-8?q?test:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=95=84=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ddang/ddang/websocket/handler/WebSocketHandlerTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java index bfd48fec1..2a9f3f522 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java @@ -1,6 +1,5 @@ package com.ddang.ddang.websocket.handler; -import com.ddang.ddang.chat.handler.ChatHandleTypeProviderComposite; import com.ddang.ddang.chat.handler.ChatWebSocketHandleTextMessageProvider; import com.ddang.ddang.configuration.IsolateDatabase; import com.ddang.ddang.websocket.handler.dto.SendMessageDto; @@ -39,9 +38,6 @@ class WebSocketHandlerTest extends WebSocketHandlerTestFixture { @MockBean WebSocketHandleTextMessageProviderComposite providerComposite; - @MockBean - ChatHandleTypeProviderComposite chatHandleTypeProviderComposite; - @Autowired WebSocketHandler webSocketHandler; From 84a6a7f00eb4f34aa76077e09b25993f51e1a439 Mon Sep 17 00:00:00 2001 From: swonny Date: Thu, 18 Apr 2024 18:28:38 +0900 Subject: [PATCH 21/24] =?UTF-8?q?chore:=20=EB=A1=9C=EA=B7=B8=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20=EC=9E=84=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/application/event/MessageNotificationEvent.java | 5 +++++ .../com/ddang/ddang/chat/handler/MessageTypeHandler.java | 8 ++++++++ .../application/NotificationEventListener.java | 3 ++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/application/event/MessageNotificationEvent.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/application/event/MessageNotificationEvent.java index 9597cafc9..f738ee83c 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/application/event/MessageNotificationEvent.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/application/event/MessageNotificationEvent.java @@ -3,4 +3,9 @@ import com.ddang.ddang.chat.domain.Message; public record MessageNotificationEvent(Message message, String profileImageAbsoluteUrl) { + + @Override + public String toString() { + return "MessageNotificationEvent{" + "message=" + message + ", profileImageAbsoluteUrl='" + profileImageAbsoluteUrl + '\'' + '}'; + } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java index 58813632f..c0b9ad1dc 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; import org.springframework.web.socket.TextMessage; @@ -28,6 +29,7 @@ import java.util.List; import java.util.Map; +@Slf4j @Component @RequiredArgsConstructor public class MessageTypeHandler implements ChatHandleProvider { @@ -69,7 +71,13 @@ private void sendNotificationIfReceiverNotInSession( final Message message, final SessionAttributeDto sessionAttribute ) { + log.info("MessageTypeHandler.sendNotificationIfRecevierNotInSession userId : {}", sessionAttribute.userId()); + log.info( + "MessageTypeHandler.sendNotificationIfReceiverNotInSession sessions : {}", + sessions.getChatRoomSessions() + ); if (!sessions.containsByUserId(message.getChatRoom().getId(), message.getReceiver().getId())) { + log.info("MessageTypeHandler.sendNotificationIfReceiverNotInSession if문 내부"); final String profileImageAbsoluteUrl = String.valueOf(sessionAttribute.baseUrl()); messageNotificationEventPublisher.publishEvent(new MessageNotificationEvent( message, diff --git a/backend/ddang/src/main/java/com/ddang/ddang/notification/application/NotificationEventListener.java b/backend/ddang/src/main/java/com/ddang/ddang/notification/application/NotificationEventListener.java index 2839f60cd..c6227c573 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/notification/application/NotificationEventListener.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/notification/application/NotificationEventListener.java @@ -37,6 +37,7 @@ public class NotificationEventListener { @TransactionalEventListener public void sendMessageNotification(final MessageNotificationEvent messageNotificationEvent) { try { + log.info("NotificationEventListener.sendMessageNotification : {}", messageNotificationEvent.toString()); final Message message = messageNotificationEvent.message(); final ProfileImage profileImage = message.getWriter().getProfileImage(); final CreateNotificationDto createNotificationDto = new CreateNotificationDto( @@ -48,7 +49,7 @@ public void sendMessageNotification(final MessageNotificationEvent messageNotifi ImageUrlCalculator.calculateBy(messageNotificationEvent.profileImageAbsoluteUrl(), ImageStoreNameProcessor.process(profileImage)) ); notificationService.send(createNotificationDto); - } catch (final FirebaseMessagingException ex) { + } catch (final Exception ex) { log.error("exception type : {}, ", ex.getClass().getSimpleName(), ex); } } From c6e8e91f1735f1e0897b11a8714b0b526d86c1ab Mon Sep 17 00:00:00 2001 From: swonny Date: Thu, 18 Apr 2024 18:35:01 +0900 Subject: [PATCH 22/24] =?UTF-8?q?chore:=20=EB=A1=9C=EA=B7=B8=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EB=A1=9C=EA=B7=B8=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=84=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ddang/ddang/chat/domain/WebSocketSessions.java | 3 +++ .../java/com/ddang/ddang/chat/handler/MessageTypeHandler.java | 1 + 2 files changed, 4 insertions(+) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java index 4a3fb23a7..abe128d59 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java @@ -1,6 +1,7 @@ package com.ddang.ddang.chat.domain; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.socket.WebSocketSession; import java.util.Collections; @@ -8,6 +9,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +@Slf4j @Getter public class WebSocketSessions { @@ -24,6 +26,7 @@ public void putIfAbsent(final WebSocketSession session, final Long chatRoomId) { } public boolean contains(final Long userId) { + log.info("WebSocketSessions.contains userId : {}, currentSessions : {}", userId, sessions); return sessions.stream() .anyMatch(session -> session.getAttributes().get(USER_ID_KEY) == userId); } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java index c0b9ad1dc..46714a033 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java @@ -92,6 +92,7 @@ private List createSendMessages( final Long chatRoomId ) throws JsonProcessingException { final WebSocketSessions groupSessions = sessions.findSessionsByChatRoomId(message.getChatRoom().getId()); + log.info("MessageTypeHandler.createSendMessages groupSessions : {}", groupSessions); final List sendMessageDtos = new ArrayList<>(); for (final WebSocketSession currentSession : groupSessions.getSessions()) { From ceef7d044c902409fc42c9851615e7634bba8f0c Mon Sep 17 00:00:00 2001 From: swonny Date: Thu, 18 Apr 2024 18:48:26 +0900 Subject: [PATCH 23/24] =?UTF-8?q?chore:=20=EB=A1=9C=EA=B7=B8=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20=EC=9E=84=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ddang/ddang/chat/handler/MessageTypeHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java index 46714a033..320fbd6d9 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java @@ -71,7 +71,7 @@ private void sendNotificationIfReceiverNotInSession( final Message message, final SessionAttributeDto sessionAttribute ) { - log.info("MessageTypeHandler.sendNotificationIfRecevierNotInSession userId : {}", sessionAttribute.userId()); + log.info("MessageTypeHandler.sendNotificationIfRecevierNotInSession receiverId : {}, chatRoomId : {}", message.getReceiver().getId(), message.getChatRoom().getId()); log.info( "MessageTypeHandler.sendNotificationIfReceiverNotInSession sessions : {}", sessions.getChatRoomSessions() From 540088689274badaa07ff76df467e669843f17a0 Mon Sep 17 00:00:00 2001 From: swonny Date: Thu, 18 Apr 2024 18:58:09 +0900 Subject: [PATCH 24/24] =?UTF-8?q?chore:=20=EB=A1=9C=EA=B7=B8=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/application/LastReadMessageLogEventListener.java | 7 +++++-- .../chat/application/event/MessageNotificationEvent.java | 5 ----- .../com/ddang/ddang/chat/domain/WebSocketSessions.java | 2 ++ .../com/ddang/ddang/chat/handler/MessageTypeHandler.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/application/LastReadMessageLogEventListener.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/application/LastReadMessageLogEventListener.java index 5c67a1089..e87f61c4a 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/application/LastReadMessageLogEventListener.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/application/LastReadMessageLogEventListener.java @@ -2,7 +2,6 @@ import com.ddang.ddang.chat.application.event.CreateReadMessageLogEvent; import com.ddang.ddang.chat.application.event.UpdateReadMessageLogEvent; -import com.ddang.ddang.chat.application.exception.ReadMessageLogNotFoundException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -31,8 +30,12 @@ public void create(final CreateReadMessageLogEvent createReadMessageLogEvent) { @Transactional(propagation = Propagation.REQUIRES_NEW) public void update(final UpdateReadMessageLogEvent updateReadMessageLogEvent) { try { + log.info( + "LastReadMessageLogEventListener.update updateReadMessageLogEvent : {}", + updateReadMessageLogEvent.toString() + ); lastReadMessageLogService.update(updateReadMessageLogEvent); - } catch (final ReadMessageLogNotFoundException ex) { + } catch (final Exception ex) { log.error("exception type : {}, ", ex.getClass().getSimpleName(), ex); } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/application/event/MessageNotificationEvent.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/application/event/MessageNotificationEvent.java index f738ee83c..9597cafc9 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/application/event/MessageNotificationEvent.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/application/event/MessageNotificationEvent.java @@ -3,9 +3,4 @@ import com.ddang.ddang.chat.domain.Message; public record MessageNotificationEvent(Message message, String profileImageAbsoluteUrl) { - - @Override - public String toString() { - return "MessageNotificationEvent{" + "message=" + message + ", profileImageAbsoluteUrl='" + profileImageAbsoluteUrl + '\'' + '}'; - } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java index abe128d59..0d5c1c53c 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java @@ -1,6 +1,7 @@ package com.ddang.ddang.chat.domain; import lombok.Getter; +import lombok.ToString; import lombok.extern.slf4j.Slf4j; import org.springframework.web.socket.WebSocketSession; @@ -9,6 +10,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +@ToString @Slf4j @Getter public class WebSocketSessions { diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java index 320fbd6d9..5d21ac71a 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/MessageTypeHandler.java @@ -92,7 +92,7 @@ private List createSendMessages( final Long chatRoomId ) throws JsonProcessingException { final WebSocketSessions groupSessions = sessions.findSessionsByChatRoomId(message.getChatRoom().getId()); - log.info("MessageTypeHandler.createSendMessages groupSessions : {}", groupSessions); + log.info("MessageTypeHandler.createSendMessages groupSessions : {}", groupSessions.toString()); final List sendMessageDtos = new ArrayList<>(); for (final WebSocketSession currentSession : groupSessions.getSessions()) {