From: Gustavo Martin Morcuende Date: Sun, 8 May 2016 20:18:34 +0000 (+0200) Subject: Spring STOMP: no way of using full featured broker and simple at the same time withou... X-Git-Url: https://git.gumartinm.name/?a=commitdiff_plain;h=708f2b89f931db70ffe1f596c459ca70b18543ed;p=JavaForFun Spring STOMP: no way of using full featured broker and simple at the same time without creating a mess. --- diff --git a/SpringJava/STOMP/pom.xml b/SpringJava/STOMP/pom.xml new file mode 100644 index 0000000..01fa86d --- /dev/null +++ b/SpringJava/STOMP/pom.xml @@ -0,0 +1,28 @@ + + + + 4.0.0 + + de.spring.stomp + spring-stomp + 1.0-SNAPSHOT + pom + SPRING STOMP + http://gumartinm.name + + Spring Websockets. STOMP protocol. + + + Gustavo Martin Morcuende + https://www.gumartinm.name + + + scm:git:http://git.gumartinm.name/JavaForFun + https://git.gumartinm.name/JavaForFun + + + + spring-stomp-bom + + + diff --git a/SpringJava/STOMP/spring-stomp-bom/pom.xml b/SpringJava/STOMP/spring-stomp-bom/pom.xml new file mode 100644 index 0000000..d802535 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-bom/pom.xml @@ -0,0 +1,329 @@ + + + 4.0.0 + + + de.spring.stomp + spring-stomp + 1.0-SNAPSHOT + + + spring-stomp-bom + pom + SPRING STOMP BOM + http://gumartinm.name + + Spring Websockets. STOMP protocol. + + + Gustavo Martin Morcuende + http://www.gumartinm.name + + + scm:git:http://git.gumartinm.name/JavaForFun + http://git.gumartinm.name/JavaForFun + + + + UTF-8 + UTF-8 + 4.2.5.RELEASE + + + + + release + + release + + + true + + + + + + ../spring-stomp-server-simple + ../spring-stomp-server-full + + + + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.3 + + + + org.apache.logging.log4j + log4j-core + 2.3 + + + + org.slf4j + jcl-over-slf4j + 1.7.12 + + + + + cglib + cglib + 2.2.2 + + + + + junit + junit + 4.12 + test + + + org.mockito + mockito-core + 2.0.43-beta + test + + + + + + org.springframework + spring-context + ${spring.version} + + + + commons-logging + commons-logging + + + + + + + org.springframework + spring-websocket + ${spring.version} + + + + commons-logging + commons-logging + + + + + + + org.springframework + spring-messaging + ${spring.version} + + + + commons-logging + commons-logging + + + + + + + org.springframework + spring-webmvc + ${spring.version} + + + + commons-logging + commons-logging + + + + + org.springframework + spring-oxm + ${spring.version} + + + + commons-logging + commons-logging + + + + + + + + javax.servlet + javax.servlet-api + 4.0.0-b01 + provided + + + + + com.fasterxml.jackson.core + jackson-databind + 2.6.4 + + + + + javax.validation + validation-api + 1.1.0.Final + + + org.hibernate + hibernate-validator + 5.2.2.Final + + + + + + org.springframework + spring-test + ${spring.version} + test + + + + commons-logging + commons-logging + + + + + com.icegreen + greenmail + 1.5.0 + test + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.19.1 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + ${project.description} + ${project.version} + ${project.organization.name} + ${project.description} + ${project.version} + ${project.organization.name} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + + + **/*IntegrationTest.java + + + + + + diff --git a/SpringJava/STOMP/spring-stomp-server-full/pom.xml b/SpringJava/STOMP/spring-stomp-server-full/pom.xml new file mode 100644 index 0000000..21ba678 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/pom.xml @@ -0,0 +1,134 @@ + + + 4.0.0 + + + de.spring.stomp + spring-stomp-bom + 1.0-SNAPSHOT + + + spring-stomp-server-full + war + SPRING STOMP SERVER. FULL FEATURED BROKER. + https://gumartinm.name + + STOMP with Spring Framework. Full featured broker. + + + Gustavo Martin Morcuende + https://www.gumartinm.name + + + scm:git:http://git.gumartinm.name/JavaForFun + https://git.gumartinm.name/JavaForFun + + + + + + org.springframework + spring-context + + + org.springframework + spring-webmvc + + + org.springframework + spring-oxm + + + + + org.springframework + spring-websocket + + + + + org.springframework + spring-messaging + + + + + javax.servlet + javax.servlet-api + provided + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + + + + io.projectreactor + reactor-net + 2.0.8.RELEASE + + + io.netty + netty-all + 4.0.36.Final + + + + + ${project.artifactId} + + + ${basedir}/src/main/webapp + + **/*.* + + + + ${basedir}/src/main/resources/ + + **/*.* + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + + + true + src/main/webapp + + WEB-INF/web.xml + + + + + + + + diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/controllers/MessageGreetingController.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/controllers/MessageGreetingController.java new file mode 100644 index 0000000..982b6ff --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/controllers/MessageGreetingController.java @@ -0,0 +1,26 @@ +package de.spring.stomp.controllers; + +import java.time.LocalDateTime; + +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.stereotype.Controller; + +@Controller +public class MessageGreetingController { + + // Sending data to /app/greeting from STOMP client (client must first connect to endpoint, in my case portfolio) + // connecting to this URL -> http://172.17.0.3/spring-stomp-server/portfolio + // sending data to /app/greeting + + // The data sent to /app/greeting will be retrieved by this method. + @MessageMapping("/greeting") + @SendTo("/topic/greeting") + public String handle(String greeting) { + // STOMP clients subscribed to /topic/greeting will receive the returned data from this method. + // Destination is selected based on a convention but can be overridden via @SendTo + // I will be using @SendTo. In my case, it is not required (because it is the same as the destination selected + // based on the convention) but I will be using it just for fun. + return "[" + LocalDateTime.now() + "]: " + greeting; + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java new file mode 100644 index 0000000..d98b36b --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java @@ -0,0 +1,19 @@ +package de.spring.stomp.controllers; + +import java.security.Principal; +import java.time.LocalDateTime; + +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.simp.annotation.SendToUser; +import org.springframework.stereotype.Controller; + +@Controller +public class UserMessageTradeController { + + @MessageMapping("/trade") + @SendToUser(destinations="/topic/position-updates", broadcast=false /* No idea what is this for */) + public String executeTrade(String trade, Principal principal) { + + return "[" + LocalDateTime.now() + "]: " + trade; + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java new file mode 100644 index 0000000..a633f75 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java @@ -0,0 +1,35 @@ +package de.spring.stomp.handlers; + +import java.security.Principal; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.server.support.DefaultHandshakeHandler; + +/** + * In some cases it may be useful to assign an identity to a WebSocket session even when + * the user has not been formally authenticated. For example, a mobile app might assign some + * identity to anonymous users, perhaps based on geographical location. The do that currently, + * an application can sub-class DefaultHandshakeHandler and override the determineUser method. + * The custom handshake handler can then be plugged in (see examples in + * Section 25.2.4, “Deployment Considerations”) + */ +public class CustomHandshakeHandler extends DefaultHandshakeHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomHandshakeHandler.class); + + @Override + protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, + Map attributes) { + + Principal principal = request.getPrincipal(); + if (principal != null) { + LOGGER.info("CustomHandshakeHandler: " + principal.getName()); + } + + return super.determineUser(request, wsHandler, attributes); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java new file mode 100644 index 0000000..7936bf8 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java @@ -0,0 +1,40 @@ +package de.spring.stomp.interceptors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.simp.stomp.StompCommand; +import org.springframework.messaging.simp.stomp.StompHeaderAccessor; +import org.springframework.messaging.support.ChannelInterceptorAdapter; + +public class CustomChannelInterceptor extends ChannelInterceptorAdapter { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomChannelInterceptor.class); + + @Override + public Message preSend(Message message, MessageChannel channel) { + StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); + StompCommand command = accessor.getCommand(); + + LOGGER.info("CustomChannelInterceptor preSend, StompCommand: " + command); + LOGGER.info("CustomChannelInterceptor preSend, login: " + accessor.getLogin()); + LOGGER.info("CustomChannelInterceptor preSend, heartBeat: " + accessor.getHeartbeat()); + LOGGER.info("CustomChannelInterceptor preSend, destination: " + accessor.getDestination()); + LOGGER.info("CustomChannelInterceptor preSend, host: " + accessor.getHost()); + + return message; + } + + @Override + public void postSend(Message message, MessageChannel channel, boolean sent) { + StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); + StompCommand command = accessor.getCommand(); + + LOGGER.info("CustomChannelInterceptor postSend, StompCommand: " + command); + LOGGER.info("CustomChannelInterceptor postSend, login: " + accessor.getLogin()); + LOGGER.info("CustomChannelInterceptor postSend, heartBeat: " + accessor.getHeartbeat()); + LOGGER.info("CustomChannelInterceptor postSend, destination: " + accessor.getDestination()); + LOGGER.info("CustomChannelInterceptor postSend, host: " + accessor.getHost()); + + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java new file mode 100644 index 0000000..784ab6a --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java @@ -0,0 +1,26 @@ +package de.spring.stomp.interceptors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; + +public class CustomHttpHandshakeInterceptor extends HttpSessionHandshakeInterceptor { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomHttpHandshakeInterceptor.class); + + + @Override + public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, + WebSocketHandler wsHandler, Exception ex) { + super.afterHandshake(request, response, wsHandler, ex); + + LOGGER.info("Request URI:" + request.getURI()); + LOGGER.info("Request remote address:" + request.getRemoteAddress()); + LOGGER.info("Request local address:" + request.getLocalAddress()); + LOGGER.info("Request headers:" + request.getHeaders()); + + LOGGER.info("Response headers:" + response.getHeaders()); + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java new file mode 100644 index 0000000..b6e3619 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java @@ -0,0 +1,19 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent; + +public class BrokerAvailabilityListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(BrokerAvailabilityListener.class); + + @Override + public void onApplicationEvent(BrokerAvailabilityEvent event) { + + LOGGER.info("BrokerAvailabilityEvent timestamp: " + event.getTimestamp()); + LOGGER.info("BrokerAvailabilityEvent brokerAvailable: " + event.isBrokerAvailable()); + LOGGER.info("BrokerAvailabilityEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java new file mode 100644 index 0000000..da374e5 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java @@ -0,0 +1,18 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionConnectEvent; + +public class SessionConnectListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionConnectListener.class); + + @Override + public void onApplicationEvent(SessionConnectEvent event) { + LOGGER.info("SessionConnectEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionConnectEvent user: " + event.getUser()); + LOGGER.info("SessionConnectEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java new file mode 100644 index 0000000..b0444f3 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java @@ -0,0 +1,18 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionConnectedEvent; + +public class SessionConnectedListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionConnectedListener.class); + + @Override + public void onApplicationEvent(SessionConnectedEvent event) { + LOGGER.info("SessionConnectedEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionConnectedEvent user: " + event.getUser()); + LOGGER.info("SessionConnectedEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java new file mode 100644 index 0000000..59ff3e4 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java @@ -0,0 +1,20 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionDisconnectEvent; + +public class SessionDisconnectListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionUnsubscribeListener.class); + + @Override + public void onApplicationEvent(SessionDisconnectEvent event) { + LOGGER.info("SessionDisconnectEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionDisconnectEvent user: " + event.getUser()); + LOGGER.info("SessionDisconnectEvent sessionId: " + event.getSessionId()); + LOGGER.info("SessionDisconnectEvent close status: " + event.getCloseStatus()); + LOGGER.info("SessionDisconnectEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java new file mode 100644 index 0000000..90ee1da --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java @@ -0,0 +1,18 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionSubscribeEvent; + +public class SessionSubscribeListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionSubscribeListener.class); + + @Override + public void onApplicationEvent(SessionSubscribeEvent event) { + LOGGER.info("SessionSubscribeEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionSubscribeEvent user: " + event.getUser()); + LOGGER.info("SessionSubscribeEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java new file mode 100644 index 0000000..142bde9 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java @@ -0,0 +1,18 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionUnsubscribeEvent; + +public class SessionUnsubscribeListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionUnsubscribeListener.class); + + @Override + public void onApplicationEvent(SessionUnsubscribeEvent event) { + LOGGER.info("SessionUnsubscribeEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionUnsubscribeEvent user: " + event.getUser()); + LOGGER.info("SessionUnsubscribeEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/RestGreetingService.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/RestGreetingService.java new file mode 100644 index 0000000..69db326 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/RestGreetingService.java @@ -0,0 +1,6 @@ +package de.spring.stomp.services; + +public interface RestGreetingService { + + void doGreetings(String greeting); +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/UserTradeService.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/UserTradeService.java new file mode 100644 index 0000000..1d6bc34 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/UserTradeService.java @@ -0,0 +1,6 @@ +package de.spring.stomp.services; + +public interface UserTradeService { + + void doTrade(String user); +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java new file mode 100644 index 0000000..b518e76 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java @@ -0,0 +1,43 @@ +package de.spring.stomp.services.impl; + +import java.time.LocalDateTime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent; +import org.springframework.stereotype.Service; + +import de.spring.stomp.services.RestGreetingService; + +@Service("restGreetingService") +public class RestGreetingServiceImpl + implements RestGreetingService, ApplicationListener { + private final SimpMessagingTemplate template; + + private volatile boolean isBrokerAvailable = true; + + @Autowired + public RestGreetingServiceImpl(SimpMessagingTemplate template) { + this.template = template; + } + + @Override + public void doGreetings(String greeting) { + String text = "[" + LocalDateTime.now() + "]:" + greeting; + + if (isBrokerAvailable) { + // STOMP clients subscribed to /topic/greeting will receive the data sent by the convertAndSend method. + template.convertAndSend("/topic/greeting", text); + } + } + + @Override + public void onApplicationEvent(BrokerAvailabilityEvent event) { + // Components using the SimpMessagingTemplate should subscribe to this event + // and avoid sending messages at times when the broker is not available. + // In any case they should be prepared to handle MessageDeliveryException + // when sending a message. + isBrokerAvailable = event.isBrokerAvailable(); + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java new file mode 100644 index 0000000..e0d63e2 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java @@ -0,0 +1,44 @@ +package de.spring.stomp.services.impl; + +import java.time.LocalDateTime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent; +import org.springframework.stereotype.Service; + +import de.spring.stomp.services.UserTradeService; + +@Service("userTradeService") +public class UserTradeServiceImpl + implements UserTradeService, ApplicationListener { + private final SimpMessagingTemplate template; + + private volatile boolean isBrokerAvailable = true; + + @Autowired + public UserTradeServiceImpl(SimpMessagingTemplate template) { + this.template = template; + } + + @Override + public void doTrade(String user) { + String text = "[" + LocalDateTime.now() + "]:" + user; + + if (isBrokerAvailable) { + // STOMP clients subscribed to /topic/position-updates will receive the data sent by the convertAndSend method. + template.convertAndSendToUser(user, "/topic/position-updates", text); + } + } + + @Override + public void onApplicationEvent(BrokerAvailabilityEvent event) { + // Components using the SimpMessagingTemplate should subscribe to this event + // and avoid sending messages at times when the broker is not available. + // In any case they should be prepared to handle MessageDeliveryException + // when sending a message. + isBrokerAvailable = event.isBrokerAvailable(); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/webservices/rest/controller/RestGreetingController.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/webservices/rest/controller/RestGreetingController.java new file mode 100644 index 0000000..ebb32ed --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/webservices/rest/controller/RestGreetingController.java @@ -0,0 +1,31 @@ +package de.spring.webservices.rest.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import de.spring.stomp.services.RestGreetingService; + + +@RestController +public class RestGreetingController { + private final RestGreetingService restGreetingService; + + @Autowired + public RestGreetingController(RestGreetingService restGreetingService) { + this.restGreetingService = restGreetingService; + } + + // Sending data to /topic/greeting from REST service. + // POST http://localhost:8080/spring-stomp-server/greetings + + @RequestMapping(path="/greetings", method=RequestMethod.POST) + public void handle(@RequestBody String greeting) { + + // STOMP clients subscribed to /topic/greeting will receive the data sent by the convertAndSend method. + restGreetingService.doGreetings(greeting); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java new file mode 100644 index 0000000..718a8bd --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java @@ -0,0 +1,27 @@ +package de.spring.webservices.rest.controller; + +import java.time.LocalDateTime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import de.spring.stomp.services.UserTradeService; + +public class UserTradeController { + private final UserTradeService userTradeService; + + @Autowired + public UserTradeController(UserTradeService userTradeService) { + this.userTradeService = userTradeService; + } + + // Sending data to /topic/greeting from REST service. + // POST http://localhost:8080/spring-stomp-server/trade + + @RequestMapping(path="/trade", method=RequestMethod.POST) + public void handle(@RequestBody String user) { + userTradeService.doTrade(user); + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/resources/log4j2.xml b/SpringJava/STOMP/spring-stomp-server-full/src/main/resources/log4j2.xml new file mode 100644 index 0000000..281da4f --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/resources/log4j2.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/resources/spring-configuration/mvc/rest/rest-config.xml b/SpringJava/STOMP/spring-stomp-server-full/src/main/resources/spring-configuration/mvc/rest/rest-config.xml new file mode 100644 index 0000000..5ce72ef --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/resources/spring-configuration/mvc/rest/rest-config.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/resources/spring-configuration/spring-configuration.xml b/SpringJava/STOMP/spring-stomp-server-full/src/main/resources/spring-configuration/spring-configuration.xml new file mode 100644 index 0000000..27771f3 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/resources/spring-configuration/spring-configuration.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/STOMP/spring-stomp-server-full/src/main/webapp/WEB-INF/web.xml b/SpringJava/STOMP/spring-stomp-server-full/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..45d6ebc --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-full/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,41 @@ + + + + Spring STOMP: example full featured broker + + + + org.springframework.web.context.ContextLoaderListener + + + + + spring.profiles.default + ${environment.profile} + contextConfigLocation + + classpath*:spring-configuration/*.xml + + + + + + spring-rest + org.springframework.web.servlet.DispatcherServlet + 1 + true + + contextConfigLocation + classpath*:spring-configuration/mvc/rest/*.xml + + + + + spring-rest + + /* + + + diff --git a/SpringJava/STOMP/spring-stomp-server-simple/pom.xml b/SpringJava/STOMP/spring-stomp-server-simple/pom.xml new file mode 100644 index 0000000..3a78248 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/pom.xml @@ -0,0 +1,121 @@ + + + 4.0.0 + + + de.spring.stomp + spring-stomp-bom + 1.0-SNAPSHOT + + + spring-stomp-server-simple + war + SPRING STOMP SERVER. SIMPLE BROKER. + https://gumartinm.name + + STOMP with Spring Framework. Simple broker. + + + Gustavo Martin Morcuende + https://www.gumartinm.name + + + scm:git:http://git.gumartinm.name/JavaForFun + https://git.gumartinm.name/JavaForFun + + + + + + org.springframework + spring-context + + + org.springframework + spring-webmvc + + + org.springframework + spring-oxm + + + + + org.springframework + spring-websocket + + + + + org.springframework + spring-messaging + + + + + javax.servlet + javax.servlet-api + provided + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + + + ${project.artifactId} + + + ${basedir}/src/main/webapp + + **/*.* + + + + ${basedir}/src/main/resources/ + + **/*.* + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + + + true + src/main/webapp + + WEB-INF/web.xml + + + + + + + + diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/controllers/MessageGreetingController.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/controllers/MessageGreetingController.java new file mode 100644 index 0000000..982b6ff --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/controllers/MessageGreetingController.java @@ -0,0 +1,26 @@ +package de.spring.stomp.controllers; + +import java.time.LocalDateTime; + +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.stereotype.Controller; + +@Controller +public class MessageGreetingController { + + // Sending data to /app/greeting from STOMP client (client must first connect to endpoint, in my case portfolio) + // connecting to this URL -> http://172.17.0.3/spring-stomp-server/portfolio + // sending data to /app/greeting + + // The data sent to /app/greeting will be retrieved by this method. + @MessageMapping("/greeting") + @SendTo("/topic/greeting") + public String handle(String greeting) { + // STOMP clients subscribed to /topic/greeting will receive the returned data from this method. + // Destination is selected based on a convention but can be overridden via @SendTo + // I will be using @SendTo. In my case, it is not required (because it is the same as the destination selected + // based on the convention) but I will be using it just for fun. + return "[" + LocalDateTime.now() + "]: " + greeting; + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java new file mode 100644 index 0000000..d98b36b --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java @@ -0,0 +1,19 @@ +package de.spring.stomp.controllers; + +import java.security.Principal; +import java.time.LocalDateTime; + +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.simp.annotation.SendToUser; +import org.springframework.stereotype.Controller; + +@Controller +public class UserMessageTradeController { + + @MessageMapping("/trade") + @SendToUser(destinations="/topic/position-updates", broadcast=false /* No idea what is this for */) + public String executeTrade(String trade, Principal principal) { + + return "[" + LocalDateTime.now() + "]: " + trade; + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java new file mode 100644 index 0000000..a633f75 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java @@ -0,0 +1,35 @@ +package de.spring.stomp.handlers; + +import java.security.Principal; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.server.support.DefaultHandshakeHandler; + +/** + * In some cases it may be useful to assign an identity to a WebSocket session even when + * the user has not been formally authenticated. For example, a mobile app might assign some + * identity to anonymous users, perhaps based on geographical location. The do that currently, + * an application can sub-class DefaultHandshakeHandler and override the determineUser method. + * The custom handshake handler can then be plugged in (see examples in + * Section 25.2.4, “Deployment Considerations”) + */ +public class CustomHandshakeHandler extends DefaultHandshakeHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomHandshakeHandler.class); + + @Override + protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, + Map attributes) { + + Principal principal = request.getPrincipal(); + if (principal != null) { + LOGGER.info("CustomHandshakeHandler: " + principal.getName()); + } + + return super.determineUser(request, wsHandler, attributes); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java new file mode 100644 index 0000000..7936bf8 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java @@ -0,0 +1,40 @@ +package de.spring.stomp.interceptors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.simp.stomp.StompCommand; +import org.springframework.messaging.simp.stomp.StompHeaderAccessor; +import org.springframework.messaging.support.ChannelInterceptorAdapter; + +public class CustomChannelInterceptor extends ChannelInterceptorAdapter { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomChannelInterceptor.class); + + @Override + public Message preSend(Message message, MessageChannel channel) { + StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); + StompCommand command = accessor.getCommand(); + + LOGGER.info("CustomChannelInterceptor preSend, StompCommand: " + command); + LOGGER.info("CustomChannelInterceptor preSend, login: " + accessor.getLogin()); + LOGGER.info("CustomChannelInterceptor preSend, heartBeat: " + accessor.getHeartbeat()); + LOGGER.info("CustomChannelInterceptor preSend, destination: " + accessor.getDestination()); + LOGGER.info("CustomChannelInterceptor preSend, host: " + accessor.getHost()); + + return message; + } + + @Override + public void postSend(Message message, MessageChannel channel, boolean sent) { + StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); + StompCommand command = accessor.getCommand(); + + LOGGER.info("CustomChannelInterceptor postSend, StompCommand: " + command); + LOGGER.info("CustomChannelInterceptor postSend, login: " + accessor.getLogin()); + LOGGER.info("CustomChannelInterceptor postSend, heartBeat: " + accessor.getHeartbeat()); + LOGGER.info("CustomChannelInterceptor postSend, destination: " + accessor.getDestination()); + LOGGER.info("CustomChannelInterceptor postSend, host: " + accessor.getHost()); + + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java new file mode 100644 index 0000000..784ab6a --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java @@ -0,0 +1,26 @@ +package de.spring.stomp.interceptors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; + +public class CustomHttpHandshakeInterceptor extends HttpSessionHandshakeInterceptor { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomHttpHandshakeInterceptor.class); + + + @Override + public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, + WebSocketHandler wsHandler, Exception ex) { + super.afterHandshake(request, response, wsHandler, ex); + + LOGGER.info("Request URI:" + request.getURI()); + LOGGER.info("Request remote address:" + request.getRemoteAddress()); + LOGGER.info("Request local address:" + request.getLocalAddress()); + LOGGER.info("Request headers:" + request.getHeaders()); + + LOGGER.info("Response headers:" + response.getHeaders()); + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java new file mode 100644 index 0000000..b6e3619 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java @@ -0,0 +1,19 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent; + +public class BrokerAvailabilityListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(BrokerAvailabilityListener.class); + + @Override + public void onApplicationEvent(BrokerAvailabilityEvent event) { + + LOGGER.info("BrokerAvailabilityEvent timestamp: " + event.getTimestamp()); + LOGGER.info("BrokerAvailabilityEvent brokerAvailable: " + event.isBrokerAvailable()); + LOGGER.info("BrokerAvailabilityEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java new file mode 100644 index 0000000..da374e5 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java @@ -0,0 +1,18 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionConnectEvent; + +public class SessionConnectListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionConnectListener.class); + + @Override + public void onApplicationEvent(SessionConnectEvent event) { + LOGGER.info("SessionConnectEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionConnectEvent user: " + event.getUser()); + LOGGER.info("SessionConnectEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java new file mode 100644 index 0000000..b0444f3 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java @@ -0,0 +1,18 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionConnectedEvent; + +public class SessionConnectedListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionConnectedListener.class); + + @Override + public void onApplicationEvent(SessionConnectedEvent event) { + LOGGER.info("SessionConnectedEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionConnectedEvent user: " + event.getUser()); + LOGGER.info("SessionConnectedEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java new file mode 100644 index 0000000..59ff3e4 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java @@ -0,0 +1,20 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionDisconnectEvent; + +public class SessionDisconnectListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionUnsubscribeListener.class); + + @Override + public void onApplicationEvent(SessionDisconnectEvent event) { + LOGGER.info("SessionDisconnectEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionDisconnectEvent user: " + event.getUser()); + LOGGER.info("SessionDisconnectEvent sessionId: " + event.getSessionId()); + LOGGER.info("SessionDisconnectEvent close status: " + event.getCloseStatus()); + LOGGER.info("SessionDisconnectEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java new file mode 100644 index 0000000..90ee1da --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java @@ -0,0 +1,18 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionSubscribeEvent; + +public class SessionSubscribeListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionSubscribeListener.class); + + @Override + public void onApplicationEvent(SessionSubscribeEvent event) { + LOGGER.info("SessionSubscribeEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionSubscribeEvent user: " + event.getUser()); + LOGGER.info("SessionSubscribeEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java new file mode 100644 index 0000000..142bde9 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java @@ -0,0 +1,18 @@ +package de.spring.stomp.listeners; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.web.socket.messaging.SessionUnsubscribeEvent; + +public class SessionUnsubscribeListener implements ApplicationListener { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionUnsubscribeListener.class); + + @Override + public void onApplicationEvent(SessionUnsubscribeEvent event) { + LOGGER.info("SessionUnsubscribeEvent timestamp: " + event.getTimestamp()); + LOGGER.info("SessionUnsubscribeEvent user: " + event.getUser()); + LOGGER.info("SessionUnsubscribeEvent: " + event.toString()); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/RestGreetingService.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/RestGreetingService.java new file mode 100644 index 0000000..69db326 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/RestGreetingService.java @@ -0,0 +1,6 @@ +package de.spring.stomp.services; + +public interface RestGreetingService { + + void doGreetings(String greeting); +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/UserTradeService.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/UserTradeService.java new file mode 100644 index 0000000..1d6bc34 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/UserTradeService.java @@ -0,0 +1,6 @@ +package de.spring.stomp.services; + +public interface UserTradeService { + + void doTrade(String user); +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java new file mode 100644 index 0000000..b518e76 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java @@ -0,0 +1,43 @@ +package de.spring.stomp.services.impl; + +import java.time.LocalDateTime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent; +import org.springframework.stereotype.Service; + +import de.spring.stomp.services.RestGreetingService; + +@Service("restGreetingService") +public class RestGreetingServiceImpl + implements RestGreetingService, ApplicationListener { + private final SimpMessagingTemplate template; + + private volatile boolean isBrokerAvailable = true; + + @Autowired + public RestGreetingServiceImpl(SimpMessagingTemplate template) { + this.template = template; + } + + @Override + public void doGreetings(String greeting) { + String text = "[" + LocalDateTime.now() + "]:" + greeting; + + if (isBrokerAvailable) { + // STOMP clients subscribed to /topic/greeting will receive the data sent by the convertAndSend method. + template.convertAndSend("/topic/greeting", text); + } + } + + @Override + public void onApplicationEvent(BrokerAvailabilityEvent event) { + // Components using the SimpMessagingTemplate should subscribe to this event + // and avoid sending messages at times when the broker is not available. + // In any case they should be prepared to handle MessageDeliveryException + // when sending a message. + isBrokerAvailable = event.isBrokerAvailable(); + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java new file mode 100644 index 0000000..e0d63e2 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java @@ -0,0 +1,44 @@ +package de.spring.stomp.services.impl; + +import java.time.LocalDateTime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent; +import org.springframework.stereotype.Service; + +import de.spring.stomp.services.UserTradeService; + +@Service("userTradeService") +public class UserTradeServiceImpl + implements UserTradeService, ApplicationListener { + private final SimpMessagingTemplate template; + + private volatile boolean isBrokerAvailable = true; + + @Autowired + public UserTradeServiceImpl(SimpMessagingTemplate template) { + this.template = template; + } + + @Override + public void doTrade(String user) { + String text = "[" + LocalDateTime.now() + "]:" + user; + + if (isBrokerAvailable) { + // STOMP clients subscribed to /topic/position-updates will receive the data sent by the convertAndSend method. + template.convertAndSendToUser(user, "/topic/position-updates", text); + } + } + + @Override + public void onApplicationEvent(BrokerAvailabilityEvent event) { + // Components using the SimpMessagingTemplate should subscribe to this event + // and avoid sending messages at times when the broker is not available. + // In any case they should be prepared to handle MessageDeliveryException + // when sending a message. + isBrokerAvailable = event.isBrokerAvailable(); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/webservices/rest/controller/RestGreetingController.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/webservices/rest/controller/RestGreetingController.java new file mode 100644 index 0000000..ebb32ed --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/webservices/rest/controller/RestGreetingController.java @@ -0,0 +1,31 @@ +package de.spring.webservices.rest.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import de.spring.stomp.services.RestGreetingService; + + +@RestController +public class RestGreetingController { + private final RestGreetingService restGreetingService; + + @Autowired + public RestGreetingController(RestGreetingService restGreetingService) { + this.restGreetingService = restGreetingService; + } + + // Sending data to /topic/greeting from REST service. + // POST http://localhost:8080/spring-stomp-server/greetings + + @RequestMapping(path="/greetings", method=RequestMethod.POST) + public void handle(@RequestBody String greeting) { + + // STOMP clients subscribed to /topic/greeting will receive the data sent by the convertAndSend method. + restGreetingService.doGreetings(greeting); + } + +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java new file mode 100644 index 0000000..718a8bd --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java @@ -0,0 +1,27 @@ +package de.spring.webservices.rest.controller; + +import java.time.LocalDateTime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import de.spring.stomp.services.UserTradeService; + +public class UserTradeController { + private final UserTradeService userTradeService; + + @Autowired + public UserTradeController(UserTradeService userTradeService) { + this.userTradeService = userTradeService; + } + + // Sending data to /topic/greeting from REST service. + // POST http://localhost:8080/spring-stomp-server/trade + + @RequestMapping(path="/trade", method=RequestMethod.POST) + public void handle(@RequestBody String user) { + userTradeService.doTrade(user); + } +} diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/resources/log4j2.xml b/SpringJava/STOMP/spring-stomp-server-simple/src/main/resources/log4j2.xml new file mode 100644 index 0000000..281da4f --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/resources/log4j2.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/resources/spring-configuration/mvc/rest/rest-config.xml b/SpringJava/STOMP/spring-stomp-server-simple/src/main/resources/spring-configuration/mvc/rest/rest-config.xml new file mode 100644 index 0000000..5ce72ef --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/resources/spring-configuration/mvc/rest/rest-config.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/resources/spring-configuration/spring-configuration.xml b/SpringJava/STOMP/spring-stomp-server-simple/src/main/resources/spring-configuration/spring-configuration.xml new file mode 100644 index 0000000..8c036bc --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/resources/spring-configuration/spring-configuration.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/STOMP/spring-stomp-server-simple/src/main/webapp/WEB-INF/web.xml b/SpringJava/STOMP/spring-stomp-server-simple/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..4ed5845 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server-simple/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,41 @@ + + + + Spring STOMP: example simple broker + + + + org.springframework.web.context.ContextLoaderListener + + + + + spring.profiles.default + ${environment.profile} + contextConfigLocation + + classpath*:spring-configuration/*.xml + + + + + + spring-rest + org.springframework.web.servlet.DispatcherServlet + 1 + true + + contextConfigLocation + classpath*:spring-configuration/mvc/rest/*.xml + + + + + spring-rest + + /* + + + diff --git a/SpringJava/STOMP/spring-stomp-server/pom.xml b/SpringJava/STOMP/spring-stomp-server/pom.xml deleted file mode 100644 index 55274b2..0000000 --- a/SpringJava/STOMP/spring-stomp-server/pom.xml +++ /dev/null @@ -1,125 +0,0 @@ - - 4.0.0 - - de.spring.stomp - spring-stomp - 1.0-SNAPSHOT - - - spring-stomp-server - war - spring-stomp-server - http://gumartinm.name - STOMP with Spring Framework. - - Gustavo Martin Morcuende - http://www.gumartinm.name - - - scm:git:http://git.gumartinm.name/JavaForFun - http://git.gumartinm.name/JavaForFun - - - - - - org.springframework - spring-context - - - org.springframework - spring-webmvc - - - org.springframework - spring-oxm - - - - - org.springframework - spring-websocket - - - - - org.springframework - spring-messaging - - - - - javax.servlet - javax.servlet-api - provided - - - - - com.fasterxml.jackson.core - jackson-databind - - - - - - javax.validation - validation-api - - - org.hibernate - hibernate-validator - - - - - - org.projectreactor - reactor-net - 1.1.6.RELEASE - - - - - ${project.artifactId} - - - ${basedir}/src/main/webapp - - **/*.* - - - - ${basedir}/src/main/resources/ - - **/*.* - - - - - - org.apache.maven.plugins - maven-war-plugin - 2.6 - - - - true - src/main/webapp - - WEB-INF/web.xml - - - - - - - - diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/controllers/MessageGreetingController.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/controllers/MessageGreetingController.java deleted file mode 100644 index 982b6ff..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/controllers/MessageGreetingController.java +++ /dev/null @@ -1,26 +0,0 @@ -package de.spring.stomp.controllers; - -import java.time.LocalDateTime; - -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.stereotype.Controller; - -@Controller -public class MessageGreetingController { - - // Sending data to /app/greeting from STOMP client (client must first connect to endpoint, in my case portfolio) - // connecting to this URL -> http://172.17.0.3/spring-stomp-server/portfolio - // sending data to /app/greeting - - // The data sent to /app/greeting will be retrieved by this method. - @MessageMapping("/greeting") - @SendTo("/topic/greeting") - public String handle(String greeting) { - // STOMP clients subscribed to /topic/greeting will receive the returned data from this method. - // Destination is selected based on a convention but can be overridden via @SendTo - // I will be using @SendTo. In my case, it is not required (because it is the same as the destination selected - // based on the convention) but I will be using it just for fun. - return "[" + LocalDateTime.now() + "]: " + greeting; - } -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java deleted file mode 100644 index d98b36b..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.spring.stomp.controllers; - -import java.security.Principal; -import java.time.LocalDateTime; - -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.simp.annotation.SendToUser; -import org.springframework.stereotype.Controller; - -@Controller -public class UserMessageTradeController { - - @MessageMapping("/trade") - @SendToUser(destinations="/topic/position-updates", broadcast=false /* No idea what is this for */) - public String executeTrade(String trade, Principal principal) { - - return "[" + LocalDateTime.now() + "]: " + trade; - } -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java deleted file mode 100644 index 452c7f0..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.spring.stomp.handlers; - -import java.security.Principal; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.server.ServerHttpRequest; -import org.springframework.web.socket.WebSocketHandler; -import org.springframework.web.socket.server.support.DefaultHandshakeHandler; - -/** - * In some cases it may be useful to assign an identity to a WebSocket session even when - * the user has not been formally authenticated. For example, a mobile app might assign some - * identity to anonymous users, perhaps based on geographical location. The do that currently, - * an application can sub-class DefaultHandshakeHandler and override the determineUser method. - * The custom handshake handler can then be plugged in (see examples in - * Section 25.2.4, “Deployment Considerations”) - */ -public class CustomHandshakeHandler extends DefaultHandshakeHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(CustomHandshakeHandler.class); - - @Override - protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, - Map attributes) { - - Principal principal = request.getPrincipal(); - LOGGER.info("CustomHandshakeHandler: " + principal.getName()); - - return super.determineUser(request, wsHandler, attributes); - } - -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java deleted file mode 100644 index 7936bf8..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.spring.stomp.interceptors; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.simp.stomp.StompCommand; -import org.springframework.messaging.simp.stomp.StompHeaderAccessor; -import org.springframework.messaging.support.ChannelInterceptorAdapter; - -public class CustomChannelInterceptor extends ChannelInterceptorAdapter { - private static final Logger LOGGER = LoggerFactory.getLogger(CustomChannelInterceptor.class); - - @Override - public Message preSend(Message message, MessageChannel channel) { - StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); - StompCommand command = accessor.getCommand(); - - LOGGER.info("CustomChannelInterceptor preSend, StompCommand: " + command); - LOGGER.info("CustomChannelInterceptor preSend, login: " + accessor.getLogin()); - LOGGER.info("CustomChannelInterceptor preSend, heartBeat: " + accessor.getHeartbeat()); - LOGGER.info("CustomChannelInterceptor preSend, destination: " + accessor.getDestination()); - LOGGER.info("CustomChannelInterceptor preSend, host: " + accessor.getHost()); - - return message; - } - - @Override - public void postSend(Message message, MessageChannel channel, boolean sent) { - StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); - StompCommand command = accessor.getCommand(); - - LOGGER.info("CustomChannelInterceptor postSend, StompCommand: " + command); - LOGGER.info("CustomChannelInterceptor postSend, login: " + accessor.getLogin()); - LOGGER.info("CustomChannelInterceptor postSend, heartBeat: " + accessor.getHeartbeat()); - LOGGER.info("CustomChannelInterceptor postSend, destination: " + accessor.getDestination()); - LOGGER.info("CustomChannelInterceptor postSend, host: " + accessor.getHost()); - - } -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java deleted file mode 100644 index 784ab6a..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java +++ /dev/null @@ -1,26 +0,0 @@ -package de.spring.stomp.interceptors; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.server.ServerHttpRequest; -import org.springframework.http.server.ServerHttpResponse; -import org.springframework.web.socket.WebSocketHandler; -import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; - -public class CustomHttpHandshakeInterceptor extends HttpSessionHandshakeInterceptor { - private static final Logger LOGGER = LoggerFactory.getLogger(CustomHttpHandshakeInterceptor.class); - - - @Override - public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, - WebSocketHandler wsHandler, Exception ex) { - super.afterHandshake(request, response, wsHandler, ex); - - LOGGER.info("Request URI:" + request.getURI()); - LOGGER.info("Request remote address:" + request.getRemoteAddress()); - LOGGER.info("Request local address:" + request.getLocalAddress()); - LOGGER.info("Request headers:" + request.getHeaders()); - - LOGGER.info("Response headers:" + response.getHeaders()); - } -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java deleted file mode 100644 index b6e3619..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.spring.stomp.listeners; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent; - -public class BrokerAvailabilityListener implements ApplicationListener { - private static final Logger LOGGER = LoggerFactory.getLogger(BrokerAvailabilityListener.class); - - @Override - public void onApplicationEvent(BrokerAvailabilityEvent event) { - - LOGGER.info("BrokerAvailabilityEvent timestamp: " + event.getTimestamp()); - LOGGER.info("BrokerAvailabilityEvent brokerAvailable: " + event.isBrokerAvailable()); - LOGGER.info("BrokerAvailabilityEvent: " + event.toString()); - } - -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java deleted file mode 100644 index da374e5..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.spring.stomp.listeners; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.web.socket.messaging.SessionConnectEvent; - -public class SessionConnectListener implements ApplicationListener { - private static final Logger LOGGER = LoggerFactory.getLogger(SessionConnectListener.class); - - @Override - public void onApplicationEvent(SessionConnectEvent event) { - LOGGER.info("SessionConnectEvent timestamp: " + event.getTimestamp()); - LOGGER.info("SessionConnectEvent user: " + event.getUser()); - LOGGER.info("SessionConnectEvent: " + event.toString()); - } - -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java deleted file mode 100644 index b0444f3..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.spring.stomp.listeners; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.web.socket.messaging.SessionConnectedEvent; - -public class SessionConnectedListener implements ApplicationListener { - private static final Logger LOGGER = LoggerFactory.getLogger(SessionConnectedListener.class); - - @Override - public void onApplicationEvent(SessionConnectedEvent event) { - LOGGER.info("SessionConnectedEvent timestamp: " + event.getTimestamp()); - LOGGER.info("SessionConnectedEvent user: " + event.getUser()); - LOGGER.info("SessionConnectedEvent: " + event.toString()); - } - -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java deleted file mode 100644 index 59ff3e4..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.spring.stomp.listeners; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.web.socket.messaging.SessionDisconnectEvent; - -public class SessionDisconnectListener implements ApplicationListener { - private static final Logger LOGGER = LoggerFactory.getLogger(SessionUnsubscribeListener.class); - - @Override - public void onApplicationEvent(SessionDisconnectEvent event) { - LOGGER.info("SessionDisconnectEvent timestamp: " + event.getTimestamp()); - LOGGER.info("SessionDisconnectEvent user: " + event.getUser()); - LOGGER.info("SessionDisconnectEvent sessionId: " + event.getSessionId()); - LOGGER.info("SessionDisconnectEvent close status: " + event.getCloseStatus()); - LOGGER.info("SessionDisconnectEvent: " + event.toString()); - } - -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java deleted file mode 100644 index 90ee1da..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.spring.stomp.listeners; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.web.socket.messaging.SessionSubscribeEvent; - -public class SessionSubscribeListener implements ApplicationListener { - private static final Logger LOGGER = LoggerFactory.getLogger(SessionSubscribeListener.class); - - @Override - public void onApplicationEvent(SessionSubscribeEvent event) { - LOGGER.info("SessionSubscribeEvent timestamp: " + event.getTimestamp()); - LOGGER.info("SessionSubscribeEvent user: " + event.getUser()); - LOGGER.info("SessionSubscribeEvent: " + event.toString()); - } - -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java deleted file mode 100644 index 142bde9..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.spring.stomp.listeners; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.web.socket.messaging.SessionUnsubscribeEvent; - -public class SessionUnsubscribeListener implements ApplicationListener { - private static final Logger LOGGER = LoggerFactory.getLogger(SessionUnsubscribeListener.class); - - @Override - public void onApplicationEvent(SessionUnsubscribeEvent event) { - LOGGER.info("SessionUnsubscribeEvent timestamp: " + event.getTimestamp()); - LOGGER.info("SessionUnsubscribeEvent user: " + event.getUser()); - LOGGER.info("SessionUnsubscribeEvent: " + event.toString()); - } - -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/RestGreetingService.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/RestGreetingService.java deleted file mode 100644 index 69db326..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/RestGreetingService.java +++ /dev/null @@ -1,6 +0,0 @@ -package de.spring.stomp.services; - -public interface RestGreetingService { - - void doGreetings(String greeting); -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/UserTradeService.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/UserTradeService.java deleted file mode 100644 index 1d6bc34..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/UserTradeService.java +++ /dev/null @@ -1,6 +0,0 @@ -package de.spring.stomp.services; - -public interface UserTradeService { - - void doTrade(String user); -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java deleted file mode 100644 index b518e76..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -package de.spring.stomp.services.impl; - -import java.time.LocalDateTime; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; -import org.springframework.messaging.simp.SimpMessagingTemplate; -import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent; -import org.springframework.stereotype.Service; - -import de.spring.stomp.services.RestGreetingService; - -@Service("restGreetingService") -public class RestGreetingServiceImpl - implements RestGreetingService, ApplicationListener { - private final SimpMessagingTemplate template; - - private volatile boolean isBrokerAvailable = true; - - @Autowired - public RestGreetingServiceImpl(SimpMessagingTemplate template) { - this.template = template; - } - - @Override - public void doGreetings(String greeting) { - String text = "[" + LocalDateTime.now() + "]:" + greeting; - - if (isBrokerAvailable) { - // STOMP clients subscribed to /topic/greeting will receive the data sent by the convertAndSend method. - template.convertAndSend("/topic/greeting", text); - } - } - - @Override - public void onApplicationEvent(BrokerAvailabilityEvent event) { - // Components using the SimpMessagingTemplate should subscribe to this event - // and avoid sending messages at times when the broker is not available. - // In any case they should be prepared to handle MessageDeliveryException - // when sending a message. - isBrokerAvailable = event.isBrokerAvailable(); - } -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java deleted file mode 100644 index e0d63e2..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package de.spring.stomp.services.impl; - -import java.time.LocalDateTime; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; -import org.springframework.messaging.simp.SimpMessagingTemplate; -import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent; -import org.springframework.stereotype.Service; - -import de.spring.stomp.services.UserTradeService; - -@Service("userTradeService") -public class UserTradeServiceImpl - implements UserTradeService, ApplicationListener { - private final SimpMessagingTemplate template; - - private volatile boolean isBrokerAvailable = true; - - @Autowired - public UserTradeServiceImpl(SimpMessagingTemplate template) { - this.template = template; - } - - @Override - public void doTrade(String user) { - String text = "[" + LocalDateTime.now() + "]:" + user; - - if (isBrokerAvailable) { - // STOMP clients subscribed to /topic/position-updates will receive the data sent by the convertAndSend method. - template.convertAndSendToUser(user, "/topic/position-updates", text); - } - } - - @Override - public void onApplicationEvent(BrokerAvailabilityEvent event) { - // Components using the SimpMessagingTemplate should subscribe to this event - // and avoid sending messages at times when the broker is not available. - // In any case they should be prepared to handle MessageDeliveryException - // when sending a message. - isBrokerAvailable = event.isBrokerAvailable(); - } - -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/webservices/rest/controller/RestGreetingController.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/webservices/rest/controller/RestGreetingController.java deleted file mode 100644 index ebb32ed..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/webservices/rest/controller/RestGreetingController.java +++ /dev/null @@ -1,31 +0,0 @@ -package de.spring.webservices.rest.controller; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -import de.spring.stomp.services.RestGreetingService; - - -@RestController -public class RestGreetingController { - private final RestGreetingService restGreetingService; - - @Autowired - public RestGreetingController(RestGreetingService restGreetingService) { - this.restGreetingService = restGreetingService; - } - - // Sending data to /topic/greeting from REST service. - // POST http://localhost:8080/spring-stomp-server/greetings - - @RequestMapping(path="/greetings", method=RequestMethod.POST) - public void handle(@RequestBody String greeting) { - - // STOMP clients subscribed to /topic/greeting will receive the data sent by the convertAndSend method. - restGreetingService.doGreetings(greeting); - } - -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java deleted file mode 100644 index 718a8bd..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java +++ /dev/null @@ -1,27 +0,0 @@ -package de.spring.webservices.rest.controller; - -import java.time.LocalDateTime; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -import de.spring.stomp.services.UserTradeService; - -public class UserTradeController { - private final UserTradeService userTradeService; - - @Autowired - public UserTradeController(UserTradeService userTradeService) { - this.userTradeService = userTradeService; - } - - // Sending data to /topic/greeting from REST service. - // POST http://localhost:8080/spring-stomp-server/trade - - @RequestMapping(path="/trade", method=RequestMethod.POST) - public void handle(@RequestBody String user) { - userTradeService.doTrade(user); - } -} diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/resources/log4j2.xml b/SpringJava/STOMP/spring-stomp-server/src/main/resources/log4j2.xml deleted file mode 100644 index 281da4f..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/resources/log4j2.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/resources/spring-configuration/mvc/rest/rest-config.xml b/SpringJava/STOMP/spring-stomp-server/src/main/resources/spring-configuration/mvc/rest/rest-config.xml deleted file mode 100644 index 5ce72ef..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/resources/spring-configuration/mvc/rest/rest-config.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/resources/spring-configuration/spring-configuration.xml b/SpringJava/STOMP/spring-stomp-server/src/main/resources/spring-configuration/spring-configuration.xml deleted file mode 100644 index 620323b..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/resources/spring-configuration/spring-configuration.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/STOMP/spring-stomp-server/src/main/webapp/WEB-INF/web.xml b/SpringJava/STOMP/spring-stomp-server/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 00d1c2e..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - Spring STOMP: example - - - - org.springframework.web.context.ContextLoaderListener - - - - - spring.profiles.active - ${environment.profile} - contextConfigLocation - - classpath*:spring-configuration/*.xml - - - - - - spring-rest - org.springframework.web.servlet.DispatcherServlet - 1 - true - - contextConfigLocation - classpath*:spring-configuration/mvc/rest/*.xml - - - - - spring-rest - - /* - - - diff --git a/SpringJava/STOMP/spring-stomp/pom.xml b/SpringJava/STOMP/spring-stomp/pom.xml deleted file mode 100644 index 8630bf6..0000000 --- a/SpringJava/STOMP/spring-stomp/pom.xml +++ /dev/null @@ -1,316 +0,0 @@ - - 4.0.0 - de.spring.stomp - spring-stomp - pom - 1.0-SNAPSHOT - spring-stomp - http://gumartinm.name - Emails with Spring Framework - - Gustavo Martin Morcuende - http://www.gumartinm.name - - - scm:git:http://git.gumartinm.name/JavaForFun - http://git.gumartinm.name/JavaForFun - - - - UTF-8 - UTF-8 - 4.2.5.RELEASE - - - - - release - - release - - - true - - - - - - - - org.apache.logging.log4j - log4j-slf4j-impl - 2.3 - - - - org.apache.logging.log4j - log4j-core - 2.3 - - - - org.slf4j - jcl-over-slf4j - 1.7.12 - - - - - cglib - cglib - 2.2.2 - - - - - junit - junit - 4.12 - test - - - org.mockito - mockito-core - 2.0.43-beta - test - - - - - - org.springframework - spring-context - ${spring.version} - - - - commons-logging - commons-logging - - - - - - - org.springframework - spring-websocket - ${spring.version} - - - - commons-logging - commons-logging - - - - - - - org.springframework - spring-messaging - ${spring.version} - - - - commons-logging - commons-logging - - - - - - - org.springframework - spring-webmvc - ${spring.version} - - - - commons-logging - commons-logging - - - - - org.springframework - spring-oxm - ${spring.version} - - - - commons-logging - commons-logging - - - - - - - - javax.servlet - javax.servlet-api - 4.0.0-b01 - provided - - - - - com.fasterxml.jackson.core - jackson-databind - 2.6.4 - - - - - javax.validation - validation-api - 1.1.0.Final - - - org.hibernate - hibernate-validator - 5.2.2.Final - - - - - - org.springframework - spring-test - ${spring.version} - test - - - - commons-logging - commons-logging - - - - - com.icegreen - greenmail - 1.5.0 - test - - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.19.1 - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.19.1 - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - ${project.build.sourceEncoding} - - - - org.apache.maven.plugins - maven-resources-plugin - 2.7 - - ${project.build.sourceEncoding} - - - - org.apache.maven.plugins - maven-jar-plugin - 2.6 - - - - ${project.description} - ${project.version} - ${project.organization.name} - ${project.description} - ${project.version} - ${project.organization.name} - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*IntegrationTest.java - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - - integration-test - verify - - - - - - **/*IntegrationTest.java - - - - - -