diff --git a/pom.xml b/pom.xml
index 4d07f379e..4c64e0911 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,9 @@
2.3.3.RELEASE
+
+
+
1.8
@@ -26,13 +29,22 @@
2.2.4
1.8.0
+ 8.32
0.8.5
+ 4.13
+ 1.0.0
+ 1.18.12
+ 3.1.1
+ 2.3.8
0.0.4.RELEASE
0.0.25
+
+
+
-
+
org.springframework.boot
spring-boot-starter-actuator
@@ -57,6 +69,10 @@
org.springframework.boot
spring-boot-starter-thymeleaf
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
org.springframework.boot
spring-boot-starter-test
@@ -69,15 +85,7 @@
-
-
- org.modelmapper
- modelmapper
- 2.3.8
- compile
-
-
-
+
com.h2database
h2
@@ -89,6 +97,15 @@
runtime
+
+
+ org.modelmapper
+ modelmapper
+ ${modelmapper.version}
+ compile
+
+
+
javax.cache
@@ -100,6 +117,12 @@
+
+ org.webjars
+ webjars-locator
+ 0.40
+
+
org.webjars
webjars-locator-core
@@ -119,9 +142,35 @@
bootstrap
${webjars-bootstrap.version}
+
+ org.webjars
+ stomp-websocket
+ 2.3.3-1
+
+
+
+ org.webjars
+ sockjs-client
+ 1.1.2
+
+
+
-
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.10.2
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.10.2
+
+
+
+
org.junit.jupiter
junit-jupiter-engine
@@ -138,20 +187,23 @@
spring-boot-devtools
true
-
- junit
- junit
- 4.13
- test
-
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
org.projectlombok
lombok
- 1.18.12
- test
+ ${lombok.version}
+
+
+
@@ -170,12 +222,12 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.1.1
+ ${maven-checkstyle-plugin.version}
com.puppycrawl.tools
checkstyle
- 8.32
+ ${checkstyle.version}
io.spring.nohttp
@@ -297,7 +349,7 @@
-
+
org.apache.maven.plugins
maven-surefire-plugin
@@ -349,6 +401,9 @@
+
+
+
Apache License, Version 2.0
@@ -356,6 +411,9 @@
+
+
+
spring-snapshots
@@ -375,6 +433,9 @@
+
+
+
spring-snapshots
@@ -394,7 +455,11 @@
+
+
+
+
m2e
@@ -410,7 +475,7 @@
org.eclipse.m2e
lifecycle-mapping
- 1.0.0
+ ${lifecycle-mapping.version}
@@ -450,5 +515,4 @@
-
diff --git a/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketConfig.java b/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketConfig.java
new file mode 100644
index 000000000..c7b1734cc
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketConfig.java
@@ -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/");
+ }
+
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketSchedulerConfiguration.java b/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketSchedulerConfiguration.java
new file mode 100644
index 000000000..db13377f6
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketSchedulerConfiguration.java
@@ -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"));
+ }
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/controller/common/UserController.java b/src/main/java/org/springframework/samples/petclinic/controller/common/UserController.java
new file mode 100644
index 000000000..fe16663c7
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/controller/common/UserController.java
@@ -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());
+ }
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/controller/common/WebSocketController.java b/src/main/java/org/springframework/samples/petclinic/controller/common/WebSocketController.java
new file mode 100644
index 000000000..5074205b7
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/controller/common/WebSocketController.java
@@ -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;
+ }
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/controller/common/WebSocketEventListener.java b/src/main/java/org/springframework/samples/petclinic/controller/common/WebSocketEventListener.java
new file mode 100644
index 000000000..0ddfbc523
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/controller/common/WebSocketEventListener.java
@@ -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));
+ }
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/model/common/User.java b/src/main/java/org/springframework/samples/petclinic/model/common/User.java
new file mode 100644
index 000000000..6cad7820e
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/model/common/User.java
@@ -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();
+ }
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/model/common/WebSocketMessage.java b/src/main/java/org/springframework/samples/petclinic/model/common/WebSocketMessage.java
new file mode 100644
index 000000000..916cf3df6
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/model/common/WebSocketMessage.java
@@ -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;
+ }
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/model/common/WebSocketMessageType.java b/src/main/java/org/springframework/samples/petclinic/model/common/WebSocketMessageType.java
new file mode 100644
index 000000000..52d946eaf
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/model/common/WebSocketMessageType.java
@@ -0,0 +1,7 @@
+package org.springframework.samples.petclinic.model.common;
+
+public enum WebSocketMessageType {
+ MESSAGE,
+ CONNECT,
+ DISCONNECT
+}