Skip to content

Commit

Permalink
Merge pull request #28 from Chat-Your-Way/CHAT-52--message-routing
Browse files Browse the repository at this point in the history
Chat 52  message routing
  • Loading branch information
Troha7 authored Nov 2, 2023
2 parents 5e28a33 + 2117094 commit 29e6b39
Show file tree
Hide file tree
Showing 26 changed files with 516 additions and 103 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@
<version>1.6.4</version>
</dependency>

<!--Configuration processor-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>3.1.5</version>
</dependency>

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.chat.yourway.config;
package com.chat.yourway.config.redis;

import com.chat.yourway.model.token.Token;
import org.springframework.beans.factory.annotation.Value;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
Expand All @@ -11,21 +11,18 @@
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@RequiredArgsConstructor
public class RedisConfig {

@Value("${spring.data.redis.host}")
private String redisHost;

@Value("${spring.data.redis.port}")
private int redisPort;

@Value("${spring.data.redis.password}")
private String redisPassword;
private final RedisProperties properties;

@Bean
public JedisConnectionFactory jedisConnectionFactory() {
var redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHost, redisPort);
redisStandaloneConfiguration.setPassword(redisPassword);
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(
properties.getHost(), properties.getPort());
if (properties.getProfile().equals("prod")) {
redisStandaloneConfiguration.setPassword(properties.getPassword());
}
return new JedisConnectionFactory(redisStandaloneConfiguration);
}

Expand Down
22 changes: 22 additions & 0 deletions src/main/java/com/chat/yourway/config/redis/RedisProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.chat.yourway.config.redis;

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "spring.data.redis")
@Getter
@Setter
public class RedisProperties {

private String host;
private int port;
private String password;

@Value("${spring.profiles.active}")
private String profile;

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
Expand Down Expand Up @@ -52,7 +51,7 @@ public class SecurityFilterConfig {
"/ws/**", "/chat/**",

//Other
"/"
"/*"
};

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.chat.yourway.config;
package com.chat.yourway.config.websocket;

import org.springframework.beans.factory.annotation.Value;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
Expand All @@ -9,26 +9,20 @@

@Configuration
@EnableWebSocketMessageBroker
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

@Value("${socket.dest-prefixes}")
private String[] destPrefixes;

@Value("${socket.app-prefix}")
private String appPrefix;

@Value("${socket.endpoint}")
private String endpoint;
private final WebsocketProperties properties;

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker(destPrefixes);
registry.setApplicationDestinationPrefixes(appPrefix);
registry.enableSimpleBroker(properties.getDestPrefixes());
registry.setApplicationDestinationPrefixes(properties.getAppPrefix());
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint(endpoint);
registry.addEndpoint(endpoint).withSockJS();
registry.addEndpoint(properties.getEndpoint());
registry.addEndpoint(properties.getEndpoint()).withSockJS();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.chat.yourway.config.websocket;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "socket")
@Getter
@Setter
public class WebsocketProperties {

private String[] destPrefixes;
private String appPrefix;
private String endpoint;

}
6 changes: 6 additions & 0 deletions src/main/java/com/chat/yourway/controller/ChatController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.chat.yourway.dto.response.MessageResponseDto;
import com.chat.yourway.service.interfaces.ChatMessageService;
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
Expand Down Expand Up @@ -32,4 +33,9 @@ public MessageResponseDto sendToContact(@Valid @Payload MessagePrivateRequestDto
String email = principal.getName();
return chatMessageService.sendToContact(message, email);
}

@MessageMapping("/get/messages/{topicId}")
public List<MessageResponseDto> getMessages(@DestinationVariable Integer topicId) {
return chatMessageService.getMessages(topicId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.chat.yourway.dto.response;

import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@AllArgsConstructor
@Getter
@ToString
public class MessageErrorResponseDto<T> {

private final LocalDateTime timestamp = LocalDateTime.now();
private final String sentFrom = "Server";
private T message;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.chat.yourway.exception.handler;

import com.chat.yourway.dto.response.MessageErrorResponseDto;
import com.chat.yourway.exception.TopicNotFoundException;
import com.chat.yourway.exception.TopicSubscriberNotFoundException;
import java.util.List;
import java.util.Objects;
import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;

@ControllerAdvice
public class WebsocketExceptionHandler {

@MessageExceptionHandler({
TopicNotFoundException.class,
TopicSubscriberNotFoundException.class
})
@SendToUser("/specific")
public MessageErrorResponseDto<String> handleException(RuntimeException e) {
return new MessageErrorResponseDto<>(e.getMessage());
}

@MessageExceptionHandler(MethodArgumentNotValidException.class)
@SendToUser("/specific")
public MessageErrorResponseDto<List<String>> handleValidationException(
MethodArgumentNotValidException e) {
List<FieldError> fieldErrors = Objects.requireNonNull(e.getBindingResult()).getFieldErrors();
List<String> errorMessages = fieldErrors.stream()
.map(err -> String.format("Invalid '%s': %s", err.getField(), err.getDefaultMessage()))
.toList();
return new MessageErrorResponseDto<>(errorMessages);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.chat.yourway.dto.response.MessageResponseDto;
import com.chat.yourway.service.interfaces.ChatMessageService;
import com.chat.yourway.service.interfaces.MessageService;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -25,7 +26,8 @@ public class ChatMessageServiceImpl implements ChatMessageService {

@Transactional
@Override
public MessageResponseDto sendToTopic(Integer topicId, MessagePublicRequestDto message, String email) {
public MessageResponseDto sendToTopic(Integer topicId, MessagePublicRequestDto message,
String email) {
log.trace("Started contact email: {} sendToTopic id: {}", email, topicId);
MessageResponseDto messageResponseDto = messageService.createPublic(topicId, message, email);

Expand All @@ -48,6 +50,18 @@ public MessageResponseDto sendToContact(MessagePrivateRequestDto message, String
return messageResponseDto;
}

@Override
public List<MessageResponseDto> getMessages(Integer topicId) {
log.trace("Started getMessages for topicId={}", topicId);

List<MessageResponseDto> messages = messageService.findAllByTopicId(topicId);
simpMessagingTemplate.convertAndSend(toTopicDestination(topicId), messages);

log.trace("All messages send to topicId={}", topicId);

return messages;
}

private String toTopicDestination(Integer topicId) {
return destPrefixes[0] + "/" + topicId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.chat.yourway.dto.request.MessagePrivateRequestDto;
import com.chat.yourway.dto.request.MessagePublicRequestDto;
import com.chat.yourway.dto.response.MessageResponseDto;
import java.util.List;

public interface ChatMessageService {

Expand All @@ -25,4 +26,12 @@ MessageResponseDto sendToTopic(Integer topicId, MessagePublicRequestDto messageP
* @return {@link MessageResponseDto} is the sent message.
*/
MessageResponseDto sendToContact(MessagePrivateRequestDto messagePrivateRequestDto, String email);

/**
* Get all messages by topic id.
*
* @param topicId The id of the topic.
* @return {@link MessageResponseDto} is the all got messages.
*/
List<MessageResponseDto> getMessages(Integer topicId);
}
6 changes: 5 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Spring Profile:
spring.profiles.active=prod

#Server port:
server.port=${PORT:8080}

Expand Down Expand Up @@ -51,5 +54,6 @@ spring.mail.properties.mail.smtp.starttls.required=true
# Message values
message.max.amount.reports=2

logging.level.com.chat.yourway=trace
#Logging:
logging.level.com.chat.yourway=info

Loading

0 comments on commit 29e6b39

Please sign in to comment.