package com.juick.server.component; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.PingMessage; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; @Component public class JuickServerComponent extends TextWebSocketHandler { private static Logger logger = LoggerFactory.getLogger(JuickServerComponent.class); @Inject private ApplicationEventPublisher applicationEventPublisher; @Inject private ObjectMapper jsonMapper; private WebSocketSession session; private final AtomicBoolean closeFlag = new AtomicBoolean(false); @PostConstruct public void init() { closeFlag.set(false); } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.info("WebSocket connected"); this.session = session; } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { logger.info("WebSocket disconnected with code {}: {}", status.getCode(), status.getReason()); applicationEventPublisher.publishEvent(new DisconnectedEvent(this)); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage text) throws Exception { com.juick.Message jmsg = jsonMapper.readValue(text.asBytes(), com.juick.Message.class); if (logger.isInfoEnabled()) // prevent writeValueAsString execution if logger disabled logger.info("got jmsg: {}", jsonMapper.writeValueAsString(jmsg)); if (!closeFlag.get()) { applicationEventPublisher.publishEvent(new MessageEvent(this, jmsg)); } } @Scheduled(fixedRate = 30000, initialDelay = 30000) public void ping() throws IOException { if (session != null && session.isOpen()) { logger.debug("Sending WebSocket ping"); session.sendMessage(new PingMessage()); } else if (!closeFlag.get()) { applicationEventPublisher.publishEvent(new DisconnectedEvent(this)); } } @PreDestroy public void close() { closeFlag.set(true); } }