diff options
author | 2018-04-12 14:32:44 +0300 | |
---|---|---|
committer | 2018-04-12 14:32:44 +0300 | |
commit | c5649915e6259e921cfd087042525b69533d53b0 (patch) | |
tree | 54e2d7bdba8a21a640b3e2a0c427b72d33c445c2 | |
parent | 9e5a6b3f2f6907f18f22718bcb6f0ac7f79c95cd (diff) |
notifications: pushserver is the only websocket component for now
7 files changed, 84 insertions, 186 deletions
diff --git a/juick-notifications/src/main/java/com/juick/components/CleanUp.java b/juick-notifications/src/main/java/com/juick/components/CleanUp.java deleted file mode 100644 index d0f3e44a..00000000 --- a/juick-notifications/src/main/java/com/juick/components/CleanUp.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.juick.components; - -import com.juick.components.service.TokenService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.ArrayList; - -/** - * Created by vitalyster on 22.11.2016. - */ -@Component -public class CleanUp { - - private static Logger logger = LoggerFactory.getLogger(CleanUp.class); - - @Inject - TokenService tokenService; - - @Inject - Notifications push; - - @Scheduled(fixedRate = 600000) - public void cleanupTokens() { - logger.debug("initializing GCM tokens cleanup: {} tokens", push.getInvalidGCMTokens().size()); - tokenService.deleteTokens("gcm", new ArrayList<>(push.getInvalidGCMTokens())); - push.cleanupGCMTokens(); - logger.debug("initializing MPNS tokens cleanup: {} tokens", push.getInvalidMPNSTokens().size()); - tokenService.deleteTokens("mpns", new ArrayList<>(push.getInvalidMPNSTokens())); - push.cleanupMPNSTokens(); - logger.debug("initializing APNS tokens cleanup: {} tokens", push.getInvalidAPNSTokens().size()); - tokenService.deleteTokens("apns", new ArrayList<>(push.getInvalidAPNSTokens())); - push.cleanupMPNSTokens(); - } -} diff --git a/juick-notifications/src/main/java/com/juick/components/Notifications.java b/juick-notifications/src/main/java/com/juick/components/Notifications.java index ce89de32..439c4bd7 100644 --- a/juick-notifications/src/main/java/com/juick/components/Notifications.java +++ b/juick-notifications/src/main/java/com/juick/components/Notifications.java @@ -22,6 +22,7 @@ import com.google.android.gcm.server.*; import com.juick.ExternalToken; import com.juick.User; import com.juick.formatters.PlainTextFormatter; +import com.juick.server.component.DisconnectedEvent; import com.juick.util.MessageUtils; import com.turo.pushy.apns.ApnsClient; import com.turo.pushy.apns.PushNotificationResponse; @@ -32,10 +33,20 @@ import org.apache.commons.text.StringEscapeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; +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.Nonnull; import javax.annotation.PostConstruct; @@ -45,13 +56,14 @@ import java.io.IOException; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; /** * @author Ugnich Anton */ @Component -public class Notifications implements NotificationClientListener { +public class Notifications extends TextWebSocketHandler implements NotificationClientListener { private static Logger logger = LoggerFactory.getLogger(Notifications.class); @Inject @@ -76,6 +88,7 @@ public class Notifications implements NotificationClientListener { @PostConstruct public void init() throws IOException { mpnsClient.setListener(this); + closeFlag.set(false); } public void messageReceived(@Nonnull com.juick.Message jmsg) { User pmTo = jmsg.getTo(); @@ -202,13 +215,6 @@ public class Notifications implements NotificationClientListener { } } - @PreDestroy - public void close() throws Exception { - apns.close(); - - logger.info("ExternalComponent on notifications destroyed"); - } - public void addInvalidGCMToken(String token) { synchronized (invalidGCMTokens) { invalidGCMTokens.add(token); @@ -252,4 +258,70 @@ public class Notifications implements NotificationClientListener { public Set<String> getInvalidAPNSTokens() { return invalidAPNSTokens; } + @Inject + private ApplicationEventPublisher applicationEventPublisher; + + private WebSocketSession session; + private final AtomicBoolean closeFlag = new AtomicBoolean(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()) { + messageReceived(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() { + apns.close(); + closeFlag.set(true); + } + @Scheduled(fixedRate = 600000) + public void cleanupTokens() { + logger.debug("initializing GCM tokens cleanup: {} tokens", getInvalidGCMTokens().size()); + deleteTokens("gcm", new ArrayList<>(getInvalidGCMTokens())); + cleanupGCMTokens(); + logger.debug("initializing MPNS tokens cleanup: {} tokens", getInvalidMPNSTokens().size()); + deleteTokens("mpns", new ArrayList<>(getInvalidMPNSTokens())); + cleanupMPNSTokens(); + logger.debug("initializing APNS tokens cleanup: {} tokens", getInvalidAPNSTokens().size()); + deleteTokens("apns", new ArrayList<>(getInvalidAPNSTokens())); + cleanupMPNSTokens(); + } + private void deleteTokens(String type, List<String> devices) { + if (devices.size() > 0) { + List<ExternalToken> list = devices.stream() + .map(d -> new ExternalToken(null, type, d, null)).collect(Collectors.toList()); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON_UTF8); + rest.exchange("http://api.juick.com/notifications", + HttpMethod.DELETE, new HttpEntity<>(list, headers), new ParameterizedTypeReference<Void>() { + }); + } + } } diff --git a/juick-notifications/src/main/java/com/juick/components/configuration/JuickServerWebsocketConfiguration.java b/juick-notifications/src/main/java/com/juick/components/configuration/JuickServerWebsocketConfiguration.java index 0cecb597..a29566aa 100644 --- a/juick-notifications/src/main/java/com/juick/components/configuration/JuickServerWebsocketConfiguration.java +++ b/juick-notifications/src/main/java/com/juick/components/configuration/JuickServerWebsocketConfiguration.java @@ -1,7 +1,7 @@ package com.juick.components.configuration; import com.fasterxml.jackson.databind.ObjectMapper; -import com.juick.components.service.JuickServerComponent; +import com.juick.components.Notifications; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,7 +22,6 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient; import org.springframework.web.util.UriComponentsBuilder; import javax.inject.Inject; -import java.io.IOException; import java.util.Collections; import java.util.List; @@ -40,7 +39,7 @@ public class JuickServerWebsocketConfiguration { @Inject ObjectMapper jsonMapper; @Inject - private JuickServerComponent juickServerComponent; + private Notifications notifications; @Bean public RestTemplate rest() { RestTemplate rest = new RestTemplate(); @@ -62,7 +61,7 @@ public class JuickServerWebsocketConfiguration { } String websocketURI = UriComponentsBuilder.fromUriString(baseUri) .queryParam("hash", hash).build().toUriString(); - WebSocketConnectionManager manager = new WebSocketConnectionManager(client(), juickServerComponent, websocketURI); + WebSocketConnectionManager manager = new WebSocketConnectionManager(client(), notifications, websocketURI); return manager; } @Bean diff --git a/juick-notifications/src/main/java/com/juick/components/service/JuickServerComponent.java b/juick-notifications/src/main/java/com/juick/components/service/JuickServerComponent.java deleted file mode 100644 index 0f62e702..00000000 --- a/juick-notifications/src/main/java/com/juick/components/service/JuickServerComponent.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.juick.components.service; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.juick.components.Notifications; -import com.juick.server.component.DisconnectedEvent; -import com.juick.server.component.MessageEvent; -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 Notifications notifications; - @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()) { - notifications.messageReceived(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); - } - -} diff --git a/juick-notifications/src/main/java/com/juick/components/service/NotificationsTokenService.java b/juick-notifications/src/main/java/com/juick/components/service/NotificationsTokenService.java deleted file mode 100644 index 6e6c8632..00000000 --- a/juick-notifications/src/main/java/com/juick/components/service/NotificationsTokenService.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.juick.components.service; - -import com.juick.ExternalToken; -import com.juick.service.BaseRestService; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import javax.inject.Inject; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Created by vitalyster on 15.12.2016. - */ -@Service -public class NotificationsTokenService extends BaseRestService implements TokenService { - - @Inject - public NotificationsTokenService(RestTemplate rest) { - super(rest); - } - - @Override - public void deleteTokens(String type, List<String> devices) { - if (devices.size() > 0) { - List<ExternalToken> list = devices.stream() - .map(d -> new ExternalToken(null, type, d, null)).collect(Collectors.toList()); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON_UTF8); - getRest().exchange("http://api.juick.com/notifications", - HttpMethod.DELETE, new HttpEntity<>(list, headers), new ParameterizedTypeReference<Void>() { - }); - } - } -} diff --git a/juick-notifications/src/main/java/com/juick/components/service/TokenService.java b/juick-notifications/src/main/java/com/juick/components/service/TokenService.java deleted file mode 100644 index 2a578386..00000000 --- a/juick-notifications/src/main/java/com/juick/components/service/TokenService.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.juick.components.service; - -import java.util.List; - -/** - * Created by vitalyster on 15.12.2016. - */ -public interface TokenService { - void deleteTokens(String type, List<String> list); -} diff --git a/juick-notifications/src/test/java/com/juick/components/test/NotificationTests.java b/juick-notifications/src/test/java/com/juick/components/test/NotificationTests.java index f1a4787d..573771fc 100644 --- a/juick-notifications/src/test/java/com/juick/components/test/NotificationTests.java +++ b/juick-notifications/src/test/java/com/juick/components/test/NotificationTests.java @@ -21,12 +21,9 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.spi.LoggingEvent; import ch.qos.logback.core.Appender; -import com.juick.components.CleanUp; import com.juick.components.Notifications; -import com.juick.components.service.TokenService; import org.junit.Before; import org.junit.Test; -import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.slf4j.LoggerFactory; @@ -41,14 +38,10 @@ import static org.mockito.Mockito.*; * Created by vitalyster on 22.11.2016. */ public class NotificationTests { - @InjectMocks - CleanUp cleanUp; @Mock RestTemplate rest; @Mock - TokenService tokenService; - @Mock Notifications push; @@ -66,7 +59,7 @@ public class NotificationTests { when(mockAppender.getName()).thenReturn("MOCK"); root.setLevel(Level.DEBUG); root.addAppender(mockAppender); - cleanUp.cleanupTokens(); + push.cleanupTokens(); verify(mockAppender).doAppend(argThat(argument -> ((LoggingEvent)argument).getFormattedMessage().contains("1 tokens"))); } |