From 95e68c1ac43a380ee947b35267d1f0b263ca3c02 Mon Sep 17 00:00:00 2001 From: Gustavo Martin Morcuende Date: Tue, 3 May 2016 00:35:14 +0200 Subject: [PATCH] STOMP many improvements --- SpringJava/STOMP/README | 1 + SpringJava/STOMP/spring-stomp-server/pom.xml | 8 ++ .../controllers/MessageGreetingController.java | 8 +- .../controllers/UserMessageTradeController.java | 19 +++++ .../stomp/handlers/CustomHandshakeHandler.java | 33 ++++++++ .../de/spring/stomp/handlers/MyCustomHandler.java | 13 ---- .../interceptors/CustomChannelInterceptor.java | 40 ++++++++++ .../CustomHttpHandshakeInterceptor.java | 26 +++++++ .../listeners/BrokerAvailabilityListener.java | 19 +++++ .../stomp/listeners/SessionConnectListener.java | 18 +++++ .../stomp/listeners/SessionConnectedListener.java | 18 +++++ .../stomp/listeners/SessionDisconnectListener.java | 20 +++++ .../stomp/listeners/SessionSubscribeListener.java | 18 +++++ .../listeners/SessionUnsubscribeListener.java | 18 +++++ .../spring/stomp/services/RestGreetingService.java | 6 ++ .../de/spring/stomp/services/UserTradeService.java | 6 ++ .../services/impl/RestGreetingServiceImpl.java | 43 +++++++++++ .../stomp/services/impl/UserTradeServiceImpl.java | 44 +++++++++++ .../rest/controller/RestGreetingController.java | 15 ++-- .../rest/controller/UserTradeController.java | 27 +++++++ .../spring-configuration/spring-configuration.xml | 88 +++++++++++++++++++++- 21 files changed, 461 insertions(+), 27 deletions(-) create mode 100644 SpringJava/STOMP/README create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/controllers/UserMessageTradeController.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java delete mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/handlers/MyCustomHandler.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/interceptors/CustomChannelInterceptor.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/RestGreetingService.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/UserTradeService.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/impl/RestGreetingServiceImpl.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/impl/UserTradeServiceImpl.java create mode 100644 SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/webservices/rest/controller/UserTradeController.java diff --git a/SpringJava/STOMP/README b/SpringJava/STOMP/README new file mode 100644 index 0000000..0df5dcf --- /dev/null +++ b/SpringJava/STOMP/README @@ -0,0 +1 @@ +TODO: sending and receiving JSON objects (using messageConverters and JSON with STOMP protocol) diff --git a/SpringJava/STOMP/spring-stomp-server/pom.xml b/SpringJava/STOMP/spring-stomp-server/pom.xml index 08f1537..55274b2 100644 --- a/SpringJava/STOMP/spring-stomp-server/pom.xml +++ b/SpringJava/STOMP/spring-stomp-server/pom.xml @@ -77,6 +77,14 @@ org.hibernate hibernate-validator + + + + + org.projectreactor + reactor-net + 1.1.6.RELEASE + 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 index d525208..982b6ff 100644 --- 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 @@ -3,6 +3,7 @@ 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 @@ -12,11 +13,14 @@ public class MessageGreetingController { // 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 retrieved by this method. + // 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 - return "[" + LocalDateTime.now() + ": " + greeting; + // 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 new file mode 100644 index 0000000..d98b36b --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java new file mode 100644 index 0000000..452c7f0 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/handlers/CustomHandshakeHandler.java @@ -0,0 +1,33 @@ +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/handlers/MyCustomHandler.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/handlers/MyCustomHandler.java deleted file mode 100644 index 6500435..0000000 --- a/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/handlers/MyCustomHandler.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.spring.stomp.handlers; - -import org.springframework.web.socket.TextMessage; -import org.springframework.web.socket.WebSocketSession; -import org.springframework.web.socket.handler.TextWebSocketHandler; - -public class MyCustomHandler extends TextWebSocketHandler { - - @Override - public void handleTextMessage(WebSocketSession session, TextMessage message) { - - } -} 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 new file mode 100644 index 0000000..7936bf8 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/interceptors/CustomHttpHandshakeInterceptor.java new file mode 100644 index 0000000..784ab6a --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/BrokerAvailabilityListener.java new file mode 100644 index 0000000..b6e3619 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectListener.java new file mode 100644 index 0000000..da374e5 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionConnectedListener.java new file mode 100644 index 0000000..b0444f3 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionDisconnectListener.java new file mode 100644 index 0000000..59ff3e4 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionSubscribeListener.java new file mode 100644 index 0000000..90ee1da --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/listeners/SessionUnsubscribeListener.java new file mode 100644 index 0000000..142bde9 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/services/RestGreetingService.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/RestGreetingService.java new file mode 100644 index 0000000..69db326 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/java/de/spring/stomp/services/UserTradeService.java b/SpringJava/STOMP/spring-stomp-server/src/main/java/de/spring/stomp/services/UserTradeService.java new file mode 100644 index 0000000..1d6bc34 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/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 new file mode 100644 index 0000000..b518e76 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/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 new file mode 100644 index 0000000..e0d63e2 --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/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 index 5ce063e..ebb32ed 100644 --- 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 @@ -1,23 +1,21 @@ package de.spring.webservices.rest.controller; -import java.time.LocalDateTime; - import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.messaging.simp.SimpMessagingTemplate; 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 SimpMessagingTemplate template; + private final RestGreetingService restGreetingService; @Autowired - public RestGreetingController(SimpMessagingTemplate template) { - this.template = template; + public RestGreetingController(RestGreetingService restGreetingService) { + this.restGreetingService = restGreetingService; } // Sending data to /topic/greeting from REST service. @@ -25,10 +23,9 @@ public class RestGreetingController { @RequestMapping(path="/greetings", method=RequestMethod.POST) public void handle(@RequestBody String greeting) { - String text = "[" + LocalDateTime.now() + "]:" + greeting; // STOMP clients subscribed to /topic/greeting will receive the data sent by the convertAndSend method. - this.template.convertAndSend("/topic/greeting", text); + 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 new file mode 100644 index 0000000..718a8bd --- /dev/null +++ b/SpringJava/STOMP/spring-stomp-server/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/src/main/resources/spring-configuration/spring-configuration.xml b/SpringJava/STOMP/spring-stomp-server/src/main/resources/spring-configuration/spring-configuration.xml index 848ddc9..620323b 100644 --- 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 @@ -23,16 +23,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + -- 2.1.4