Starting WebSocket

This commit is contained in:
PEDSF 2020-11-01 09:23:29 +01:00
parent 8755ca9cf1
commit ad9d5f513c
9 changed files with 280 additions and 24 deletions

102
pom.xml
View file

@ -14,6 +14,9 @@
<version>2.3.3.RELEASE</version>
</parent>
<!-- ===================================================================== -->
<!-- PROPERTIES -->
<!-- ===================================================================== -->
<properties>
<!-- Generic properties -->
<java.version>1.8</java.version>
@ -26,13 +29,22 @@
<webjars-jquery.version>2.2.4</webjars-jquery.version>
<wro4j.version>1.8.0</wro4j.version>
<checkstyle.version>8.32</checkstyle.version>
<jacoco.version>0.8.5</jacoco.version>
<junit.version>4.13</junit.version>
<lifecycle-mapping.version>1.0.0</lifecycle-mapping.version>
<lombok.version>1.18.12</lombok.version>
<maven-checkstyle-plugin.version>3.1.1</maven-checkstyle-plugin.version>
<modelmapper.version>2.3.8</modelmapper.version>
<nohttp-checkstyle.version>0.0.4.RELEASE</nohttp-checkstyle.version>
<spring-format.version>0.0.25</spring-format.version>
</properties>
<!-- ===================================================================== -->
<!-- DEPENDENCIES -->
<!-- ===================================================================== -->
<dependencies>
<!-- Spring and Spring Boot dependencies -->
<!-- ============================================================ SPRING -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
@ -57,6 +69,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
@ -69,15 +85,7 @@
</exclusions>
</dependency>
<!-- ================================================== MODELMAPPER -->
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.8</version>
<scope>compile</scope>
</dependency>
<!-- Databases - Uses H2 by default -->
<!-- ========================================================= DATABASES -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
@ -89,6 +97,15 @@
<scope>runtime</scope>
</dependency>
<!-- ======================================================= MODELMAPPER -->
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>${modelmapper.version}</version>
<scope>compile</scope>
</dependency>
<!-- caching -->
<dependency>
<groupId>javax.cache</groupId>
@ -100,6 +117,12 @@
</dependency>
<!-- webjars -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.40</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
@ -119,9 +142,35 @@
<artifactId>bootstrap</artifactId>
<version>${webjars-bootstrap.version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>stomp-websocket</artifactId>
<version>2.3.3-1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.1.2</version>
</dependency>
<!-- end of webjars -->
<!-- Testing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
<!-- =========================================================== TESTING -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
@ -141,17 +190,20 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>test</scope>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<!-- ===================================================================== -->
<!-- BUILD -->
<!-- ===================================================================== -->
<build>
<plugins>
<plugin>
@ -170,12 +222,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.1</version>
<version>${maven-checkstyle-plugin.version}</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.32</version>
<version>${checkstyle.version}</version>
</dependency>
<dependency>
<groupId>io.spring.nohttp</groupId>
@ -297,7 +349,7 @@
</dependencies>
</plugin>
<!-- ===================================================== SUREFIRE -->
<!-- ======================================================== SUREFIRE -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
@ -349,6 +401,9 @@
</plugins>
</build>
<!-- ===================================================================== -->
<!-- LICENCIES -->
<!-- ===================================================================== -->
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@ -356,6 +411,9 @@
</license>
</licenses>
<!-- ===================================================================== -->
<!-- REPOSITORIES -->
<!-- ===================================================================== -->
<repositories>
<repository>
<id>spring-snapshots</id>
@ -375,6 +433,9 @@
</repository>
</repositories>
<!-- ===================================================================== -->
<!-- PLUGIN REPOSITORIES -->
<!-- ===================================================================== -->
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
@ -394,7 +455,11 @@
</pluginRepository>
</pluginRepositories>
<!-- ===================================================================== -->
<!-- PROFILES -->
<!-- ===================================================================== -->
<profiles>
<!-- =============================================================== M2E -->
<profile>
<id>m2e</id>
<activation>
@ -410,7 +475,7 @@
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<version>${lifecycle-mapping.version}</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
@ -450,5 +515,4 @@
</profile>
</profiles>
</project>

View file

@ -0,0 +1,32 @@
package org.springframework.samples.petclinic.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/**
* Configuration class to enable WebSocket and STOMP messaging.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setApplicationDestinationPrefixes("/app");
config.enableSimpleBroker("/topic/");
}
}

View file

@ -0,0 +1,22 @@
package org.springframework.samples.petclinic.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.samples.petclinic.model.common.WebSocketMessage;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
@Configuration
@EnableScheduling
public class WebSocketSchedulerConfiguration {
@Autowired
SimpMessagingTemplate simpMessagingTemplate;
@Scheduled(fixedDelay = 3000)
public void sendMessages() {
simpMessagingTemplate.convertAndSend("/topic/user", new WebSocketMessage("Fixed Delay Scheduler"));
}
}

View file

@ -0,0 +1,19 @@
package org.springframework.samples.petclinic.controller.common;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.samples.petclinic.model.common.User;
import org.springframework.samples.petclinic.model.common.WebSocketMessage;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@MessageMapping("/user")
@SendTo("/topic/user")
public WebSocketMessage getUser(User user) {
return new WebSocketMessage("Hi " + user.getFirstName() + user.getLastName());
}
}

View file

@ -0,0 +1,26 @@
package org.springframework.samples.petclinic.controller.common;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.samples.petclinic.model.common.WebSocketMessage;
import org.springframework.stereotype.Controller;
@Controller
public class WebSocketController {
@MessageMapping("/websocket.send")
@SendTo("/topic/public")
public WebSocketMessage sendMessage(@Payload final WebSocketMessage message) {
return message;
}
@MessageMapping("/websocket.newUser")
@SendTo("/topic/public")
public WebSocketMessage newUser(@Payload final WebSocketMessage message, SimpMessageHeaderAccessor headerAccessor) {
headerAccessor.getSessionAttributes().put("usqername", message.getSender());
return message;
}
}

View file

@ -0,0 +1,33 @@
package org.springframework.samples.petclinic.controller.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.samples.petclinic.model.common.WebSocketMessage;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionConnectedEvent;
@Slf4j
@Component
public class WebSocketEventListener {
@Autowired
private SimpMessageSendingOperations sendingOperations;
@EventListener
public void handlewebSocketConnectListener(final SessionConnectedEvent event) {
log.info("Ding dong. We have a new connection!");
}
@EventListener
public void handlewebSocketDisconnectListener(final SessionConnectedEvent event) {
final StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
final String username = (String) headerAccessor.getSessionAttributes().get("username");
sendingOperations.convertAndSend("/topic/public", new WebSocketMessage("Hello" + username));
}
}

View file

@ -0,0 +1,10 @@
package org.springframework.samples.petclinic.model.common;
import org.springframework.samples.petclinic.model.Person;
public class User extends Person {
public User() {
super();
}
}

View file

@ -0,0 +1,43 @@
package org.springframework.samples.petclinic.model.common;
import java.time.LocalDate;
public class WebSocketMessage {
private String sender;
private String time;
private String content;
public WebSocketMessage(String content) {
this.time = LocalDate.now().toString();
this.content = content;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View file

@ -0,0 +1,7 @@
package org.springframework.samples.petclinic.model.common;
public enum WebSocketMessageType {
MESSAGE,
CONNECT,
DISCONNECT
}