From d94036c2a16606789cfb24467e8f2a206c02c822 Mon Sep 17 00:00:00 2001 From: Dmytro Trotsenko Date: Wed, 13 Mar 2024 22:35:46 +0200 Subject: [PATCH 1/4] fix: fixed notification and event type --- .../chat/yourway/listener/StompSubscriptionListener.java | 7 ++++--- src/main/java/com/chat/yourway/model/event/EventType.java | 3 +-- .../unit/listener/StompSubscriptionListenerTest.java | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/chat/yourway/listener/StompSubscriptionListener.java b/src/main/java/com/chat/yourway/listener/StompSubscriptionListener.java index 2fae796c..bf0766cc 100644 --- a/src/main/java/com/chat/yourway/listener/StompSubscriptionListener.java +++ b/src/main/java/com/chat/yourway/listener/StompSubscriptionListener.java @@ -1,7 +1,7 @@ package com.chat.yourway.listener; +import static com.chat.yourway.model.event.EventType.ONLINE; import static com.chat.yourway.model.event.EventType.SUBSCRIBED; -import static com.chat.yourway.model.event.EventType.UNSUBSCRIBED; import com.chat.yourway.config.websocket.WebsocketProperties; import com.chat.yourway.dto.response.LastMessageResponseDto; @@ -46,10 +46,11 @@ public void handleWebSocketSubscribeListener(SessionSubscribeEvent event) { .getLastMessage(); var contactEvent = new ContactEvent(email, getTopicId(event), SUBSCRIBED, getTimestamp(event), lastMessageDto); + contactEventService.updateEventTypeByEmail(ONLINE, email); contactEventService.save(contactEvent); } - chatNotificationService.notifyTopicSubscribers(getTopicId(event)); + chatNotificationService.notifyAllWhoSubscribedToSameUserTopic(email); chatNotificationService.notifyAllWhoSubscribedToTopic(getTopicId(event)); } catch (NumberFormatException e) { @@ -70,7 +71,7 @@ public void handleWebSocketUnsubscribeListener(SessionUnsubscribeEvent event) { try { if (isTopicDestination(destination)) { - var contactEvent = new ContactEvent(email, getTopicId(event), UNSUBSCRIBED, + var contactEvent = new ContactEvent(email, getTopicId(event), ONLINE, getTimestamp(event), lastMessageDto); contactEventService.save(contactEvent); } diff --git a/src/main/java/com/chat/yourway/model/event/EventType.java b/src/main/java/com/chat/yourway/model/event/EventType.java index 03916f44..f72005fe 100644 --- a/src/main/java/com/chat/yourway/model/event/EventType.java +++ b/src/main/java/com/chat/yourway/model/event/EventType.java @@ -3,6 +3,5 @@ public enum EventType { ONLINE, OFFLINE, - SUBSCRIBED, - UNSUBSCRIBED + SUBSCRIBED } diff --git a/src/test/java/com/chat/yourway/unit/listener/StompSubscriptionListenerTest.java b/src/test/java/com/chat/yourway/unit/listener/StompSubscriptionListenerTest.java index 481ce221..38685b4a 100644 --- a/src/test/java/com/chat/yourway/unit/listener/StompSubscriptionListenerTest.java +++ b/src/test/java/com/chat/yourway/unit/listener/StompSubscriptionListenerTest.java @@ -1,7 +1,7 @@ package com.chat.yourway.unit.listener; +import static com.chat.yourway.model.event.EventType.ONLINE; import static com.chat.yourway.model.event.EventType.SUBSCRIBED; -import static com.chat.yourway.model.event.EventType.UNSUBSCRIBED; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.ArgumentMatchers.anyInt; @@ -108,7 +108,7 @@ public void handleWebSocketSubscribeListener_shouldNotifyTopicSubscribers() { stompSubscriptionListener.handleWebSocketSubscribeListener(event); // Then - verify(chatNotificationService, times(1)).notifyTopicSubscribers(topicId); + verify(chatNotificationService, times(1)).notifyAllWhoSubscribedToSameUserTopic(email); } @Test @@ -132,7 +132,7 @@ public void handleWebSocketUnsubscribeListener_shouldSaveEvent() { assertThat(capturedEvent.getTopicId()).isEqualTo(topicId); assertThat(capturedEvent.getEmail()).isEqualTo(email); assertThat(capturedEvent.getTimestamp()).isInstanceOfAny(LocalDateTime.class); - assertThat(capturedEvent.getEventType()).isEqualTo(UNSUBSCRIBED); + assertThat(capturedEvent.getEventType()).isEqualTo(ONLINE); } @Test From 2e4b462b94ac6179345aa63110a49ebad2c2affd Mon Sep 17 00:00:00 2001 From: Dmytro Trotsenko Date: Sun, 17 Mar 2024 11:52:30 +0200 Subject: [PATCH 2/4] bugfix: fixed disconnect from websocket. Set time to first message. --- .../chat/yourway/config/websocket/WebSocketConfig.java | 8 ++++++++ .../yourway/config/websocket/WebsocketProperties.java | 1 + src/main/resources/application.properties | 5 +++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/chat/yourway/config/websocket/WebSocketConfig.java b/src/main/java/com/chat/yourway/config/websocket/WebSocketConfig.java index fb74aeee..c14d7a3e 100644 --- a/src/main/java/com/chat/yourway/config/websocket/WebSocketConfig.java +++ b/src/main/java/com/chat/yourway/config/websocket/WebSocketConfig.java @@ -6,6 +6,7 @@ import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration; @Configuration @EnableWebSocketMessageBroker @@ -25,4 +26,11 @@ public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint(properties.getEndpoint()); registry.addEndpoint(properties.getEndpoint()).setAllowedOriginPatterns("*").withSockJS(); } + + + @Override + public void configureWebSocketTransport(WebSocketTransportRegistration registry) { + registry.setTimeToFirstMessage(properties.getTimeToFirstMessage()); + } + } diff --git a/src/main/java/com/chat/yourway/config/websocket/WebsocketProperties.java b/src/main/java/com/chat/yourway/config/websocket/WebsocketProperties.java index 83e8eca4..8c000619 100644 --- a/src/main/java/com/chat/yourway/config/websocket/WebsocketProperties.java +++ b/src/main/java/com/chat/yourway/config/websocket/WebsocketProperties.java @@ -17,5 +17,6 @@ public class WebsocketProperties { private String topicPrefix; private String notifyPrefix; private String errorPrefix; + private int TimeToFirstMessage; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 023afd21..ecf8cbc5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -16,7 +16,7 @@ spring.data.redis.password=${REDIS_PASSWORD:admin} #Hibernate spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect -spring.jpa.show-sql=true +#spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true spring.jpa.hibernate.ddl-auto=validate @@ -30,6 +30,7 @@ socket.endpoint=/chat socket.topic-prefix=/topic socket.notify-prefix=/specific/notify socket.error-prefix=/specific/error +socket.time-to-first-message=999999 #Security: security.jwt.token-type=Bearer @@ -58,5 +59,5 @@ spring.mail.properties.mail.smtp.starttls.required=true message.max.amount.reports=2 #Logging: -logging.level.com.chat.yourway=${LOGGING_LEVEL:info} +logging.level.com.chat.yourway=${LOGGING_LEVEL:trace} From 7f88ea827b6dd5a9519af28a512e57ac7899050b Mon Sep 17 00:00:00 2001 From: Dmytro Trotsenko Date: Sun, 24 Mar 2024 13:30:40 +0200 Subject: [PATCH 3/4] fix: refactored and optimized notifications --- .../TopicNotificationResponseDto.java | 2 +- .../listener/StompSubscriptionListener.java | 9 +++-- .../mapper/MessageNotificationMapper.java | 16 -------- .../yourway/mapper/NotificationMapper.java | 22 ++++++++++ .../yourway/model/event/ContactEvent.java | 4 +- .../service/ChatMessageServiceImpl.java | 10 ++--- .../service/ChatNotificationServiceImpl.java | 40 +++++++++++++++++-- .../service/ContactEventServiceImpl.java | 17 +++++--- .../service/NotificationServiceImpl.java | 38 +++++++++--------- .../interfaces/ChatNotificationService.java | 16 +++++++- .../interfaces/ContactEventService.java | 2 +- .../interfaces/NotificationService.java | 14 +++++-- src/main/resources/application.properties | 4 +- .../controller/ChatControllerTest.java | 4 +- .../impl/ContactEventServiceImplTest.java | 24 ++++++----- .../impl/NotificationServiceImplTest.java | 12 +++--- 16 files changed, 154 insertions(+), 80 deletions(-) delete mode 100644 src/main/java/com/chat/yourway/mapper/MessageNotificationMapper.java create mode 100644 src/main/java/com/chat/yourway/mapper/NotificationMapper.java diff --git a/src/main/java/com/chat/yourway/dto/response/TopicNotificationResponseDto.java b/src/main/java/com/chat/yourway/dto/response/TopicNotificationResponseDto.java index 5de5165d..744604f4 100644 --- a/src/main/java/com/chat/yourway/dto/response/TopicNotificationResponseDto.java +++ b/src/main/java/com/chat/yourway/dto/response/TopicNotificationResponseDto.java @@ -13,7 +13,7 @@ @ToString public class TopicNotificationResponseDto { - private TopicResponseDto topic; + private Integer topicId; private Integer unreadMessages; diff --git a/src/main/java/com/chat/yourway/listener/StompSubscriptionListener.java b/src/main/java/com/chat/yourway/listener/StompSubscriptionListener.java index bf0766cc..2b38f4e7 100644 --- a/src/main/java/com/chat/yourway/listener/StompSubscriptionListener.java +++ b/src/main/java/com/chat/yourway/listener/StompSubscriptionListener.java @@ -44,8 +44,11 @@ public void handleWebSocketSubscribeListener(SessionSubscribeEvent event) { if (isTopicDestination(destination)) { lastMessageDto = contactEventService.getByTopicIdAndEmail(getTopicId(event), email) .getLastMessage(); + int unreadMessages = contactEventService.getByTopicIdAndEmail(getTopicId(event), email) + .getUnreadMessages(); + var contactEvent = new ContactEvent(email, getTopicId(event), SUBSCRIBED, - getTimestamp(event), lastMessageDto); + getTimestamp(event), unreadMessages, lastMessageDto); contactEventService.updateEventTypeByEmail(ONLINE, email); contactEventService.save(contactEvent); } @@ -58,7 +61,7 @@ public void handleWebSocketSubscribeListener(SessionSubscribeEvent event) { } if (destination.equals(USER_DESTINATION + properties.getNotifyPrefix() + TOPICS_DESTINATION)) { - chatNotificationService.notifyAllPublicTopics(getEmail(event)); + chatNotificationService.notifyAllTopics(getEmail(event)); } log.info("Contact [{}] subscribe to [{}]", email, destination); @@ -72,7 +75,7 @@ public void handleWebSocketUnsubscribeListener(SessionUnsubscribeEvent event) { try { if (isTopicDestination(destination)) { var contactEvent = new ContactEvent(email, getTopicId(event), ONLINE, - getTimestamp(event), lastMessageDto); + getTimestamp(event), 0, lastMessageDto); contactEventService.save(contactEvent); } diff --git a/src/main/java/com/chat/yourway/mapper/MessageNotificationMapper.java b/src/main/java/com/chat/yourway/mapper/MessageNotificationMapper.java deleted file mode 100644 index 7a80c96e..00000000 --- a/src/main/java/com/chat/yourway/mapper/MessageNotificationMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.chat.yourway.mapper; - -import com.chat.yourway.dto.response.MessageNotificationResponseDto; -import com.chat.yourway.model.event.ContactEvent; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -@Mapper(componentModel = "spring") -public interface MessageNotificationMapper { - - @Mapping(target = "status", source = "eventType") - @Mapping(target = "lastRead", source = "timestamp") - @Mapping(target = "email", source = "email") - MessageNotificationResponseDto toNotificationResponseDto(ContactEvent event); - -} diff --git a/src/main/java/com/chat/yourway/mapper/NotificationMapper.java b/src/main/java/com/chat/yourway/mapper/NotificationMapper.java new file mode 100644 index 00000000..591a5454 --- /dev/null +++ b/src/main/java/com/chat/yourway/mapper/NotificationMapper.java @@ -0,0 +1,22 @@ +package com.chat.yourway.mapper; + +import com.chat.yourway.dto.response.MessageNotificationResponseDto; +import com.chat.yourway.dto.response.TopicNotificationResponseDto; +import com.chat.yourway.model.event.ContactEvent; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +@Mapper(componentModel = "spring") +public interface NotificationMapper { + + @Mapping(target = "status", source = "eventType") + @Mapping(target = "lastRead", source = "timestamp") + @Mapping(target = "email", source = "email") + MessageNotificationResponseDto toMessageNotificationResponseDto(ContactEvent event); + + @Mapping(target = "topicId", source = "topicId") + @Mapping(target = "unreadMessages", source = "unreadMessages") + @Mapping(target = "lastMessage", source = "lastMessage") + TopicNotificationResponseDto toTopicNotificationResponseDto(ContactEvent event); + +} diff --git a/src/main/java/com/chat/yourway/model/event/ContactEvent.java b/src/main/java/com/chat/yourway/model/event/ContactEvent.java index e782d795..8f7e9f15 100644 --- a/src/main/java/com/chat/yourway/model/event/ContactEvent.java +++ b/src/main/java/com/chat/yourway/model/event/ContactEvent.java @@ -26,16 +26,18 @@ public class ContactEvent { private Integer topicId; private EventType eventType; private LocalDateTime timestamp; + private int unreadMessages; private LastMessageResponseDto lastMessage; public ContactEvent(String email, Integer topicId, EventType eventType, LocalDateTime timestamp, - LastMessageResponseDto lastMessage) { + int unreadMessages, LastMessageResponseDto lastMessage) { this.id = email + "_" + topicId; this.email = email; this.topicId = topicId; this.eventType = eventType; this.timestamp = timestamp; + this.unreadMessages = unreadMessages; this.lastMessage = lastMessage; } diff --git a/src/main/java/com/chat/yourway/service/ChatMessageServiceImpl.java b/src/main/java/com/chat/yourway/service/ChatMessageServiceImpl.java index 8191aee0..5fac88f1 100644 --- a/src/main/java/com/chat/yourway/service/ChatMessageServiceImpl.java +++ b/src/main/java/com/chat/yourway/service/ChatMessageServiceImpl.java @@ -69,16 +69,16 @@ public List sendMessageHistoryByTopicId(Integer topicId, private void sendToTopic(Integer topicId, MessageResponseDto messageDto) { var lastMessageDto = new LastMessageResponseDto(); - lastMessageDto.setTimestamp(messageDto.getTimestamp()); - lastMessageDto.setSentFrom(messageDto.getSentFrom()); - lastMessageDto.setLastMessage(messageDto.getContent()); + lastMessageDto.setTimestamp(messageDto.getTimestamp()); + lastMessageDto.setSentFrom(messageDto.getSentFrom()); + lastMessageDto.setLastMessage(messageDto.getContent()); - contactEventService.setLastMessageToAllTopicSubscribers(topicId, lastMessageDto); + contactEventService.updateMessageInfoForAllTopicSubscribers(topicId, lastMessageDto); simpMessagingTemplate.convertAndSend(toTopicDestination(topicId), messageDto); chatNotificationService.notifyTopicSubscribers(topicId); - chatNotificationService.notifyAllWhoSubscribedToTopic(topicId); + chatNotificationService.updateNotificationForAllWhoSubscribedToTopic(topicId); } private String toTopicDestination(Integer topicId) { diff --git a/src/main/java/com/chat/yourway/service/ChatNotificationServiceImpl.java b/src/main/java/com/chat/yourway/service/ChatNotificationServiceImpl.java index a3b5772b..c833f187 100644 --- a/src/main/java/com/chat/yourway/service/ChatNotificationServiceImpl.java +++ b/src/main/java/com/chat/yourway/service/ChatNotificationServiceImpl.java @@ -27,25 +27,57 @@ public void notifyTopicSubscribers(Integer topicId) { .forEach(n -> simpMessagingTemplate.convertAndSendToUser( n.getEmail(), toNotifyMessageDest(topicId), notifications)); - log.trace("All subscribers was notified by topic id = [{}]", topicId); + log.info("All subscribers was notified by topic id = [{}]", topicId); } @Override public void notifyAllWhoSubscribedToSameUserTopic(String userEmail) { + log.trace("Started notifyAllWhoSubscribedToSameUserTopic, user email = [{}]", userEmail); + contactEventService.getAllByEmail(userEmail) .forEach(e -> notifyTopicSubscribers(e.getTopicId())); + + log.info("All subscribers who subscribed to same topic was notified, email = [{}]", userEmail); } @Override - public void notifyAllPublicTopics(String email){ - var notifiedTopics = notificationService.notifyAllPublicTopicsByEmail(email); + public void notifyAllTopics(String email) { + log.trace("Started notifyAllTopics, email = [{}]", email); + + var notifiedTopics = notificationService.notifyAllTopicsByEmail(email); simpMessagingTemplate.convertAndSendToUser(email, toNotifyTopicsDest(), notifiedTopics); + + log.info("All topics was notified for user email = [{}]", email); } @Override public void notifyAllWhoSubscribedToTopic(Integer topicId) { + log.trace("Started notifyAllWhoSubscribedToTopic, topicId = [{}]", topicId); + + contactEventService.getAllByTopicId(topicId) + .forEach(e -> notifyAllTopics(e.getEmail())); + + log.info("All subscribed users was notified, topicId = [{}]", topicId); + } + + @Override + public void updateNotificationForAllTopics(String email) { + log.trace("Started updateNotificationForAllTopics, email = [{}]", email); + + var notifiedTopics = notificationService.updateTopicNotification(email); + simpMessagingTemplate.convertAndSendToUser(email, toNotifyTopicsDest(), notifiedTopics); + + log.info("All topics for user was notified, email = [{}]", email); + } + + @Override + public void updateNotificationForAllWhoSubscribedToTopic(Integer topicId) { + log.trace("Started updateNotificationForAllWhoSubscribedToTopic, topicId = [{}]", topicId); + contactEventService.getAllByTopicId(topicId) - .forEach(e -> notifyAllPublicTopics(e.getEmail())); + .forEach(e -> updateNotificationForAllTopics(e.getEmail())); + + log.info("Topic notifications was updated for all subscribed users, topicId = [{}]", topicId); } private String toNotifyMessageDest(Integer topicId) { diff --git a/src/main/java/com/chat/yourway/service/ContactEventServiceImpl.java b/src/main/java/com/chat/yourway/service/ContactEventServiceImpl.java index b742d8dc..aace67d0 100644 --- a/src/main/java/com/chat/yourway/service/ContactEventServiceImpl.java +++ b/src/main/java/com/chat/yourway/service/ContactEventServiceImpl.java @@ -1,6 +1,7 @@ package com.chat.yourway.service; import static com.chat.yourway.model.event.EventType.ONLINE; +import static com.chat.yourway.model.event.EventType.SUBSCRIBED; import com.chat.yourway.dto.response.LastMessageResponseDto; import com.chat.yourway.model.event.ContactEvent; @@ -31,7 +32,7 @@ public ContactEvent getByTopicIdAndEmail(Integer topicId, String email) { log.trace("Started getByTopicIdAndEmail, topicId [{}], email [{}]", topicId, email); return contactEventRedisRepository.findById(email + "_" + topicId) - .orElse(new ContactEvent(email, topicId, ONLINE, LocalDateTime.now(), null)); + .orElse(new ContactEvent(email, topicId, ONLINE, LocalDateTime.now(), 0, null)); } @Override @@ -62,15 +63,21 @@ public List getAllByTopicId(Integer topicId) { } @Override - public void setLastMessageToAllTopicSubscribers(Integer topicId, LastMessageResponseDto message) { - log.trace("Started setLastMessageToAllTopicSubscribers, topic id [{}], last message [{}]", + public void updateMessageInfoForAllTopicSubscribers(Integer topicId, + LastMessageResponseDto message) { + log.trace("Started updateMessageInfoForAllTopicSubscribers, topic id [{}], last message [{}]", topicId, message); List events = getAllByTopicId(topicId).stream() - .peek(e -> e.setLastMessage(message)) + .peek(e -> { + if (!e.getEventType().equals(SUBSCRIBED)) { + e.setUnreadMessages(e.getUnreadMessages() + 1); + } + e.setLastMessage(message); + }) .toList(); - log.trace("Last message [{}] was set to all topic id [{}] subscribers", message, topicId); + log.trace("Message info [{}] was updated for all topic id [{}] subscribers", message, topicId); contactEventRedisRepository.saveAll(events); } diff --git a/src/main/java/com/chat/yourway/service/NotificationServiceImpl.java b/src/main/java/com/chat/yourway/service/NotificationServiceImpl.java index f23060ad..6639f943 100644 --- a/src/main/java/com/chat/yourway/service/NotificationServiceImpl.java +++ b/src/main/java/com/chat/yourway/service/NotificationServiceImpl.java @@ -2,12 +2,11 @@ import com.chat.yourway.dto.response.MessageNotificationResponseDto; import com.chat.yourway.dto.response.TopicNotificationResponseDto; -import com.chat.yourway.mapper.MessageNotificationMapper; +import com.chat.yourway.mapper.NotificationMapper; import com.chat.yourway.model.event.ContactEvent; import com.chat.yourway.service.interfaces.ContactEventService; import com.chat.yourway.service.interfaces.MessageService; import com.chat.yourway.service.interfaces.NotificationService; -import com.chat.yourway.service.interfaces.TopicService; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,39 +18,40 @@ public class NotificationServiceImpl implements NotificationService { private final ContactEventService contactEventService; - private final TopicService topicService; private final MessageService messageService; - private final MessageNotificationMapper notificationMapper; + private final NotificationMapper notificationMapper; @Override public List notifyTopicSubscribers(Integer topicId) { log.trace("Started notifyTopicSubscribers by topic id [{}]", topicId); return contactEventService.getAllByTopicId(topicId).stream() - .map(notificationMapper::toNotificationResponseDto) + .map(notificationMapper::toMessageNotificationResponseDto) .toList(); } @Override - public List notifyAllPublicTopicsByEmail(String email) { - - return topicService.findAllPublic().stream() - .map(topic -> { - var event = contactEventService.getByTopicIdAndEmail(topic.getId(), email); - var topicNotificationDto = new TopicNotificationResponseDto(); - topicNotificationDto.setTopic(topic); - topicNotificationDto.setUnreadMessages(countUnreadMessages(event)); - topicNotificationDto.setLastMessage(event.getLastMessage()); - return topicNotificationDto; - }) + public List notifyAllTopicsByEmail(String email) { + + return contactEventService.getAllByEmail(email).stream() + .peek(this::countUnreadMessages) + .map(notificationMapper::toTopicNotificationResponseDto) + .toList(); + } + + @Override + public List updateTopicNotification(String email) { + return contactEventService.getAllByEmail(email).stream() + .map(notificationMapper::toTopicNotificationResponseDto) .toList(); } - private int countUnreadMessages(ContactEvent event) { - return messageService.countMessagesBetweenTimestampByTopicId( + private void countUnreadMessages(ContactEvent event) { + event.setUnreadMessages(messageService.countMessagesBetweenTimestampByTopicId( event.getTopicId(), event.getEmail(), - event.getTimestamp()); + event.getTimestamp())); + contactEventService.save(event); } } diff --git a/src/main/java/com/chat/yourway/service/interfaces/ChatNotificationService.java b/src/main/java/com/chat/yourway/service/interfaces/ChatNotificationService.java index aef3056a..d05ff51f 100644 --- a/src/main/java/com/chat/yourway/service/interfaces/ChatNotificationService.java +++ b/src/main/java/com/chat/yourway/service/interfaces/ChatNotificationService.java @@ -21,7 +21,7 @@ public interface ChatNotificationService { * * @param userEmail user email. */ - void notifyAllPublicTopics(String userEmail); + void notifyAllTopics(String userEmail); /** * Notify everyone who is subscribed to the same topic. @@ -30,4 +30,18 @@ public interface ChatNotificationService { */ void notifyAllWhoSubscribedToTopic(Integer topicId); + /** + * Update topic notification for user who subscribed to the same topic. + * + * @param topicId The id of the topic. + */ + void updateNotificationForAllWhoSubscribedToTopic(Integer topicId); + + /** + * Update notification for all topics. + * + * @param email user email. + */ + void updateNotificationForAllTopics(String email); + } diff --git a/src/main/java/com/chat/yourway/service/interfaces/ContactEventService.java b/src/main/java/com/chat/yourway/service/interfaces/ContactEventService.java index ae199c9f..69f225ff 100644 --- a/src/main/java/com/chat/yourway/service/interfaces/ContactEventService.java +++ b/src/main/java/com/chat/yourway/service/interfaces/ContactEventService.java @@ -47,6 +47,6 @@ public interface ContactEventService { * @param topicId topic id. * @param lastMessageDto last message Dto. */ - void setLastMessageToAllTopicSubscribers(Integer topicId, LastMessageResponseDto lastMessageDto); + void updateMessageInfoForAllTopicSubscribers(Integer topicId, LastMessageResponseDto lastMessageDto); } diff --git a/src/main/java/com/chat/yourway/service/interfaces/NotificationService.java b/src/main/java/com/chat/yourway/service/interfaces/NotificationService.java index a14ab271..b549bc63 100644 --- a/src/main/java/com/chat/yourway/service/interfaces/NotificationService.java +++ b/src/main/java/com/chat/yourway/service/interfaces/NotificationService.java @@ -15,11 +15,19 @@ public interface NotificationService { List notifyTopicSubscribers(Integer topicId); /** - * Retrieves a list of notifying all public topics. + * Retrieves a list of notifying all topics. * * @param email user email. - * @return A list of public topic's information. + * @return A list of topic's information. */ - List notifyAllPublicTopicsByEmail(String email); + List notifyAllTopicsByEmail(String email); + + /** + * Update info and return a list of notifying all topics. + * + * @param email user email. + * @return A list of topic's information. + */ + List updateTopicNotification(String email); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index ecf8cbc5..7255fc40 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -16,7 +16,7 @@ spring.data.redis.password=${REDIS_PASSWORD:admin} #Hibernate spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect -#spring.jpa.show-sql=true +spring.jpa.show-sql=false spring.jpa.properties.hibernate.format_sql=true spring.jpa.hibernate.ddl-auto=validate @@ -59,5 +59,5 @@ spring.mail.properties.mail.smtp.starttls.required=true message.max.amount.reports=2 #Logging: -logging.level.com.chat.yourway=${LOGGING_LEVEL:trace} +logging.level.com.chat.yourway=${LOGGING_LEVEL:info} diff --git a/src/test/java/com/chat/yourway/integration/controller/ChatControllerTest.java b/src/test/java/com/chat/yourway/integration/controller/ChatControllerTest.java index 86063ceb..6d2ab90f 100644 --- a/src/test/java/com/chat/yourway/integration/controller/ChatControllerTest.java +++ b/src/test/java/com/chat/yourway/integration/controller/ChatControllerTest.java @@ -202,7 +202,7 @@ void notifyTopicSubscribers_shouldNotifyTopicSubscribersIfSubscribeEvent() { lastMessageDto.setSentFrom("vasil@gmail.com"); lastMessageDto.setLastMessage("Hi"); - var event = new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), + var event = new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), 0, lastMessageDto); saveContactEvent(event); //Stored subscription results for testing @@ -233,7 +233,7 @@ void notifyTopicSubscribers_shouldNotifyTopicSubscribersIfAnyContactSubscribedTo lastMessageDto.setSentFrom("vasil@gmail.com"); lastMessageDto.setLastMessage("Hi"); - var event = new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), + var event = new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), 0, lastMessageDto); saveContactEvent(event); //Stored subscription results for testing diff --git a/src/test/java/com/chat/yourway/unit/service/impl/ContactEventServiceImplTest.java b/src/test/java/com/chat/yourway/unit/service/impl/ContactEventServiceImplTest.java index da8fb7b5..7c263f01 100644 --- a/src/test/java/com/chat/yourway/unit/service/impl/ContactEventServiceImplTest.java +++ b/src/test/java/com/chat/yourway/unit/service/impl/ContactEventServiceImplTest.java @@ -41,7 +41,8 @@ void save_shouldSaveToRepository() { // Given String email = "vasil@gmail.com"; int topicId = 1; - ContactEvent contactEvent = new ContactEvent(email, topicId, ONLINE, LocalDateTime.now(), null); + ContactEvent contactEvent = new ContactEvent(email, topicId, ONLINE, LocalDateTime.now(), 0, + null); // When contactEventService.save(contactEvent); @@ -56,7 +57,8 @@ void getByTopicIdAndEmail_shouldReturnContactEventFromRepository() { // Given Integer topicId = 1; String email = "vasil@gmail.com"; - ContactEvent expectedContactEvent = new ContactEvent(email, topicId, ONLINE, LocalDateTime.now(), null); + ContactEvent expectedContactEvent = new ContactEvent(email, topicId, ONLINE, + LocalDateTime.now(), 0, null); when(contactEventRedisRepository.findById(email + "_" + topicId)) .thenReturn(Optional.of(expectedContactEvent)); @@ -91,8 +93,8 @@ void getAllByEmail_shouldReturnContactEventsFromRepository() { // Given String email = "vasil@gmail.com"; List expectedContactEvents = Arrays.asList( - new ContactEvent(email, 1, ONLINE, LocalDateTime.now(), null), - new ContactEvent(email, 2, OFFLINE, LocalDateTime.now(), null) + new ContactEvent(email, 1, ONLINE, LocalDateTime.now(), 0, null), + new ContactEvent(email, 2, OFFLINE, LocalDateTime.now(), 0, null) ); when(contactEventRedisRepository.findAllByEmail(email)).thenReturn(expectedContactEvents); @@ -110,8 +112,8 @@ void updateEventTypeByEmail_shouldUpdateEventTypesInRepository() { String email = "vasil@gmail.com"; EventType newEventType = OFFLINE; List events = Arrays.asList( - new ContactEvent(email, 1, ONLINE, LocalDateTime.now(), null), - new ContactEvent(email, 2, ONLINE, LocalDateTime.now(), null) + new ContactEvent(email, 1, ONLINE, LocalDateTime.now(), 0, null), + new ContactEvent(email, 2, ONLINE, LocalDateTime.now(), 0, null) ); when(contactEventRedisRepository.findAllByEmail(email)).thenReturn(events); @@ -129,8 +131,8 @@ void getAllByTopicId_shouldReturnContactEventsFromRepository() { // Given Integer topicId = 1; List expectedContactEvents = Arrays.asList( - new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), null), - new ContactEvent("anton@gmail.com", topicId, OFFLINE, LocalDateTime.now(), null) + new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), 0, null), + new ContactEvent("anton@gmail.com", topicId, OFFLINE, LocalDateTime.now(), 0, null) ); when(contactEventRedisRepository.findAllByTopicId(topicId)).thenReturn(expectedContactEvents); @@ -152,13 +154,13 @@ void setLastMessageToAllTopicSubscribers_shouldUpdateLastMessagesInRepository() lastMessageDto.setLastMessage("New message"); List events = Arrays.asList( - new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), null), - new ContactEvent("anton@gmail.com", topicId, OFFLINE, LocalDateTime.now(), null) + new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), 0, null), + new ContactEvent("anton@gmail.com", topicId, OFFLINE, LocalDateTime.now(), 0, null) ); when(contactEventRedisRepository.findAllByTopicId(topicId)).thenReturn(events); // When - contactEventService.setLastMessageToAllTopicSubscribers(topicId, lastMessageDto); + contactEventService.updateMessageInfoForAllTopicSubscribers(topicId, lastMessageDto); // Then events.forEach(e -> e.setLastMessage(lastMessageDto)); diff --git a/src/test/java/com/chat/yourway/unit/service/impl/NotificationServiceImplTest.java b/src/test/java/com/chat/yourway/unit/service/impl/NotificationServiceImplTest.java index dde09bcd..ab82a331 100644 --- a/src/test/java/com/chat/yourway/unit/service/impl/NotificationServiceImplTest.java +++ b/src/test/java/com/chat/yourway/unit/service/impl/NotificationServiceImplTest.java @@ -10,7 +10,7 @@ import com.chat.yourway.dto.response.LastMessageResponseDto; import com.chat.yourway.dto.response.MessageNotificationResponseDto; -import com.chat.yourway.mapper.MessageNotificationMapper; +import com.chat.yourway.mapper.NotificationMapper; import com.chat.yourway.model.event.ContactEvent; import com.chat.yourway.service.NotificationServiceImpl; import com.chat.yourway.service.interfaces.ContactEventService; @@ -31,7 +31,7 @@ class NotificationServiceImplTest { private ContactEventService contactEventService; @Mock - private MessageNotificationMapper notificationMapper; + private NotificationMapper notificationMapper; @InjectMocks private NotificationServiceImpl notificationService; @@ -47,8 +47,8 @@ void notifyTopicSubscribers_shouldReturnListOfNotifications() { lastMessageDto.setLastMessage("Hello"); List events = Arrays.asList( - new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), lastMessageDto), - new ContactEvent("anton@gmail.com", topicId, OFFLINE, LocalDateTime.now(), lastMessageDto) + new ContactEvent("vasil@gmail.com", topicId, ONLINE, LocalDateTime.now(), 0, lastMessageDto), + new ContactEvent("anton@gmail.com", topicId, OFFLINE, LocalDateTime.now(), 0, lastMessageDto) ); var expectedNotifications = events.stream() @@ -63,7 +63,7 @@ void notifyTopicSubscribers_shouldReturnListOfNotifications() { .toList(); when(contactEventService.getAllByTopicId(topicId)).thenReturn(events); - when(notificationMapper.toNotificationResponseDto(any())) + when(notificationMapper.toMessageNotificationResponseDto(any())) .thenReturn(expectedNotifications.get(0), expectedNotifications.get(1)); // When @@ -72,7 +72,7 @@ void notifyTopicSubscribers_shouldReturnListOfNotifications() { // Then assertEquals(expectedNotifications, result, "Should return the expected list of notifications"); - verify(notificationMapper, times(2)).toNotificationResponseDto(any()); + verify(notificationMapper, times(2)).toMessageNotificationResponseDto(any()); } } From 1abe15dacea65d767e0b604acabf57232a7db0b7 Mon Sep 17 00:00:00 2001 From: Dmytro Trotsenko Date: Thu, 28 Mar 2024 22:30:59 +0200 Subject: [PATCH 4/4] refactor: refactored and optimized request to get all topics --- .../yourway/controller/TopicController.java | 7 ++-- .../dto/response/TopicInfoResponseDto.java | 26 ++++++++++++++ .../com/chat/yourway/mapper/TopicMapper.java | 3 ++ .../java/com/chat/yourway/model/Topic.java | 4 +-- .../yourway/repository/TopicRepository.java | 26 +++++++------- .../yourway/service/TopicServiceImpl.java | 13 +++---- .../service/interfaces/TopicService.java | 35 +++++++++---------- .../controller/TopicControllerTest.java | 6 +--- .../service/impl/TopicServiceImplTest.java | 11 ++++-- 9 files changed, 81 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/chat/yourway/dto/response/TopicInfoResponseDto.java diff --git a/src/main/java/com/chat/yourway/controller/TopicController.java b/src/main/java/com/chat/yourway/controller/TopicController.java index 5bc7f297..ad7f6117 100644 --- a/src/main/java/com/chat/yourway/controller/TopicController.java +++ b/src/main/java/com/chat/yourway/controller/TopicController.java @@ -8,6 +8,7 @@ import com.chat.yourway.dto.request.TopicRequestDto; import com.chat.yourway.dto.response.ApiErrorResponseDto; import com.chat.yourway.dto.response.ContactResponseDto; +import com.chat.yourway.dto.response.TopicInfoResponseDto; import com.chat.yourway.dto.response.TopicResponseDto; import com.chat.yourway.service.interfaces.TopicService; import com.chat.yourway.service.interfaces.TopicSubscriberService; @@ -149,7 +150,7 @@ public TopicResponseDto findById(@PathVariable Integer id) { content = @Content(schema = @Schema(implementation = ApiErrorResponseDto.class))) }) @GetMapping(path = "/all", produces = APPLICATION_JSON_VALUE) - public List findAllPublic() { + public List findAllPublic() { return topicService.findAllPublic(); } @@ -322,7 +323,7 @@ public void removeToFavouriteTopic( content = @Content(schema = @Schema(implementation = ApiErrorResponseDto.class))) }) @GetMapping(path = "/favourite", produces = APPLICATION_JSON_VALUE) - public List findAllFavouriteTopics( + public List findAllFavouriteTopics( @AuthenticationPrincipal UserDetails userDetails) { return topicService.findAllFavouriteTopics(userDetails); } @@ -333,7 +334,7 @@ public List findAllFavouriteTopics( @ApiResponse(responseCode = "200", description = SUCCESSFULLY_FOUND_TOPIC) }) @GetMapping(path = "/popular/public", produces = APPLICATION_JSON_VALUE) - public List findAllPopularPublicTopics() { + public List findAllPopularPublicTopics() { return topicService.findPopularPublicTopics(); } diff --git a/src/main/java/com/chat/yourway/dto/response/TopicInfoResponseDto.java b/src/main/java/com/chat/yourway/dto/response/TopicInfoResponseDto.java new file mode 100644 index 00000000..d1dec5db --- /dev/null +++ b/src/main/java/com/chat/yourway/dto/response/TopicInfoResponseDto.java @@ -0,0 +1,26 @@ +package com.chat.yourway.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@AllArgsConstructor +@NoArgsConstructor +@Setter +@Getter +@ToString +public class TopicInfoResponseDto { + @Schema(description = "ID", example = "1") + private Integer id; + @Schema(description = "New Topic name", example = "My programming topic") + private String topicName; + @Schema(description = "Email of Topic creator", example = "example@gmail.com") + private String createdBy; + @Schema(description = "Created time") + private LocalDateTime createdAt; + +} diff --git a/src/main/java/com/chat/yourway/mapper/TopicMapper.java b/src/main/java/com/chat/yourway/mapper/TopicMapper.java index 0d71fb5e..2dff6d6e 100644 --- a/src/main/java/com/chat/yourway/mapper/TopicMapper.java +++ b/src/main/java/com/chat/yourway/mapper/TopicMapper.java @@ -1,5 +1,6 @@ package com.chat.yourway.mapper; +import com.chat.yourway.dto.response.TopicInfoResponseDto; import com.chat.yourway.dto.response.TopicResponseDto; import com.chat.yourway.model.Topic; import java.util.List; @@ -12,6 +13,8 @@ public interface TopicMapper { TopicResponseDto toResponseDto(Topic topic); List toListResponseDto(List topics); + List toListInfoResponseDto(List topics); + @Mapping(target = "messages", ignore = true) Topic toEntity(TopicResponseDto topicResponseDto); diff --git a/src/main/java/com/chat/yourway/model/Topic.java b/src/main/java/com/chat/yourway/model/Topic.java index 0eca84d3..1e05c306 100644 --- a/src/main/java/com/chat/yourway/model/Topic.java +++ b/src/main/java/com/chat/yourway/model/Topic.java @@ -48,7 +48,7 @@ public class Topic { @Column(name = "created_at", nullable = false) private LocalDateTime createdAt; - @ManyToMany(fetch = FetchType.EAGER) + @ManyToMany(fetch = FetchType.LAZY) @JoinTable( schema = "chat", name = "topic_tag", @@ -56,7 +56,7 @@ public class Topic { inverseJoinColumns = @JoinColumn(name = "tag_id")) private Set tags; - @OneToMany(mappedBy = "topic", fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @OneToMany(mappedBy = "topic", fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Set topicSubscribers; @OneToMany(mappedBy = "topic", fetch = FetchType.LAZY, cascade = CascadeType.ALL) diff --git a/src/main/java/com/chat/yourway/repository/TopicRepository.java b/src/main/java/com/chat/yourway/repository/TopicRepository.java index 5c0a0b53..de34ae69 100644 --- a/src/main/java/com/chat/yourway/repository/TopicRepository.java +++ b/src/main/java/com/chat/yourway/repository/TopicRepository.java @@ -18,10 +18,10 @@ public interface TopicRepository extends JpaRepository { @Query( value = """ - SELECT * - FROM chat.topic t - WHERE to_tsvector('english', t.topic_name) @@ to_tsquery('english', :query) - """, + SELECT * + FROM chat.topic t + WHERE to_tsvector('english', t.topic_name) @@ to_tsquery('english', :query) + """, nativeQuery = true) List findAllByTopicName(String query); @@ -31,18 +31,16 @@ WHERE to_tsvector('english', t.topic_name) @@ to_tsquery('english', :query) @Query( "select t from Topic t join fetch t.topicSubscribers ts " - + "where ts.contact.email = :contactEmail and ts.isFavouriteTopic = true") + + "where ts.contact.email = :contactEmail and ts.isFavouriteTopic = true") List findAllFavouriteTopicsByContactEmail(String contactEmail); - boolean existsByIdAndIsPublic(int topicId, boolean isPublic); - @Query(nativeQuery = true, value = - "SELECT t.*, COUNT(ts.id) AS ts_count, COUNT(m.id) AS m_count " + - "FROM chat.topic t " + - "JOIN chat.topic_subscriber ts ON t.id = ts.topic_id " + - "JOIN chat.message m ON t.id = m.topic_id " + - "WHERE t.is_public = true " + - "GROUP BY t.id " + - "ORDER BY ts_count DESC, m_count DESC") + "SELECT t.*, COUNT(ts.id) AS ts_count, COUNT(m.id) AS m_count " + + "FROM chat.topic t " + + "JOIN chat.topic_subscriber ts ON t.id = ts.topic_id " + + "JOIN chat.message m ON t.id = m.topic_id " + + "WHERE t.is_public = true " + + "GROUP BY t.id " + + "ORDER BY ts_count DESC, m_count DESC") List findPopularPublicTopics(); } diff --git a/src/main/java/com/chat/yourway/service/TopicServiceImpl.java b/src/main/java/com/chat/yourway/service/TopicServiceImpl.java index 60ad4913..2470e70f 100644 --- a/src/main/java/com/chat/yourway/service/TopicServiceImpl.java +++ b/src/main/java/com/chat/yourway/service/TopicServiceImpl.java @@ -5,6 +5,7 @@ import com.chat.yourway.dto.request.TagRequestDto; import com.chat.yourway.dto.request.TopicPrivateRequestDto; import com.chat.yourway.dto.request.TopicRequestDto; +import com.chat.yourway.dto.response.TopicInfoResponseDto; import com.chat.yourway.dto.response.TopicResponseDto; import com.chat.yourway.exception.ContactEmailNotExist; import com.chat.yourway.exception.TopicAccessException; @@ -100,13 +101,13 @@ public TopicResponseDto findByName(String name) { } @Override - public List findAllPublic() { + public List findAllPublic() { log.trace("Started findAllPublic"); List topics = topicRepository.findAllByIsPublicIsTrue(); log.trace("All public topics was found"); - return topicMapper.toListResponseDto(topics); + return topicMapper.toListInfoResponseDto(topics); } @Override @@ -173,15 +174,15 @@ public String generatePrivateName(String sendTo, String email) { } @Override - public List findAllFavouriteTopics(UserDetails userDetails) { + public List findAllFavouriteTopics(UserDetails userDetails) { String contactEmail = userDetails.getUsername(); - return topicMapper.toListResponseDto( + return topicMapper.toListInfoResponseDto( topicRepository.findAllFavouriteTopicsByContactEmail(contactEmail)); } @Override - public List findPopularPublicTopics() { - return topicMapper.toListResponseDto(topicRepository.findPopularPublicTopics()); + public List findPopularPublicTopics() { + return topicMapper.toListInfoResponseDto(topicRepository.findPopularPublicTopics()); } private Topic createOrUpdateTopic(Topic topic, TopicRequestDto topicRequestDto, String email) { diff --git a/src/main/java/com/chat/yourway/service/interfaces/TopicService.java b/src/main/java/com/chat/yourway/service/interfaces/TopicService.java index 41e1c974..3e305d8a 100644 --- a/src/main/java/com/chat/yourway/service/interfaces/TopicService.java +++ b/src/main/java/com/chat/yourway/service/interfaces/TopicService.java @@ -3,16 +3,15 @@ import com.chat.yourway.dto.request.TagRequestDto; import com.chat.yourway.dto.request.TopicPrivateRequestDto; import com.chat.yourway.dto.request.TopicRequestDto; +import com.chat.yourway.dto.response.TopicInfoResponseDto; import com.chat.yourway.dto.response.TopicResponseDto; import com.chat.yourway.exception.TopicAccessException; import com.chat.yourway.exception.TopicNotFoundException; import com.chat.yourway.exception.ValueNotUniqException; import com.chat.yourway.model.Tag; -import com.chat.yourway.model.Topic; -import org.springframework.security.core.userdetails.UserDetails; - import java.util.List; import java.util.Set; +import org.springframework.security.core.userdetails.UserDetails; public interface TopicService { @@ -20,7 +19,7 @@ public interface TopicService { * Creates a new topic with the specified email of the creator. * * @param topicRequestDto Request object for creating topic. - * @param email The email of the creator. + * @param email The email of the creator. * @return Created topic. * @throws ValueNotUniqException If the topic name already in use. */ @@ -31,7 +30,7 @@ public interface TopicService { * contacts. * * @param topicPrivateDto Request object for creating topic. - * @param email The email of the creator. + * @param email The email of the creator. * @return Created private topic. * @throws ValueNotUniqException If the topic name already in use. */ @@ -40,12 +39,12 @@ public interface TopicService { /** * Update an existing topic with the specified email of the creator. * - * @param topicId The ID of the topic to find. + * @param topicId The ID of the topic to find. * @param topicRequestDto Request object for creating topic. - * @param email The email of the creator. + * @param email The email of the creator. * @return Updated topic. * @throws ValueNotUniqException If the topic name already in use. - * @throws TopicAccessException if the email is not the creator of the topic. + * @throws TopicAccessException if the email is not the creator of the topic. */ TopicResponseDto update(Integer topicId, TopicRequestDto topicRequestDto, String email); @@ -72,12 +71,12 @@ public interface TopicService { * * @return A list of public topics. */ - List findAllPublic(); + List findAllPublic(); /** * Deletes a topic by ID if the specified email is the creator of the topic. * - * @param id The ID of the topic to delete. + * @param id The ID of the topic to delete. * @param email The email of the user. * @throws TopicAccessException if the email is not the creator of the topic. */ @@ -88,7 +87,7 @@ public interface TopicService { * * @param tagName The unique name of the tag for which topics are to be retrieved. * @return A list of {@link TopicResponseDto} objects associated with the given tag. An empty list - * is returned if no topics are found for the specified tag. + * is returned if no topics are found for the specified tag. */ List findTopicsByTagName(String tagName); @@ -116,7 +115,7 @@ public interface TopicService { * separated by "<->" symbol. * * @param sendTo Email address of the receiver. - * @param email Email address of the sender. + * @param email Email address of the sender. * @return Unique private topic name. */ String generatePrivateName(String sendTo, String email); @@ -125,20 +124,20 @@ public interface TopicService { * Retrieves a list of favorite topics for the specified user. * * @param userDetails The details of the user for whom favorite topics are to be retrieved. - * @return A list of {@code TopicResponseDto} objects representing the user's favorite topics. + * @return A list of {@code TopicInfoResponseDto} objects representing the user's favorite topics. */ - List findAllFavouriteTopics(UserDetails userDetails); + List findAllFavouriteTopics(UserDetails userDetails); /** * Retrieves a list of popular public topics. *

- * This method returns a list of {@code TopicResponseDto} objects representing popular topics - * that are marked as public. The popularity is determined by the number of subscribers and messages + * This method returns a list of {@code TopicResponseDto} objects representing popular topics that + * are marked as public. The popularity is determined by the number of subscribers and messages * associated with each topic. * - * @return A list of {@code TopicResponseDto} objects representing popular public topics. + * @return A list of {@code TopicInfoResponseDto} objects representing popular public topics. * @see TopicResponseDto */ - List findPopularPublicTopics(); + List findPopularPublicTopics(); } diff --git a/src/test/java/com/chat/yourway/integration/controller/TopicControllerTest.java b/src/test/java/com/chat/yourway/integration/controller/TopicControllerTest.java index 299d1673..95b3a676 100644 --- a/src/test/java/com/chat/yourway/integration/controller/TopicControllerTest.java +++ b/src/test/java/com/chat/yourway/integration/controller/TopicControllerTest.java @@ -515,11 +515,7 @@ public void findAllPublic_shouldReturnListOfAllPublicTopics() throws Exception { .andExpect(jsonPath("$[0].createdBy").value(savedTopics.get(0).getCreatedBy())) .andExpect(jsonPath("$[1].topicName").value(savedTopics.get(1).getTopicName())) .andExpect(jsonPath("$[1].createdBy").value(savedTopics.get(1).getCreatedBy())) - .andExpect(jsonPath("$[*].createdAt").isNotEmpty()) - .andExpect(jsonPath("$[0].isPublic").value(true)) - .andExpect(jsonPath("$[1].isPublic").value(true)) - .andExpect(jsonPath("$[*].tags").isArray()) - .andExpect(jsonPath("$[*].topicSubscribers").isArray()); + .andExpect(jsonPath("$[*].createdAt").isNotEmpty()); } @Test diff --git a/src/test/java/com/chat/yourway/unit/service/impl/TopicServiceImplTest.java b/src/test/java/com/chat/yourway/unit/service/impl/TopicServiceImplTest.java index 5d113a5d..3fdbcf92 100644 --- a/src/test/java/com/chat/yourway/unit/service/impl/TopicServiceImplTest.java +++ b/src/test/java/com/chat/yourway/unit/service/impl/TopicServiceImplTest.java @@ -17,6 +17,7 @@ import com.chat.yourway.dto.request.TopicPrivateRequestDto; import com.chat.yourway.dto.request.TopicRequestDto; import com.chat.yourway.dto.response.TagResponseDto; +import com.chat.yourway.dto.response.TopicInfoResponseDto; import com.chat.yourway.dto.response.TopicResponseDto; import com.chat.yourway.exception.TopicAccessException; import com.chat.yourway.exception.TopicNotFoundException; @@ -351,7 +352,7 @@ public void findAllPublic_shouldReturnListOfTopicResponseDto() { when(topicRepository.findAllByIsPublicIsTrue()).thenReturn(topics); // When - List topicResponseDtos = topicService.findAllPublic(); + List topicResponseDtos = topicService.findAllPublic(); // Then assertThat(topicResponseDtos).isNotNull(); @@ -369,7 +370,7 @@ public void findAllPublic_shouldReturnEmptyListOfTopicResponseDto() { when(topicRepository.findAllByIsPublicIsTrue()).thenReturn(emptyList); // When - List topicResponseDtos = topicService.findAllPublic(); + List topicResponseDtos = topicService.findAllPublic(); // Then assertThat(topicResponseDtos).isNotNull(); @@ -486,4 +487,10 @@ private void assertTopicEquals(Topic topic, TopicResponseDto topicResponseDto) { assertThat(topicResponseDto.getTopicSubscribers()).isNull(); } + private void assertTopicEquals(Topic topic, TopicInfoResponseDto topicResponseDto) { + assertThat(topicResponseDto.getTopicName()).isEqualTo(topic.getTopicName()); + assertThat(topicResponseDto.getCreatedBy()).isEqualTo(topic.getCreatedBy()); + assertThat(topicResponseDto.getCreatedAt()).isEqualTo(topic.getCreatedAt()); + } + }