├── .project ├── LICENSE ├── README.md └── slime-microservice-chat ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.m2e.core.prefs └── org.eclipse.wst.common.project.facet.core.xml ├── README.md ├── pom.xml ├── slime-common ├── .classpath ├── .gitignore ├── .project ├── .settings │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml ├── src │ └── main │ │ ├── java │ │ └── io │ │ │ └── slime │ │ │ └── chat │ │ │ └── common │ │ │ ├── Launcher.java │ │ │ ├── redis │ │ │ ├── AbstractRedisClient.java │ │ │ ├── JedisConnectionPool.java │ │ │ ├── RedisDaemonClient.java │ │ │ ├── RedisHttpClient.java │ │ │ ├── RedisKeyStore.java │ │ │ └── RedisSockjsClient.java │ │ │ ├── spring │ │ │ ├── SpringConfiguration.java │ │ │ └── service │ │ │ │ ├── RequestLogService.java │ │ │ │ └── impl │ │ │ │ └── RequestLogServiceImpl.java │ │ │ └── util │ │ │ ├── VertxHolder.java │ │ │ └── WebSocketSessionHolder.java │ │ └── resources │ │ └── cluster.xml └── target │ └── classes │ └── META-INF │ ├── MANIFEST.MF │ └── maven │ └── io.slime.workshop │ └── slime-common │ ├── pom.properties │ └── pom.xml ├── slime-http ├── .classpath ├── .gitignore ├── .project ├── .settings │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml ├── src │ ├── conf │ │ └── config_properties.json │ └── main │ │ ├── java │ │ └── io │ │ │ └── slime │ │ │ └── chat │ │ │ └── http │ │ │ └── HttpServer.java │ │ └── resources │ │ └── webroot │ │ ├── chat │ │ ├── assets │ │ │ ├── css │ │ │ │ ├── bootstrap.css │ │ │ │ └── bootstrap.css.map │ │ │ ├── img │ │ │ │ ├── favicon.png │ │ │ │ ├── user.png │ │ │ │ └── user_offline.png │ │ │ └── js │ │ │ │ ├── chat.js │ │ │ │ ├── jquery-1.12.3.min.js │ │ │ │ ├── sockjs-1.1.0.min.js │ │ │ │ ├── sprintf.min.js │ │ │ │ ├── sprintf.min.js.map │ │ │ │ └── vertxbus.js │ │ └── index.html │ │ └── error │ │ └── 404.html └── target │ └── classes │ ├── META-INF │ ├── MANIFEST.MF │ └── maven │ │ └── io.slime.workshop │ │ └── slime-http │ │ ├── pom.properties │ │ └── pom.xml │ └── webroot │ ├── chat │ ├── assets │ │ ├── css │ │ │ ├── bootstrap.css │ │ │ └── bootstrap.css.map │ │ ├── img │ │ │ ├── favicon.png │ │ │ ├── user.png │ │ │ └── user_offline.png │ │ └── js │ │ │ ├── chat.js │ │ │ ├── jquery-1.12.3.min.js │ │ │ ├── sockjs-1.1.0.min.js │ │ │ ├── sprintf.min.js │ │ │ ├── sprintf.min.js.map │ │ │ └── vertxbus.js │ └── index.html │ └── error │ └── 404.html ├── slime-publish ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml ├── src │ ├── conf │ │ └── config_properties.json │ └── main │ │ └── java │ │ └── io │ │ └── slime │ │ └── chat │ │ └── publish │ │ └── MessagePublishVerticle.java └── target │ ├── .gitignore │ └── classes │ └── META-INF │ └── maven │ └── io.slime.workshop │ └── slime-publish │ ├── pom.properties │ └── pom.xml ├── slime-search ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml └── target │ └── .gitignore ├── slime-sockjs ├── .classpath ├── .gitignore ├── .project ├── .settings │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml ├── src │ ├── conf │ │ └── config_properties.json │ └── main │ │ └── java │ │ └── io │ │ └── slime │ │ └── chat │ │ └── sockjs │ │ ├── PubSubSockJsServer.java │ │ ├── eventbridge │ │ ├── EventBridgeChain.java │ │ ├── EventBridgeChainException.java │ │ ├── EventBridgeChainHandler.java │ │ ├── EventBridgeChainResponse.java │ │ └── chain │ │ │ ├── ChatMessageChainHandler.java │ │ │ ├── LoginChainHandler.java │ │ │ └── OfflineChainHandler.java │ │ ├── spring │ │ └── SpringConfigurationSockjs.java │ │ └── subscribe │ │ └── MessageSubscribeVerticle.java └── target │ └── classes │ └── META-INF │ ├── MANIFEST.MF │ └── maven │ └── io.slime.workshop │ └── slime-sockjs │ ├── pom.properties │ └── pom.xml └── target ├── maven-archiver └── pom.properties ├── slime-microservice-chat-0.0.1-SNAPSHOT-sources.jar └── slime-microservice-chat-0.0.1-SNAPSHOT-tests.jar /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | slime 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 GoodRhys 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slime microservice chat example 2 | 3 | ## Content 4 | 5 | * Vert.x 6 | * Chat Microservices 7 | * Message Queue ( Redis Queue ) 8 | * 10,000 peoples in same chat room. 9 | * Distributed message server 10 | 11 | ## Requirement 12 | * Maven (https://maven.apache.org/) 13 | * JDK 1.8 (http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 14 | * Redis (https://redis.io) 15 | 16 | ## Building 17 | 18 | To build the code: 19 | 20 | cd slime-http 21 | mvn clean package 22 | java -jar target/slime-http-0.0.1-SNAPSHOT-fat.jar 23 | 24 | cd slime-sockjs 25 | mvn clean package 26 | java -jar target/slime-sockjs-0.0.1-SNAPSHOT-fat.jar 27 | 28 | == REDIS MQ : Routing Message == 29 | cd slime-publish 30 | mvn clean package 31 | java -jar target/slime-publish-0.0.1-SNAPSHOT-fat.jar 32 | 33 | And connect your browser http://localhost:8080/ 34 | 35 | ## Comming Soon other examples 36 | 37 | 38 | ## Reference Project 39 | - https://github.com/sayseakleng/vertx-eventbus-chat 40 | - https://github.com/cescoffier/vertx-microservices-workshop 41 | -------------------------------------------------------------------------------- /slime-microservice-chat/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | slime-microservice-chat 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.common.project.facet.core.builder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.m2e.core.maven2Nature 21 | org.eclipse.wst.common.project.facet.core.nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /slime-microservice-chat/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /slime-microservice-chat/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /slime-microservice-chat/.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /slime-microservice-chat/README.md: -------------------------------------------------------------------------------- 1 | # slime microservice chat example 2 | 3 | ## Content 4 | 5 | * Vert.x 6 | * Chat Microservices 7 | * Message Queue 8 | * 10,000 peoples in same chat room. 9 | * Distributed message server 10 | 11 | ## Requirement 12 | * Maven (https://maven.apache.org/) 13 | * JDK 1.8 (http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 14 | * Redis (https://redis.io) 15 | 16 | ## Building 17 | 18 | To build the code: 19 | 20 | cd slime-http 21 | mvn clean package 22 | java -jar target/slime-http-0.0.1-SNAPSHOT-fat.jar 23 | 24 | cd slime-sockjs 25 | mvn clean package 26 | java -jar target/slime-sockjs-0.0.1-SNAPSHOT-fat.jar 27 | 28 | == REDIS MQ 사용 == 29 | cd slime-publish 30 | mvn clean package 31 | java -jar target/slime-publish-0.0.1-SNAPSHOT-fat.jar 32 | 33 | And connect your browser http://localhost:8080/ 34 | 35 | ## Comming Soon other examples 36 | 37 | 38 | ## Reference Project 39 | - https://github.com/sayseakleng/vertx-eventbus-chat 40 | - https://github.com/cescoffier/vertx-microservices-workshop -------------------------------------------------------------------------------- /slime-microservice-chat/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | io.slime.workshop 4 | slime-microservice-chat 5 | 0.0.1-SNAPSHOT 6 | 7 | 8 | io.vertx 9 | vertx-ext-parent 10 | 20 11 | 12 | 13 | pom 14 | 15 | 16 | 3.3.3 17 | true 18 | 1.8 19 | 2.8.1 20 | 4.2.6.RELEASE 21 | 22 | 23 | 24 | 25 | 26 | 27 | slime-common 28 | slime-http 29 | slime-sockjs 30 | slime-publish 31 | slime-search 32 | 33 | 34 | 35 | 36 | 37 | io.vertx 38 | vertx-dependencies 39 | ${stack.version} 40 | pom 41 | import 42 | 43 | 44 | 45 | 46 | 47 | 48 | io.vertx 49 | vertx-core 50 | 51 | 52 | io.vertx 53 | vertx-service-proxy 54 | 55 | 56 | io.vertx 57 | vertx-lang-groovy 58 | 59 | 60 | io.vertx 61 | vertx-lang-js 62 | 63 | 64 | io.vertx 65 | vertx-codegen 66 | true 67 | 68 | 69 | io.vertx 70 | vertx-sockjs-service-proxy 71 | 72 | 73 | 74 | io.vertx 75 | vertx-web 76 | 77 | 78 | io.vertx 79 | vertx-hazelcast 80 | 81 | 82 | 83 | 84 | io.vertx 85 | vertx-service-discovery 86 | 87 | 88 | io.vertx 89 | vertx-circuit-breaker 90 | 91 | 92 | 93 | ch.qos.logback 94 | logback-classic 95 | 1.1.7 96 | 97 | 98 | org.slf4j 99 | jcl-over-slf4j 100 | 1.7.21 101 | 102 | 103 | 104 | org.springframework 105 | spring-core 106 | ${org.springframework-version} 107 | 108 | 109 | org.springframework 110 | spring-context 111 | ${org.springframework-version} 112 | 113 | 114 | 115 | 116 | org.mybatis 117 | mybatis 118 | 3.4.0 119 | 120 | 121 | org.mybatis 122 | mybatis-spring 123 | 1.3.0 124 | 125 | 126 | commons-dbcp 127 | commons-dbcp 128 | 1.4 129 | 130 | 131 | 132 | redis.clients 133 | jedis 134 | ${jedis.version} 135 | 136 | 137 | 138 | 139 | io.vertx 140 | vertx-unit 141 | test 142 | 143 | 144 | junit 145 | junit 146 | 4.12 147 | test 148 | 149 | 150 | org.assertj 151 | assertj-core 152 | 3.5.2 153 | test 154 | 155 | 156 | com.jayway.awaitility 157 | awaitility 158 | 1.7.0 159 | test 160 | 161 | 162 | com.jayway.restassured 163 | rest-assured 164 | 2.9.0 165 | test 166 | 167 | 168 | org.springframework 169 | spring-test 170 | ${org.springframework-version} 171 | test 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | maven-compiler-plugin 180 | 181 | 1.8 182 | 1.8 183 | 184 | 185 | 186 | default-compile 187 | 188 | 189 | io.vertx.codegen.CodeGenProcessor 190 | 191 | src/main/generated 192 | 193 | -AoutputDirectory=${project.basedir}/src/main 194 | 195 | 196 | 197 | 198 | default-testCompile 199 | 200 | 201 | io.vertx.codegen.CodeGenProcessor 202 | 203 | src/test/generated 204 | 205 | -AoutputDirectory=${project.basedir}/src/test 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | maven-compiler-plugin 217 | 3.1 218 | 219 | 1.8 220 | 1.8 221 | 222 | 223 | 224 | 225 | maven-dependency-plugin 226 | 2.10 227 | 228 | 229 | unpack-hazelcast-configuration 230 | process-resources 231 | 232 | unpack-dependencies 233 | 234 | 235 | slime-common 236 | ${project.build.directory}/classes 237 | **/cluster.xml 238 | 239 | 240 | 241 | 242 | 243 | 244 | org.apache.maven.plugins 245 | maven-shade-plugin 246 | 2.4.3 247 | 248 | 249 | package 250 | 251 | shade 252 | 253 | 254 | 255 | 256 | 257 | io.slime.chat.common.Launcher 258 | ${main.verticle} 259 | 260 | 261 | 262 | META-INF/services/io.vertx.core.spi.VerticleFactory 263 | 264 | 265 | 266 | 267 | ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar 268 | 269 | 270 | 271 | 272 | 273 | 274 | org.eclipse.m2e 275 | lifecycle-mapping 276 | 1.0.0 277 | 278 | 279 | 280 | 281 | 282 | org.codehaus.gmavenplus 283 | gmavenplus-plugin 284 | [1.0.0,) 285 | 286 | compile 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | org.apache.maven.plugins 296 | maven-dependency-plugin 297 | [2.10.0.0,) 298 | 299 | unpack-dependencies 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | slime-common 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/test/java=UTF-8 5 | encoding//src/test/resources=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.8 6 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | io.slime.workshop 5 | slime-microservice-chat 6 | 0.0.1-SNAPSHOT 7 | 8 | slime-common 9 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/Launcher.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.net.InetAddress; 6 | import java.util.Scanner; 7 | 8 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 9 | 10 | import io.slime.chat.common.redis.RedisDaemonClient; 11 | import io.slime.chat.common.redis.RedisHttpClient; 12 | import io.slime.chat.common.redis.RedisSockjsClient; 13 | import io.slime.chat.common.spring.SpringConfiguration; 14 | import io.vertx.core.DeploymentOptions; 15 | import io.vertx.core.VertxOptions; 16 | import io.vertx.core.json.DecodeException; 17 | import io.vertx.core.json.JsonObject; 18 | 19 | public class Launcher extends io.vertx.core.Launcher { 20 | 21 | public static void main(String[] args) { 22 | new Launcher().dispatch(args); 23 | } 24 | 25 | @SuppressWarnings("resource") 26 | @Override 27 | public void beforeStartingVertx(VertxOptions options) { 28 | new AnnotationConfigApplicationContext(SpringConfiguration.class); 29 | // options.setClustered(true) 30 | // .setClusterHost("127.0.0.1"); 31 | } 32 | 33 | @Override 34 | public void beforeDeployingVerticle(DeploymentOptions deploymentOptions) { 35 | super.beforeDeployingVerticle(deploymentOptions); 36 | 37 | if (deploymentOptions.getConfig() == null) { 38 | deploymentOptions.setConfig(new JsonObject()); 39 | } 40 | 41 | File conf = new File("src/conf/config.json"); 42 | deploymentOptions.getConfig().mergeIn(getConfiguration(conf)); 43 | 44 | File conf_properties = new File("src/conf/config_properties.json"); 45 | JsonObject properties = getConfiguration(conf_properties); 46 | if(properties.containsKey("type")){ 47 | switch(properties.getString("type")){ 48 | case "sockjs": 49 | try { 50 | InetAddress Address = InetAddress.getLocalHost(); 51 | new RedisSockjsClient("localhost", 6379, Address.getHostAddress()+":"+properties.getInteger("port")); 52 | } catch (Exception e) { 53 | e.printStackTrace(); 54 | } 55 | break; 56 | case "http": 57 | try { 58 | InetAddress Address = InetAddress.getLocalHost(); 59 | new RedisHttpClient("localhost", 6379, Address.getHostAddress()+":"+properties.getInteger("port")); 60 | } catch (Exception e) { 61 | e.printStackTrace(); 62 | } 63 | break; 64 | case "daemon": 65 | try { 66 | InetAddress Address = InetAddress.getLocalHost(); 67 | new RedisDaemonClient("localhost", 6379, Address.getHostAddress()+":"+RedisDaemonClient.getPID()); 68 | } catch (Exception e) { 69 | e.printStackTrace(); 70 | } 71 | break; 72 | } 73 | 74 | } 75 | 76 | } 77 | 78 | private JsonObject getConfiguration(File config) { 79 | JsonObject conf = new JsonObject(); 80 | if (config.isFile()) { 81 | System.out.println("Reading config file: " + config.getAbsolutePath()); 82 | try (Scanner scanner = new Scanner(config).useDelimiter("\\A")) { 83 | String sconf = scanner.next(); 84 | try { 85 | conf = new JsonObject(sconf); 86 | } catch (DecodeException e) { 87 | System.err.println("Configuration file " + sconf + " does not contain a valid JSON object"); 88 | } 89 | } catch (FileNotFoundException e) { 90 | // Ignore it. 91 | } 92 | } else { 93 | System.out.println("Config file not found " + config.getAbsolutePath()); 94 | } 95 | return conf; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/redis/AbstractRedisClient.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.redis; 2 | 3 | import java.lang.management.ManagementFactory; 4 | import java.util.List; 5 | 6 | import redis.clients.jedis.Jedis; 7 | 8 | public class AbstractRedisClient { 9 | 10 | protected static String serverKey; 11 | 12 | public static String getServerKey() { 13 | return serverKey; 14 | } 15 | 16 | protected static List BRPOP(int timeout, String key) throws Exception { 17 | Jedis jedis = null; 18 | try { 19 | jedis = JedisConnectionPool.getJedisConnection(); 20 | return BRPOP(timeout, key, jedis); 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | return null; 24 | } finally { 25 | if (jedis != null) 26 | JedisConnectionPool.close(jedis); 27 | } 28 | } 29 | 30 | protected static List BRPOP(int timeout, String key, Jedis jedis) throws Exception { 31 | List list = jedis.brpop(timeout, key); 32 | return list; 33 | } 34 | 35 | protected static String RPOP(String key) throws Exception { 36 | Jedis jedis = null; 37 | try { 38 | jedis = JedisConnectionPool.getJedisConnection(); 39 | return RPOP(key, jedis); 40 | } catch (Exception e) { 41 | e.printStackTrace(); 42 | return null; 43 | } finally { 44 | if (jedis != null) 45 | JedisConnectionPool.close(jedis); 46 | } 47 | } 48 | 49 | protected static String RPOP(String key, Jedis jedis) throws Exception { 50 | String str = jedis.rpop(key); 51 | return str; 52 | } 53 | 54 | protected static void LPUSH(String key, String message, Jedis jedis) { 55 | jedis.lpush(key, message); 56 | } 57 | 58 | protected static void HSET(String key, String field, String message, Jedis jedis) throws Exception { 59 | jedis.hset(key, field, message); 60 | } 61 | 62 | protected static String SESSION(String key) throws Exception { 63 | return ""; 64 | } 65 | 66 | protected static String HGET(String key, String field) throws Exception { 67 | Jedis jedis = null; 68 | try { 69 | jedis = JedisConnectionPool.getJedisConnection(); 70 | return HGET(jedis, key, field); 71 | } catch (Exception e) { 72 | e.printStackTrace(); 73 | return null; 74 | } finally { 75 | if (jedis != null) 76 | JedisConnectionPool.close(jedis); 77 | } 78 | } 79 | 80 | protected static String HGET(Jedis jedis, String key, String field) throws Exception { 81 | String r = jedis.hget(key, field); 82 | return r; 83 | } 84 | 85 | protected static String HGETDEL(String key, String field) throws Exception { 86 | Jedis jedis = null; 87 | try { 88 | jedis = JedisConnectionPool.getJedisConnection(); 89 | return HGETDEL(key, field, jedis); 90 | } catch (Exception e) { 91 | e.printStackTrace(); 92 | return null; 93 | } finally { 94 | if (jedis != null) 95 | JedisConnectionPool.close(jedis); 96 | } 97 | } 98 | 99 | protected static String HGETDEL(String key, String field, Jedis jedis) throws Exception { 100 | String r = jedis.hget(key, field); 101 | jedis.hdel(key, field); 102 | return r; 103 | } 104 | 105 | public static String getPID() { 106 | return ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; 107 | } 108 | 109 | public AbstractRedisClient() { 110 | super(); 111 | } 112 | 113 | protected static void LOG_CNT(Jedis jedis, String key, String field) { 114 | jedis.select(10); 115 | jedis.zincrby(RedisKeyStore.LOG + ":" + key, -1D, field); 116 | } 117 | 118 | protected static void LOG_MSG(Jedis jedis, String key, String msg) { 119 | jedis.select(10); 120 | jedis.lpush(RedisKeyStore.LOG + ":" + key, msg); 121 | } 122 | } -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/redis/JedisConnectionPool.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.redis; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Timer; 6 | import java.util.TimerTask; 7 | 8 | import redis.clients.jedis.Jedis; 9 | import redis.clients.jedis.JedisPool; 10 | import redis.clients.jedis.JedisPoolConfig; 11 | import redis.clients.jedis.exceptions.JedisConnectionException; 12 | 13 | public class JedisConnectionPool { 14 | 15 | private static JedisPool jedisPoolA; 16 | private static String host; 17 | private static int port; 18 | 19 | private static boolean status = true; 20 | private static JedisPool jedisPoolB; 21 | 22 | private static List jedisPools = new ArrayList(); 23 | private static String[] arrAddress; 24 | 25 | public static void close(Jedis jedis) { 26 | if (jedis != null) { 27 | if (jedis != null && jedis.isConnected()) { 28 | jedis.close(); 29 | } 30 | } 31 | } 32 | 33 | public JedisConnectionPool() { 34 | if (jedisPoolA == null) { 35 | String host = "localhost"; 36 | int port = 6379; 37 | try { 38 | initJedisPool(host, port); 39 | } catch (Exception e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | } 44 | 45 | /** 46 | * @param host 47 | * redis.server.ip 48 | * @param port 49 | * redis.server.port 50 | */ 51 | public JedisConnectionPool(String h, int p) throws Exception { 52 | if (jedisPoolA == null) { 53 | host = h; 54 | port = p; 55 | try { 56 | JedisPool pool = initJedisPool(host, port); 57 | if (pool != null) { 58 | jedisPoolA = pool; 59 | } else { 60 | throw new Exception("Redis Connection Error - " + h + ":" + p); 61 | } 62 | } catch (Exception e) { 63 | e.printStackTrace(); 64 | } 65 | } 66 | } 67 | 68 | public JedisConnectionPool(String[] urls) throws Exception { 69 | if (jedisPoolA == null) { 70 | arrAddress = urls; 71 | for (String url : urls) { 72 | String h = url.split("\\:")[0]; 73 | int p = Integer.parseInt(url.split("\\:")[1]); 74 | JedisPool pool = initJedisPool(h, p); 75 | if (pool != null) { 76 | jedisPools.add(pool); 77 | } else { 78 | continue; 79 | } 80 | } 81 | 82 | jedisPoolA = jedisPools.get(0); 83 | jedisPools.remove(0); 84 | if (jedisPools.size() > 0) { 85 | jedisPoolB = jedisPools.get(0); 86 | startTimmerForHA(); 87 | } 88 | } 89 | } 90 | 91 | /** 92 | * @Method Name : getJedisConnection 93 | * @date : 2016. 7. 13. 94 | * @author : goodrhys 95 | * @history : 96 | * ----------------------------------------------------------------------- 97 | * 변경일 작성자 변경내용 ----------- ------------------- 98 | * --------------------------------------- 2016. 7. 13. goodrhys 최초 99 | * 작성 100 | * ----------------------------------------------------------------------- 101 | * 102 | * @return 103 | */ 104 | public static Jedis getJedisConnection() { // koushik: removed static 105 | try { 106 | if (jedisPoolA == null) { 107 | String host = "localhost"; 108 | int port = 6379; 109 | 110 | try { 111 | initJedisPool(host, port); 112 | } catch (Exception e) { 113 | e.printStackTrace(); 114 | return null; 115 | } 116 | } 117 | // System.out.println(jedisPoolA); 118 | // System.out.println(host); 119 | // System.out.println(jedisPoolA.getNumActive()); 120 | // System.out.println(jedisPoolA.getNumIdle()); 121 | // System.out.println(jedisPoolA.isClosed()); 122 | // System.out.println(jedisPoolA.getNumWaiters()); 123 | // System.out.println(jedisPoolA.toString()); 124 | return jedisPoolA.getResource(); 125 | } catch (JedisConnectionException e) { 126 | e.printStackTrace(); 127 | return null; 128 | } 129 | } 130 | 131 | public static Jedis getJedisConnection(int db) { // koushik: removed static 132 | try { 133 | if (jedisPoolA == null) { 134 | String host = "localhost"; 135 | int port = 6379; 136 | 137 | initJedisPool(host, port); 138 | } 139 | // System.out.println(jedisPool); 140 | // System.out.println(jedisPool.getNumActive()); 141 | // System.out.println(jedisPool.getNumIdle()); 142 | // System.out.println(jedisPool.isClosed()); 143 | // System.out.println(jedisPool.getNumWaiters()); 144 | // System.out.println(jedisPool.toString()); 145 | Jedis jedis = jedisPoolA.getResource(); 146 | jedis.select(db); 147 | 148 | return jedis; 149 | } catch (Exception e) { 150 | if (jedisPoolA == null) { 151 | System.out.println(jedisPoolA); 152 | System.out.println(jedisPoolA.getNumActive()); 153 | System.out.println(jedisPoolA.getNumIdle()); 154 | System.out.println(jedisPoolA.isClosed()); 155 | System.out.println(jedisPoolA.getNumWaiters()); 156 | System.out.println(jedisPoolA.toString()); 157 | } 158 | e.printStackTrace(); 159 | return null; 160 | } 161 | } 162 | 163 | /** 164 | * @Method Name : initJedisPool 165 | * @date : 2016. 7. 13. 166 | * @author : goodrhys 167 | * @history : 168 | * ----------------------------------------------------------------------- 169 | * 변경일 작성자 변경내용 ----------- ------------------- 170 | * --------------------------------------- 2016. 7. 13. goodrhys 최초 171 | * 작성 172 | * ----------------------------------------------------------------------- 173 | * 174 | * @param host 175 | * @param port 176 | */ 177 | private static JedisPool initJedisPool(String host, int port) throws Exception { 178 | JedisPool r = null; 179 | JedisPoolConfig config = new JedisPoolConfig(); 180 | config.setMaxTotal(20); 181 | config.setMaxIdle(10); 182 | config.setMinIdle(10); 183 | config.setMaxWaitMillis(30000); 184 | try { 185 | r = new JedisPool(config, host, port); 186 | Jedis j = r.getResource(); 187 | j.close(); 188 | } catch (JedisConnectionException e) { 189 | r = null; 190 | e.printStackTrace(); 191 | } catch (Exception e) { 192 | r = null; 193 | e.printStackTrace(); 194 | } 195 | 196 | return r; 197 | } 198 | 199 | private static JedisPool initJedisPool(String host, int port, int maxCnt) throws Exception { 200 | JedisPool r = null; 201 | JedisPoolConfig config = new JedisPoolConfig(); 202 | config.setMaxTotal(maxCnt); 203 | config.setMaxIdle(10); 204 | config.setMinIdle(10); 205 | config.setMaxWaitMillis(30000); 206 | try { 207 | r = new JedisPool(config, host, port); 208 | Jedis j = r.getResource(); 209 | j.close(); 210 | } catch (JedisConnectionException e) { 211 | r = null; 212 | e.printStackTrace(); 213 | } catch (Exception e) { 214 | r = null; 215 | e.printStackTrace(); 216 | } 217 | 218 | return r; 219 | } 220 | 221 | public static void changePool() { 222 | if (status) { 223 | status = false; 224 | Jedis jedis = null; 225 | try { 226 | jedis = jedisPoolB.getResource(); 227 | String ping = jedis.ping(); 228 | if (ping != null && ping.equals("PONG")) { 229 | 230 | // TODO reset redis now ! 231 | 232 | jedisPoolA = jedisPoolB; 233 | if (jedisPools.size() > 0) { 234 | jedisPoolB = jedisPools.get(0); 235 | jedisPools.remove(0); 236 | } 237 | } 238 | } catch (Exception e) { 239 | e.printStackTrace(); 240 | } finally { 241 | if (jedis != null) 242 | jedis.close(); 243 | } 244 | } 245 | } 246 | 247 | private void startTimmerForHA() { 248 | int delay = 5000;// delay for 5 sec. 249 | int interval = 1000; // iterate every sec. 250 | Timer timer = new Timer(); 251 | timer.scheduleAtFixedRate(new TimerTask() { 252 | public void run() { 253 | Jedis jedis = null; 254 | try { 255 | jedis = JedisConnectionPool.getJedisConnection(); 256 | String ping = jedis.ping(); 257 | // System.out.println("22222"); 258 | changeRedisPool(); 259 | } catch (Exception e) { 260 | changeRedisPool(); 261 | } finally { 262 | if (jedis != null) 263 | JedisConnectionPool.close(jedis); 264 | } 265 | } 266 | }, delay, interval); 267 | } 268 | 269 | private void changeRedisPool() { 270 | // System.out.println("111111"); 271 | } 272 | } -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/redis/RedisDaemonClient.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.redis; 2 | 3 | import java.util.Iterator; 4 | import java.util.List; 5 | 6 | import io.vertx.core.Vertx; 7 | import io.vertx.core.json.JsonObject; 8 | import redis.clients.jedis.Jedis; 9 | 10 | public class RedisDaemonClient extends AbstractRedisClient { 11 | 12 | public RedisDaemonClient(String host, int port, String key) throws Exception { 13 | System.out.println("REDIS CONNECTION INIT !!! " + host + ":" + port); 14 | new JedisConnectionPool(host, port); 15 | serverKey = key; 16 | pingDaemonServer(); 17 | } 18 | 19 | public RedisDaemonClient(String[] urls, String key) throws Exception { 20 | new JedisConnectionPool(urls); 21 | serverKey = key; 22 | pingDaemonServer(); 23 | } 24 | 25 | public static void pingDaemonServer() { 26 | Jedis jedis = null; 27 | JsonObject status = new JsonObject(); 28 | status.put("status", true); 29 | status.put("time", System.currentTimeMillis()); 30 | try { 31 | jedis = JedisConnectionPool.getJedisConnection(10); 32 | HSET(RedisKeyStore.DAEMON.getMaster(), serverKey, status.toString(), jedis); 33 | } catch (Exception e) { 34 | e.printStackTrace(); 35 | } finally { 36 | if (jedis != null) 37 | JedisConnectionPool.close(jedis); 38 | } 39 | } 40 | 41 | public static void pingDaemonInstance(String deplomentId, boolean isD) { 42 | Jedis jedis = null; 43 | JsonObject status = new JsonObject(); 44 | status.put("status", isD); 45 | status.put("time", System.currentTimeMillis()); 46 | try { 47 | jedis = JedisConnectionPool.getJedisConnection(); 48 | jedis.select(10); 49 | HSET(RedisKeyStore.DAEMON.name(), serverKey + ":" + deplomentId, status.toString(), jedis); 50 | } catch (Exception e) { 51 | e.printStackTrace(); 52 | } finally { 53 | if (jedis != null && jedis.isConnected()) 54 | JedisConnectionPool.close(jedis); 55 | } 56 | } 57 | 58 | public static boolean daemonManageFunction(String resStr, Vertx vertx) { 59 | boolean ret_ = true; 60 | if (resStr.indexOf("PING:") > -1) { 61 | if (resStr.indexOf("PING:INSTANCE") > -1) { 62 | boolean isD = false; 63 | String dID = resStr.split(":")[2]; 64 | Iterator it = vertx.deploymentIDs().iterator(); 65 | while (it.hasNext()) { 66 | String dID_ = it.next(); 67 | System.out.println(dID_ + "$$$"); 68 | if (dID.equals(dID_)) { 69 | isD = true; 70 | break; 71 | } 72 | } 73 | if (isD) 74 | RedisDaemonClient.pingDaemonInstance(dID, isD); 75 | } else if (resStr.indexOf("PING:MASTER") > -1) { 76 | RedisDaemonClient.pingDaemonServer(); 77 | } 78 | ret_ = false; 79 | } else { 80 | 81 | } 82 | return ret_; 83 | } 84 | 85 | public static List getPublishMaster(int timeout) { 86 | Jedis jedis = null; 87 | try { 88 | jedis = JedisConnectionPool.getJedisConnection(); 89 | return BRPOP(timeout, RedisKeyStore.PUBLISH.getMaster(), jedis); 90 | } catch (Exception e) { 91 | e.printStackTrace(); 92 | return null; 93 | } finally { 94 | if (jedis != null) 95 | JedisConnectionPool.close(jedis); 96 | } 97 | } 98 | 99 | public static String getPublishMasterD() { 100 | Jedis jedis = null; 101 | try { 102 | jedis = JedisConnectionPool.getJedisConnection(); 103 | return RPOP(RedisKeyStore.PUBLISH.getMaster(), jedis); 104 | } catch (Exception e) { 105 | e.printStackTrace(); 106 | return null; 107 | } finally { 108 | if (jedis != null) 109 | JedisConnectionPool.close(jedis); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/redis/RedisHttpClient.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.redis; 2 | 3 | import java.util.Iterator; 4 | 5 | import io.vertx.core.Vertx; 6 | import io.vertx.core.json.JsonObject; 7 | import redis.clients.jedis.Jedis; 8 | 9 | public class RedisHttpClient extends AbstractRedisClient { 10 | 11 | public RedisHttpClient(String host, int port, String key) throws Exception { 12 | System.out.println("REDIS CONNECTION INIT !!! " + host + ":" + port); 13 | new JedisConnectionPool(host, port); 14 | serverKey = key; 15 | pingDaemonServer(); 16 | } 17 | 18 | public RedisHttpClient(String[] urls, String key) throws Exception { 19 | new JedisConnectionPool(urls); 20 | serverKey = key; 21 | pingDaemonServer(); 22 | } 23 | 24 | public static void pingDaemonServer() { 25 | Jedis jedis = null; 26 | try { 27 | jedis = JedisConnectionPool.getJedisConnection(); 28 | jedis.select(10); 29 | JsonObject status = new JsonObject(); 30 | status.put("status", true); 31 | status.put("time", System.currentTimeMillis()); 32 | jedis.hset(RedisKeyStore.HTTP.getMaster(), serverKey, status.toString()); 33 | jedis.zadd(RedisKeyStore.HTTP + ":STATUS", 0, serverKey); 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | } finally { 37 | if (jedis != null) 38 | JedisConnectionPool.close(jedis); 39 | } 40 | } 41 | 42 | public static void pingDaemonInstance(String deplomentId, boolean isD) { 43 | Jedis jedis = null; 44 | JsonObject status = new JsonObject(); 45 | status.put("status", isD); 46 | status.put("time", System.currentTimeMillis()); 47 | try { 48 | jedis = JedisConnectionPool.getJedisConnection(); 49 | jedis.select(10); 50 | HSET(RedisKeyStore.DAEMON.name(), serverKey + ":" + deplomentId, status.toString(), jedis); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } finally { 54 | if (jedis != null && jedis.isConnected()) 55 | JedisConnectionPool.close(jedis); 56 | } 57 | } 58 | 59 | public static boolean daemonManageFunction(String resStr, Vertx vertx) { 60 | boolean ret_ = true; 61 | if (resStr.indexOf("PING:") > -1) { 62 | if (resStr.indexOf("PING:INSTANCE") > -1) { 63 | boolean isD = false; 64 | String dID = resStr.split(":")[2]; 65 | Iterator it = vertx.deploymentIDs().iterator(); 66 | while (it.hasNext()) { 67 | String dID_ = it.next(); 68 | System.out.println(dID_ + "$$$"); 69 | if (dID.equals(dID_)) { 70 | isD = true; 71 | break; 72 | } 73 | } 74 | if (isD) 75 | RedisHttpClient.pingDaemonInstance(dID, isD); 76 | } else if (resStr.indexOf("PING:MASTER") > -1) { 77 | RedisHttpClient.pingDaemonServer(); 78 | } 79 | ret_ = false; 80 | } else { 81 | 82 | } 83 | return ret_; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/redis/RedisKeyStore.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.redis; 2 | 3 | public enum RedisKeyStore { 4 | 5 | CHANNEL("CHANNEL:MASTER"), 6 | CLIENT("CLIENT:MASTER"), 7 | INSTANCE("CLIENT:INSTANCE:MASTER"), 8 | DAEMON("DAEMON:MASTER"), 9 | PUBLISH("REQUEST:PUBLISH:MASTER"), 10 | REGIST("REQUEST:REGIST"), 11 | VERTX("VERTX:MASTER"), 12 | LOG("LOG:MASTER"), 13 | HTTP("HTTP:MASTER"); 14 | 15 | private String master; 16 | 17 | RedisKeyStore(String master) { 18 | this.master = master; 19 | } 20 | 21 | public String getMaster() { 22 | return this.master; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/redis/RedisSockjsClient.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.redis; 2 | 3 | import java.util.Iterator; 4 | import java.util.List; 5 | 6 | import io.vertx.core.Vertx; 7 | import io.vertx.core.json.JsonObject; 8 | import io.vertx.ext.web.handler.sockjs.BridgeEvent; 9 | import redis.clients.jedis.Jedis; 10 | 11 | public class RedisSockjsClient extends AbstractRedisClient { 12 | 13 | public RedisSockjsClient(String host, int port, String key) throws Exception { 14 | System.out.println("REDIS CONNECTION INIT !!! " + host + ":" + port); 15 | new JedisConnectionPool(host, port); 16 | serverKey = key; 17 | pingDaemonServer(); 18 | } 19 | 20 | public RedisSockjsClient(String[] urls, String key) throws Exception { 21 | new JedisConnectionPool(urls); 22 | serverKey = key; 23 | pingDaemonServer(); 24 | } 25 | 26 | public static void pingDaemonServer() { 27 | Jedis jedis = null; 28 | try { 29 | jedis = JedisConnectionPool.getJedisConnection(); 30 | jedis.select(10); 31 | JsonObject status = new JsonObject(); 32 | status.put("status", true); 33 | status.put("time", System.currentTimeMillis()); 34 | jedis.hset(RedisKeyStore.CLIENT.getMaster(), serverKey, status.toString()); 35 | jedis.zadd(RedisKeyStore.CLIENT + ":STATUS", 0, serverKey); 36 | } catch (Exception e) { 37 | e.printStackTrace(); 38 | } finally { 39 | if (jedis != null) 40 | JedisConnectionPool.close(jedis); 41 | } 42 | } 43 | 44 | public static void pingClientInstance(String deplomentId, boolean isD) { 45 | Jedis jedis = null; 46 | try { 47 | jedis = JedisConnectionPool.getJedisConnection(); 48 | jedis.select(10); 49 | JsonObject status = new JsonObject(); 50 | status.put("status", isD); 51 | status.put("time", System.currentTimeMillis()); 52 | HSET(RedisKeyStore.CLIENT.name(), serverKey + ":" + deplomentId, status.toString(), jedis); 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } finally { 56 | if (jedis != null) 57 | JedisConnectionPool.close(jedis); 58 | } 59 | } 60 | 61 | public static boolean clientManageFunction(String resStr, Vertx vertx) { 62 | boolean ret_ = true; 63 | try { 64 | if (resStr.indexOf("PING:") > -1) { 65 | if (resStr.indexOf("PING:INSTANCE") > -1) { 66 | boolean isD = false; 67 | String dID = resStr.split(":")[2]; 68 | Iterator it = vertx.deploymentIDs().iterator(); 69 | while (it.hasNext()) { 70 | String id_ = it.next(); 71 | System.out.println(id_ + "$$$"); 72 | if (dID.equals(id_)) { 73 | isD = true; 74 | break; 75 | } 76 | } 77 | if (isD) 78 | pingClientInstance(dID, isD); 79 | } else if (resStr.indexOf("PING:MASTER") > -1) { 80 | pingDaemonServer(); 81 | } 82 | ret_ = false; 83 | } else { 84 | 85 | } 86 | } catch (Exception e) { 87 | e.printStackTrace(); 88 | } 89 | return ret_; 90 | } 91 | public static boolean daemonManageFunction(String resStr, Vertx vertx) { 92 | boolean ret_ = true; 93 | if (resStr.indexOf("PING:") > -1) { 94 | if (resStr.indexOf("PING:INSTANCE") > -1) { 95 | boolean isD = false; 96 | String dID = resStr.split(":")[2]; 97 | Iterator it = vertx.deploymentIDs().iterator(); 98 | while (it.hasNext()) { 99 | String dID_ = it.next(); 100 | System.out.println(dID_ + "$$$"); 101 | if (dID.equals(dID_)) { 102 | isD = true; 103 | break; 104 | } 105 | } 106 | if (isD) 107 | RedisSockjsClient.pingClientInstance(dID, isD); 108 | } else if (resStr.indexOf("PING:MASTER") > -1) { 109 | RedisSockjsClient.pingDaemonServer(); 110 | } 111 | ret_ = false; 112 | } else { 113 | 114 | } 115 | return ret_; 116 | } 117 | 118 | 119 | 120 | public static List getClientNotify(int timeout) { 121 | try { 122 | return BRPOP(timeout, RedisKeyStore.CLIENT + ":" + serverKey); 123 | } catch (Exception e) { 124 | e.printStackTrace(); 125 | return null; 126 | } 127 | } 128 | 129 | public static String getClientNotifyD() { 130 | try { 131 | return RPOP(RedisKeyStore.CLIENT + ":" + serverKey); 132 | } catch (Exception e) { 133 | e.printStackTrace(); 134 | return null; 135 | } 136 | } 137 | 138 | public static void PUBLISH(String address, JsonObject msg) { 139 | msg.put("address", address); 140 | Jedis jedis = null; 141 | try { 142 | jedis = JedisConnectionPool.getJedisConnection(); 143 | jedis.lpush(RedisKeyStore.PUBLISH.getMaster(), msg.toString()); 144 | } catch (Exception e) { 145 | e.printStackTrace(); 146 | } finally { 147 | if (jedis != null) 148 | JedisConnectionPool.close(jedis); 149 | } 150 | } 151 | 152 | public static void REGISTER(BridgeEvent event) { 153 | Jedis jedis = null; 154 | try { 155 | JsonObject rawMessage = event.getRawMessage(); 156 | String address = rawMessage.getString("address"); 157 | jedis = JedisConnectionPool.getJedisConnection(10); 158 | jedis.zincrby(RedisKeyStore.REGIST + ":CHANNELS:" + serverKey, -1, address); 159 | jedis.zincrby(RedisKeyStore.REGIST + ":SERVERS:" + address, -1, serverKey); 160 | } catch (Exception e) { 161 | e.printStackTrace(); 162 | } finally { 163 | if (jedis != null) 164 | JedisConnectionPool.close(jedis); 165 | } 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/spring/SpringConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.spring; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | @Configuration 10 | @ComponentScan("io.slime.chat") 11 | public class SpringConfiguration implements ApplicationContextAware{ 12 | private static ApplicationContext context; 13 | 14 | @Override 15 | public void setApplicationContext(ApplicationContext ac) throws BeansException { 16 | context = ac; 17 | } 18 | 19 | public static Object getBean(String beanName){ 20 | return context.getBean(beanName); 21 | } 22 | 23 | public static Object getBean(Class arg){ 24 | return context.getBean(arg); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/spring/service/RequestLogService.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.spring.service; 2 | 3 | import io.vertx.core.http.ServerWebSocket; 4 | import io.vertx.ext.web.handler.sockjs.SockJSSocket; 5 | 6 | public interface RequestLogService { 7 | public void print(String message); 8 | void logWebSocketConnection(ServerWebSocket webSocket); 9 | void logWebSocketConnection(SockJSSocket sockJSSocket); 10 | } 11 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/spring/service/impl/RequestLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.spring.service.impl; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Service; 6 | 7 | import io.slime.chat.common.spring.service.RequestLogService; 8 | import io.slime.chat.common.util.WebSocketSessionHolder; 9 | import io.vertx.core.http.ServerWebSocket; 10 | import io.vertx.ext.web.handler.sockjs.SockJSSocket; 11 | 12 | @Service("requestLogService") 13 | public class RequestLogServiceImpl implements RequestLogService { 14 | private final static Logger logger = LoggerFactory.getLogger(RequestLogServiceImpl.class); 15 | 16 | @Override 17 | public void print(String message) { 18 | logger.info(message); 19 | } 20 | 21 | @Override 22 | public void logWebSocketConnection(ServerWebSocket webSocket) { 23 | logger.info("Connection {} from user {}", webSocket.binaryHandlerID(), 24 | webSocket.headers().get(WebSocketSessionHolder.USER_KEY)); 25 | } 26 | 27 | @Override 28 | public void logWebSocketConnection(SockJSSocket sockJSSocket) { 29 | logger.info("Connection {} from user {}", sockJSSocket.writeHandlerID(), 30 | sockJSSocket.headers().get(WebSocketSessionHolder.USER_KEY)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/util/VertxHolder.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.util; 2 | 3 | import io.vertx.core.Vertx; 4 | 5 | public class VertxHolder { 6 | private static Vertx vertx; 7 | 8 | public static Vertx getVertx() { 9 | return vertx; 10 | } 11 | 12 | public static void setVertx(Vertx vertx) { 13 | VertxHolder.vertx = vertx; 14 | } 15 | 16 | 17 | } -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/java/io/slime/chat/common/util/WebSocketSessionHolder.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.common.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import io.vertx.ext.web.handler.sockjs.SockJSSocket; 9 | 10 | public abstract class WebSocketSessionHolder { 11 | public static final String USER_KEY = "userId"; 12 | 13 | private static final Map sessions = new HashMap<>(); 14 | 15 | public static void add(String userId, SockJSSocket session) { 16 | sessions.put(userId, session); 17 | } 18 | 19 | public static SockJSSocket remove(String userId) { 20 | return sessions.remove(userId); 21 | } 22 | 23 | public static Map getMap() { 24 | return sessions; 25 | } 26 | 27 | 28 | public static List getUsers() { 29 | return new ArrayList(sessions.keySet()); 30 | } 31 | 32 | public static SockJSSocket get(String userId) { 33 | return sessions.get(userId); 34 | } 35 | 36 | public static boolean exists(String userId) { 37 | return get(userId) != null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/src/main/resources/cluster.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | false 7 | false 8 | 0 9 | jdk 10 | 11 | 2 12 | 13 | 5 14 | 10 15 | 10 16 | 10 17 | 10 18 | 2 19 | 10 20 | 3 21 | 22 | 23 | 5701 24 | 25 | 0 26 | 27 | 28 | 29 | 30 | 31 | 127.0.0.1 32 | 33 | 34 | 35 | 36 | 37 | 10.10.1.* 38 | 39 | 40 | 41 | 42 | 50 | PBEWithMD5AndDES 51 | 52 | thesalt 53 | 54 | thepass 55 | 56 | 19 57 | 58 | 59 | 60 | 61 | 16 62 | 63 | 0 64 | 65 | 66 | 67 | 72 | 1 73 | 79 | 0 80 | 86 | 0 87 | 94 | NONE 95 | 101 | 0 102 | 108 | 25 109 | 124 | com.hazelcast.map.merge.LatestUpdateMapMergePolicy 125 | 126 | 127 | 128 | 129 | 130 | 1 131 | 132 | 133 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/target/classes/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Maven-Artifact-Id: slime-common 3 | Built-By: pgmnle 4 | Maven-Version: 0.0.1-SNAPSHOT 5 | Build-Jdk: 1.8.0_25 6 | Created-By: Maven Integration for Eclipse 7 | Maven-Group-Id: io.slime.workshop 8 | 9 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/target/classes/META-INF/maven/io.slime.workshop/slime-common/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Sun Feb 26 15:08:15 KST 2017 3 | version=0.0.1-SNAPSHOT 4 | groupId=io.slime.workshop 5 | m2e.projectName=slime-common 6 | m2e.projectLocation=/Users/pgmnle/git/slime/slime-microservice-chat/slime-common 7 | artifactId=slime-common 8 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-common/target/classes/META-INF/maven/io.slime.workshop/slime-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | io.slime.workshop 5 | slime-microservice-chat 6 | 0.0.1-SNAPSHOT 7 | 8 | slime-common 9 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | slime-http 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/test/java=UTF-8 5 | encoding//src/test/resources=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.8 6 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | io.slime.workshop 5 | slime-microservice-chat 6 | 0.0.1-SNAPSHOT 7 | 8 | 9 | slime-http 10 | 11 | 12 | io.slime.chat.http.HttpServer 13 | 14 | 15 | 16 | 17 | io.slime.workshop 18 | slime-common 19 | ${project.version} 20 | 21 | 22 | 23 | 24 | 25 | 26 | maven-shade-plugin 27 | 28 | 29 | maven-dependency-plugin 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/conf/config_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "http", 3 | "port" : 8080 4 | } -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/java/io/slime/chat/http/HttpServer.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.http; 2 | 3 | import java.io.FileNotFoundException; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.stereotype.Service; 8 | 9 | import io.slime.chat.common.spring.SpringConfiguration; 10 | import io.slime.chat.common.spring.service.RequestLogService; 11 | import io.vertx.core.AbstractVerticle; 12 | import io.vertx.core.AsyncResult; 13 | import io.vertx.core.Handler; 14 | import io.vertx.core.http.HttpServerRequest; 15 | 16 | public class HttpServer extends AbstractVerticle { 17 | private static final Logger logger = LoggerFactory.getLogger(HttpServer.class); 18 | private int serverPort = 8080; 19 | 20 | private RequestLogService requestLogService = (RequestLogService) SpringConfiguration.getBean("requestLogService"); 21 | 22 | @Override 23 | public void start() throws Exception { 24 | 25 | logger.info("HTTP Server started on port: {}", serverPort); 26 | 27 | vertx.createHttpServer().requestHandler(new Handler() { 28 | 29 | public void handle(HttpServerRequest req) { 30 | 31 | requestLogService.print(String.format("Request on path: %s", req.path())); 32 | 33 | String file = req.path().equals("/") ? "/chat/index.html" : req.path(); 34 | 35 | //send file and handle file not found 36 | req.response().sendFile("webroot" + file, new Handler>() { 37 | @Override 38 | public void handle(AsyncResult event) { 39 | if(event.cause() instanceof FileNotFoundException) { 40 | 41 | logger.error("Resource not found: {}", "webroot" + file); 42 | 43 | req.response().sendFile("webroot/error/404.html"); 44 | } 45 | } 46 | }); 47 | 48 | 49 | } 50 | 51 | }).listen(serverPort); 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unlogicaldev/slime/3fb52f60e08b4c97f9ff5dec2107f9f19bbb4ad8/slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/img/favicon.png -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/img/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unlogicaldev/slime/3fb52f60e08b4c97f9ff5dec2107f9f19bbb4ad8/slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/img/user.png -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/img/user_offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unlogicaldev/slime/3fb52f60e08b4c97f9ff5dec2107f9f19bbb4ad8/slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/img/user_offline.png -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/js/chat.js: -------------------------------------------------------------------------------- 1 | var ChannelType = { 2 | NEW_USER: "/user", 3 | NEW_MESSAGE: "/message", 4 | OFFLINE: "/offline" 5 | }; 6 | var serverIp = "localhost"; 7 | 8 | var page = { 9 | 10 | sockJSClient: null, 11 | 12 | $msgList: $("#lstMsg"), 13 | $msgModel: $("#msgModel").detach().removeAttr("id"), 14 | 15 | $userList: $("#lstUsers"), 16 | $userModel: $("#userModel").detach().removeAttr("id"), 17 | 18 | init: function() { 19 | page.initView(); 20 | page.bindEvent(); 21 | }, 22 | 23 | initView: function() { 24 | 25 | }, 26 | 27 | connect: function(userId, successCallback) { 28 | var url = sprintf("http://%s:8383/sockjs", serverIp, userId) 29 | page.sockJSClient = new vertx.EventBus(url); 30 | 31 | page.sockJSClient.onopen = function () { 32 | page.sockJSClient.login(userId, "password", function(response) { 33 | successCallback(response); 34 | }); 35 | }; 36 | }, 37 | 38 | bindEvent: function() { 39 | 40 | $("#txtName").keyup(function(e){ 41 | if(e.keyCode == 13) 42 | { 43 | $("#btnJoin").click(); 44 | } 45 | }); 46 | $("#btnJoin").on("click", function() { 47 | var userId = $("#txtName").val(); 48 | 49 | page.connect(userId, function(response){ 50 | 51 | $(".loginDiv").hide(); 52 | $(".container").show(); 53 | 54 | var users = response.list; 55 | $.each(users, function(index, user){ 56 | page.renderUser({userId: user}); 57 | }); 58 | 59 | // emphasize current user 60 | page.$userList.find("#" + userId).find("h5").css("font-weight", "bold").css("font-style", "italic") 61 | 62 | 63 | // handle event of server close current connection 64 | page.sockJSClient.onclose = function(){ 65 | $(".loginDiv").show(); 66 | $(".container").hide(); 67 | }; 68 | 69 | 70 | var channel = "topic/chat".concat(ChannelType.NEW_MESSAGE); 71 | page.sockJSClient.registerHandler(channel, function(msg){ 72 | page.renderMessage(msg) 73 | }); 74 | 75 | 76 | var channel = "topic/chat".concat(ChannelType.NEW_USER); 77 | page.sockJSClient.registerHandler(channel, function(user){ 78 | page.renderUser(user); 79 | }); 80 | 81 | var channel = "topic/chat".concat(ChannelType.OFFLINE); 82 | page.sockJSClient.registerHandler(channel, function(user){ 83 | page.removeUser(user); 84 | }); 85 | 86 | }) 87 | }); 88 | 89 | 90 | 91 | $("#txtMessage").keyup(function(e){ 92 | if(e.keyCode == 13) 93 | { 94 | $("#btnSend").click(); 95 | } 96 | }); 97 | 98 | $("#btnSend").on("click", function(){ 99 | var $txtMessage = $("#txtMessage"); 100 | var msg = $txtMessage.val(); 101 | $txtMessage.val(""); 102 | 103 | var address = "topic/chat".concat(ChannelType.NEW_MESSAGE); 104 | page.sockJSClient.publish(address, msg, function(response) {}); 105 | }); 106 | }, 107 | 108 | renderMessage: function(msg) { 109 | var $msgModel = page.$msgModel.clone(); 110 | $msgModel.find(".lblMsg").text(msg.message); 111 | $msgModel.find(".lblUser").text(msg.sender); 112 | page.$msgList.append($msgModel); 113 | }, 114 | 115 | renderUser: function(user) { 116 | var $userModel = page.$userModel.clone(); 117 | $userModel.prop("id", user.userId); 118 | $userModel.find(".lblUser").text(user.userId); 119 | page.$userList.append($userModel); 120 | }, 121 | 122 | removeUser: function(user) { 123 | page.$userList.find("#" + user.userId).remove(); 124 | } 125 | }; 126 | 127 | $(document).ready(function(){ 128 | page.init(); 129 | 130 | window.onbeforeunload = function (event) { 131 | 132 | // demonstrate before closing browser, 133 | // no need to call this, disconnect is called when tab/browser is close 134 | if(page.sockJSClient != null) { 135 | page.sockJSClient.close(); 136 | } 137 | }; 138 | 139 | }) -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/js/sprintf.min.js: -------------------------------------------------------------------------------- 1 | /*! sprintf-js v1.0.3 | Copyright (c) 2007-present, Alexandru Marasteanu | BSD-3-Clause */ 2 | !function(e){"use strict";function t(){var e=arguments[0],r=t.cache;return r[e]&&r.hasOwnProperty(e)||(r[e]=t.parse(e)),t.format.call(null,r[e],arguments)}function r(e){return"number"==typeof e?"number":"string"==typeof e?"string":Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}function n(e,t){return t>=0&&7>=t&&i[e]?i[e][t]:Array(t+1).join(e)}var s={not_string:/[^s]/,not_bool:/[^t]/,not_type:/[^T]/,not_primitive:/[^v]/,number:/[diefg]/,numeric_arg:/bcdiefguxX/,json:/[j]/,not_json:/[^j]/,text:/^[^\x25]+/,modulo:/^\x25{2}/,placeholder:/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/,key:/^([a-z_][a-z_\d]*)/i,key_access:/^\.([a-z_][a-z_\d]*)/i,index_access:/^\[(\d+)\]/,sign:/^[\+\-]/};t.format=function(e,a){var i,o,l,c,p,f,u,g=1,_=e.length,d="",b=[],h=!0,x="";for(o=0;_>o;o++)if(d=r(e[o]),"string"===d)b[b.length]=e[o];else if("array"===d){if(c=e[o],c[2])for(i=a[g],l=0;l=0),c[8]){case"b":i=parseInt(i,10).toString(2);break;case"c":i=String.fromCharCode(parseInt(i,10));break;case"d":case"i":i=parseInt(i,10);break;case"j":i=JSON.stringify(i,null,c[6]?parseInt(c[6]):0);break;case"e":i=c[7]?parseFloat(i).toExponential(c[7]):parseFloat(i).toExponential();break;case"f":i=c[7]?parseFloat(i).toFixed(c[7]):parseFloat(i);break;case"g":i=c[7]?parseFloat(i).toPrecision(c[7]):parseFloat(i);break;case"o":i=i.toString(8);break;case"s":i=String(i),i=c[7]?i.substring(0,c[7]):i;break;case"t":i=String(!!i),i=c[7]?i.substring(0,c[7]):i;break;case"T":i=r(i),i=c[7]?i.substring(0,c[7]):i;break;case"u":i=parseInt(i,10)>>>0;break;case"v":i=i.valueOf(),i=c[7]?i.substring(0,c[7]):i;break;case"x":i=parseInt(i,10).toString(16);break;case"X":i=parseInt(i,10).toString(16).toUpperCase()}s.json.test(c[8])?b[b.length]=i:(!s.number.test(c[8])||h&&!c[3]?x="":(x=h?"+":"-",i=i.toString().replace(s.sign,"")),f=c[4]?"0"===c[4]?"0":c[4].charAt(1):" ",u=c[6]-(x+i).length,p=c[6]&&u>0?n(f,u):"",b[b.length]=c[5]?x+i+p:"0"===f?x+p+i:p+x+i)}return b.join("")},t.cache={},t.parse=function(e){for(var t=e,r=[],n=[],a=0;t;){if(null!==(r=s.text.exec(t)))n[n.length]=r[0];else if(null!==(r=s.modulo.exec(t)))n[n.length]="%";else{if(null===(r=s.placeholder.exec(t)))throw new SyntaxError("[sprintf] unexpected placeholder");if(r[2]){a|=1;var i=[],o=r[2],l=[];if(null===(l=s.key.exec(o)))throw new SyntaxError("[sprintf] failed to parse named argument key");for(i[i.length]=l[1];""!==(o=o.substring(l[0].length));)if(null!==(l=s.key_access.exec(o)))i[i.length]=l[1];else{if(null===(l=s.index_access.exec(o)))throw new SyntaxError("[sprintf] failed to parse named argument key");i[i.length]=l[1]}r[2]=i}else a|=2;if(3===a)throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported");n[n.length]=r}t=t.substring(r[0].length)}return n};var a=function(e,r,n){return n=(r||[]).slice(0),n.splice(0,0,e),t.apply(null,n)},i={0:["","0","00","000","0000","00000","000000","0000000"]," ":[""," "," "," "," "," "," "," "],_:["","_","__","___","____","_____","______","_______"]};"undefined"!=typeof exports?(exports.sprintf=t,exports.vsprintf=a):(e.sprintf=t,e.vsprintf=a,"function"==typeof define&&define.amd&&define(function(){return{sprintf:t,vsprintf:a}}))}("undefined"==typeof window?this:window); 3 | //# sourceMappingURL=sprintf.min.js.map -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/js/sprintf.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["sprintf.min.js","sprintf.js"],"names":["window","sprintf","key","arguments","cache","hasOwnProperty","parse","format","call","get_type","variable","Object","prototype","toString","slice","toLowerCase","str_repeat","input","multiplier","preformattedPadding","Array","join","re","not_string","not_bool","not_type","not_primitive","number","numeric_arg","json","not_json","text","modulo","placeholder","key_access","index_access","sign","parse_tree","argv","arg","i","k","match","pad","pad_character","pad_length","cursor","tree_length","length","node_type","output","is_positive","Error","test","isNaN","TypeError","parseInt","String","fromCharCode","JSON","stringify","parseFloat","toExponential","toFixed","toPrecision","substring","valueOf","toUpperCase","replace","charAt","fmt","_fmt","arg_names","exec","SyntaxError","field_list","replacement_field","field_match","vsprintf","_argv","splice","apply","0"," ","_","exports","define","amd","this"],"mappings":"AAAA;AACA,CCCA,SAAUA,GACN,YAoBA,SAASC,KACL,GAAIC,GAAMC,UAAU,GAAIC,EAAQH,EAAQG,KAIxC,OAHMA,GAAMF,IAAQE,EAAMC,eAAeH,KACrCE,EAAMF,GAAOD,EAAQK,MAAMJ,IAExBD,EAAQM,OAAOC,KAAK,KAAMJ,EAAMF,GAAMC,WA4KjD,QAASM,GAASC,GACd,MAAwB,gBAAbA,GACA,SAEkB,gBAAbA,GACL,SAGAC,OAAOC,UAAUC,SAASL,KAAKE,GAAUI,MAAM,EAAG,IAAIC,cASrE,QAASC,GAAWC,EAAOC,GACvB,MAAIA,IAAc,GAAmB,GAAdA,GAAmBC,EAAoBF,GACnDE,EAAoBF,GAAOC,GAE/BE,MAAMF,EAAa,GAAGG,KAAKJ,GAxNtC,GAAIK,IACAC,WAAY,OACZC,SAAU,OACVC,SAAU,OACVC,cAAe,OACfC,OAAQ,UACRC,YAAa,aACbC,KAAM,MACNC,SAAU,OACVC,KAAM,YACNC,OAAQ,WACRC,YAAa,4FACb/B,IAAK,sBACLgC,WAAY,wBACZC,aAAc,aACdC,KAAM,UAWVnC,GAAQM,OAAS,SAAS8B,EAAYC,GAClC,GAAiEC,GAAkBC,EAAGC,EAAGC,EAAOC,EAAKC,EAAeC,EAAhHC,EAAS,EAAGC,EAAcV,EAAWW,OAAQC,EAAY,GAASC,KAA0DC,GAAc,EAAMf,EAAO,EAC3J,KAAKI,EAAI,EAAOO,EAAJP,EAAiBA,IAEzB,GADAS,EAAYxC,EAAS4B,EAAWG,IACd,WAAdS,EACAC,EAAOA,EAAOF,QAAUX,EAAWG,OAElC,IAAkB,UAAdS,EAAuB,CAE5B,GADAP,EAAQL,EAAWG,GACfE,EAAM,GAEN,IADAH,EAAMD,EAAKQ,GACNL,EAAI,EAAGA,EAAIC,EAAM,GAAGM,OAAQP,IAAK,CAClC,IAAKF,EAAIlC,eAAeqC,EAAM,GAAGD,IAC7B,KAAM,IAAIW,OAAMnD,EAAQ,yCAA0CyC,EAAM,GAAGD,IAE/EF,GAAMA,EAAIG,EAAM,GAAGD,QAIvBF,GADKG,EAAM,GACLJ,EAAKI,EAAM,IAGXJ,EAAKQ,IAOf,IAJIxB,EAAGG,SAAS4B,KAAKX,EAAM,KAAOpB,EAAGI,cAAc2B,KAAKX,EAAM,KAAwB,YAAjBjC,EAAS8B,KAC1EA,EAAMA,KAGNjB,EAAGM,YAAYyB,KAAKX,EAAM,KAAyB,UAAjBjC,EAAS8B,IAAoBe,MAAMf,GACrE,KAAM,IAAIgB,WAAUtD,EAAQ,0CAA2CQ,EAAS8B,IAOpF,QAJIjB,EAAGK,OAAO0B,KAAKX,EAAM,MACrBS,EAAcZ,GAAO,GAGjBG,EAAM,IACV,IAAK,IACDH,EAAMiB,SAASjB,EAAK,IAAI1B,SAAS,EACrC,MACA,KAAK,IACD0B,EAAMkB,OAAOC,aAAaF,SAASjB,EAAK,IAC5C,MACA,KAAK,IACL,IAAK,IACDA,EAAMiB,SAASjB,EAAK,GACxB,MACA,KAAK,IACDA,EAAMoB,KAAKC,UAAUrB,EAAK,KAAMG,EAAM,GAAKc,SAASd,EAAM,IAAM,EACpE,MACA,KAAK,IACDH,EAAMG,EAAM,GAAKmB,WAAWtB,GAAKuB,cAAcpB,EAAM,IAAMmB,WAAWtB,GAAKuB,eAC/E,MACA,KAAK,IACDvB,EAAMG,EAAM,GAAKmB,WAAWtB,GAAKwB,QAAQrB,EAAM,IAAMmB,WAAWtB,EACpE,MACA,KAAK,IACDA,EAAMG,EAAM,GAAKmB,WAAWtB,GAAKyB,YAAYtB,EAAM,IAAMmB,WAAWtB,EACxE,MACA,KAAK,IACDA,EAAMA,EAAI1B,SAAS,EACvB,MACA,KAAK,IACD0B,EAAMkB,OAAOlB,GACbA,EAAOG,EAAM,GAAKH,EAAI0B,UAAU,EAAGvB,EAAM,IAAMH,CACnD,MACA,KAAK,IACDA,EAAMkB,SAASlB,GACfA,EAAOG,EAAM,GAAKH,EAAI0B,UAAU,EAAGvB,EAAM,IAAMH,CACnD,MACA,KAAK,IACDA,EAAM9B,EAAS8B,GACfA,EAAOG,EAAM,GAAKH,EAAI0B,UAAU,EAAGvB,EAAM,IAAMH,CACnD,MACA,KAAK,IACDA,EAAMiB,SAASjB,EAAK,MAAQ,CAChC,MACA,KAAK,IACDA,EAAMA,EAAI2B,UACV3B,EAAOG,EAAM,GAAKH,EAAI0B,UAAU,EAAGvB,EAAM,IAAMH,CACnD,MACA,KAAK,IACDA,EAAMiB,SAASjB,EAAK,IAAI1B,SAAS,GACrC,MACA,KAAK,IACD0B,EAAMiB,SAASjB,EAAK,IAAI1B,SAAS,IAAIsD,cAGzC7C,EAAGO,KAAKwB,KAAKX,EAAM,IACnBQ,EAAOA,EAAOF,QAAUT,IAGpBjB,EAAGK,OAAO0B,KAAKX,EAAM,KAASS,IAAeT,EAAM,GAKnDN,EAAO,IAJPA,EAAOe,EAAc,IAAM,IAC3BZ,EAAMA,EAAI1B,WAAWuD,QAAQ9C,EAAGc,KAAM,KAK1CQ,EAAgBF,EAAM,GAAkB,MAAbA,EAAM,GAAa,IAAMA,EAAM,GAAG2B,OAAO,GAAK,IACzExB,EAAaH,EAAM,IAAMN,EAAOG,GAAKS,OACrCL,EAAMD,EAAM,IAAMG,EAAa,EAAI7B,EAAW4B,EAAeC,GAAoB,GACjFK,EAAOA,EAAOF,QAAUN,EAAM,GAAKN,EAAOG,EAAMI,EAAyB,MAAlBC,EAAwBR,EAAOO,EAAMJ,EAAMI,EAAMP,EAAOG,GAI3H,MAAOW,GAAO7B,KAAK,KAGvBpB,EAAQG,SAERH,EAAQK,MAAQ,SAASgE,GAErB,IADA,GAAIC,GAAOD,EAAK5B,KAAYL,KAAiBmC,EAAY,EAClDD,GAAM,CACT,GAAqC,QAAhC7B,EAAQpB,EAAGS,KAAK0C,KAAKF,IACtBlC,EAAWA,EAAWW,QAAUN,EAAM,OAErC,IAAuC,QAAlCA,EAAQpB,EAAGU,OAAOyC,KAAKF,IAC7BlC,EAAWA,EAAWW,QAAU,QAE/B,CAAA,GAA4C,QAAvCN,EAAQpB,EAAGW,YAAYwC,KAAKF,IAgClC,KAAM,IAAIG,aAAY,mCA/BtB,IAAIhC,EAAM,GAAI,CACV8B,GAAa,CACb,IAAIG,MAAiBC,EAAoBlC,EAAM,GAAImC,IACnD,IAAuD,QAAlDA,EAAcvD,EAAGpB,IAAIuE,KAAKG,IAe3B,KAAM,IAAIF,aAAY,+CAbtB,KADAC,EAAWA,EAAW3B,QAAU6B,EAAY,GACwC,MAA5ED,EAAoBA,EAAkBX,UAAUY,EAAY,GAAG7B,UACnE,GAA8D,QAAzD6B,EAAcvD,EAAGY,WAAWuC,KAAKG,IAClCD,EAAWA,EAAW3B,QAAU6B,EAAY,OAE3C,CAAA,GAAgE,QAA3DA,EAAcvD,EAAGa,aAAasC,KAAKG,IAIzC,KAAM,IAAIF,aAAY,+CAHtBC,GAAWA,EAAW3B,QAAU6B,EAAY,GAUxDnC,EAAM,GAAKiC,MAGXH,IAAa,CAEjB,IAAkB,IAAdA,EACA,KAAM,IAAIpB,OAAM,4EAEpBf,GAAWA,EAAWW,QAAUN,EAKpC6B,EAAOA,EAAKN,UAAUvB,EAAM,GAAGM,QAEnC,MAAOX,GAGX,IAAIyC,GAAW,SAASR,EAAKhC,EAAMyC,GAG/B,MAFAA,IAASzC,OAAYxB,MAAM,GAC3BiE,EAAMC,OAAO,EAAG,EAAGV,GACZrE,EAAQgF,MAAM,KAAMF,IAkB3B5D,GACA+D,GAAM,GAAI,IAAK,KAAM,MAAO,OAAQ,QAAS,SAAU,WACvDC,KAAM,GAAI,IAAK,KAAM,MAAO,OAAQ,QAAS,SAAU,WACvDC,GAAM,GAAI,IAAK,KAAM,MAAO,OAAQ,QAAS,SAAU,WAYpC,oBAAZC,UACPA,QAAQpF,QAAUA,EAClBoF,QAAQP,SAAWA,IAGnB9E,EAAOC,QAAUA,EACjBD,EAAO8E,SAAWA,EAEI,kBAAXQ,SAAyBA,OAAOC,KACvCD,OAAO,WACH,OACIrF,QAASA,EACT6E,SAAUA,OAKT,mBAAX9E,QAAyBwF,KAAOxF","file":"sprintf.min.js","sourcesContent":[null,"/* globals window, exports, define */\n\n(function(window) {\n 'use strict'\n\n var re = {\n not_string: /[^s]/,\n not_bool: /[^t]/,\n not_type: /[^T]/,\n not_primitive: /[^v]/,\n number: /[diefg]/,\n numeric_arg: /bcdiefguxX/,\n json: /[j]/,\n not_json: /[^j]/,\n text: /^[^\\x25]+/,\n modulo: /^\\x25{2}/,\n placeholder: /^\\x25(?:([1-9]\\d*)\\$|\\(([^\\)]+)\\))?(\\+)?(0|'[^$])?(-)?(\\d+)?(?:\\.(\\d+))?([b-gijostTuvxX])/,\n key: /^([a-z_][a-z_\\d]*)/i,\n key_access: /^\\.([a-z_][a-z_\\d]*)/i,\n index_access: /^\\[(\\d+)\\]/,\n sign: /^[\\+\\-]/\n }\n\n function sprintf() {\n var key = arguments[0], cache = sprintf.cache\n if (!(cache[key] && cache.hasOwnProperty(key))) {\n cache[key] = sprintf.parse(key)\n }\n return sprintf.format.call(null, cache[key], arguments)\n }\n\n sprintf.format = function(parse_tree, argv) {\n var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = ''\n for (i = 0; i < tree_length; i++) {\n node_type = get_type(parse_tree[i])\n if (node_type === 'string') {\n output[output.length] = parse_tree[i]\n }\n else if (node_type === 'array') {\n match = parse_tree[i] // convenience purposes only\n if (match[2]) { // keyword argument\n arg = argv[cursor]\n for (k = 0; k < match[2].length; k++) {\n if (!arg.hasOwnProperty(match[2][k])) {\n throw new Error(sprintf('[sprintf] property \"%s\" does not exist', match[2][k]))\n }\n arg = arg[match[2][k]]\n }\n }\n else if (match[1]) { // positional argument (explicit)\n arg = argv[match[1]]\n }\n else { // positional argument (implicit)\n arg = argv[cursor++]\n }\n\n if (re.not_type.test(match[8]) && re.not_primitive.test(match[8]) && get_type(arg) == 'function') {\n arg = arg()\n }\n\n if (re.numeric_arg.test(match[8]) && (get_type(arg) != 'number' && isNaN(arg))) {\n throw new TypeError(sprintf(\"[sprintf] expecting number but found %s\", get_type(arg)))\n }\n\n if (re.number.test(match[8])) {\n is_positive = arg >= 0\n }\n\n switch (match[8]) {\n case 'b':\n arg = parseInt(arg, 10).toString(2)\n break\n case 'c':\n arg = String.fromCharCode(parseInt(arg, 10))\n break\n case 'd':\n case 'i':\n arg = parseInt(arg, 10)\n break\n case 'j':\n arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0)\n break\n case 'e':\n arg = match[7] ? parseFloat(arg).toExponential(match[7]) : parseFloat(arg).toExponential()\n break\n case 'f':\n arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg)\n break\n case 'g':\n arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg)\n break\n case 'o':\n arg = arg.toString(8)\n break\n case 's':\n arg = String(arg)\n arg = (match[7] ? arg.substring(0, match[7]) : arg)\n break\n case 't':\n arg = String(!!arg)\n arg = (match[7] ? arg.substring(0, match[7]) : arg)\n break\n case 'T':\n arg = get_type(arg)\n arg = (match[7] ? arg.substring(0, match[7]) : arg)\n break\n case 'u':\n arg = parseInt(arg, 10) >>> 0\n break\n case 'v':\n arg = arg.valueOf()\n arg = (match[7] ? arg.substring(0, match[7]) : arg)\n break\n case 'x':\n arg = parseInt(arg, 10).toString(16)\n break\n case 'X':\n arg = parseInt(arg, 10).toString(16).toUpperCase()\n break\n }\n if (re.json.test(match[8])) {\n output[output.length] = arg\n }\n else {\n if (re.number.test(match[8]) && (!is_positive || match[3])) {\n sign = is_positive ? '+' : '-'\n arg = arg.toString().replace(re.sign, '')\n }\n else {\n sign = ''\n }\n pad_character = match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' '\n pad_length = match[6] - (sign + arg).length\n pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : '') : ''\n output[output.length] = match[5] ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg)\n }\n }\n }\n return output.join('')\n }\n\n sprintf.cache = {}\n\n sprintf.parse = function(fmt) {\n var _fmt = fmt, match = [], parse_tree = [], arg_names = 0\n while (_fmt) {\n if ((match = re.text.exec(_fmt)) !== null) {\n parse_tree[parse_tree.length] = match[0]\n }\n else if ((match = re.modulo.exec(_fmt)) !== null) {\n parse_tree[parse_tree.length] = '%'\n }\n else if ((match = re.placeholder.exec(_fmt)) !== null) {\n if (match[2]) {\n arg_names |= 1\n var field_list = [], replacement_field = match[2], field_match = []\n if ((field_match = re.key.exec(replacement_field)) !== null) {\n field_list[field_list.length] = field_match[1]\n while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {\n if ((field_match = re.key_access.exec(replacement_field)) !== null) {\n field_list[field_list.length] = field_match[1]\n }\n else if ((field_match = re.index_access.exec(replacement_field)) !== null) {\n field_list[field_list.length] = field_match[1]\n }\n else {\n throw new SyntaxError(\"[sprintf] failed to parse named argument key\")\n }\n }\n }\n else {\n throw new SyntaxError(\"[sprintf] failed to parse named argument key\")\n }\n match[2] = field_list\n }\n else {\n arg_names |= 2\n }\n if (arg_names === 3) {\n throw new Error(\"[sprintf] mixing positional and named placeholders is not (yet) supported\")\n }\n parse_tree[parse_tree.length] = match\n }\n else {\n throw new SyntaxError(\"[sprintf] unexpected placeholder\")\n }\n _fmt = _fmt.substring(match[0].length)\n }\n return parse_tree\n }\n\n var vsprintf = function(fmt, argv, _argv) {\n _argv = (argv || []).slice(0)\n _argv.splice(0, 0, fmt)\n return sprintf.apply(null, _argv)\n }\n\n /**\n * helpers\n */\n function get_type(variable) {\n if (typeof variable === 'number') {\n return 'number'\n }\n else if (typeof variable === 'string') {\n return 'string'\n }\n else {\n return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase()\n }\n }\n\n var preformattedPadding = {\n '0': ['', '0', '00', '000', '0000', '00000', '000000', '0000000'],\n ' ': ['', ' ', ' ', ' ', ' ', ' ', ' ', ' '],\n '_': ['', '_', '__', '___', '____', '_____', '______', '_______'],\n }\n function str_repeat(input, multiplier) {\n if (multiplier >= 0 && multiplier <= 7 && preformattedPadding[input]) {\n return preformattedPadding[input][multiplier]\n }\n return Array(multiplier + 1).join(input)\n }\n\n /**\n * export to either browser or node.js\n */\n if (typeof exports !== 'undefined') {\n exports.sprintf = sprintf\n exports.vsprintf = vsprintf\n }\n else {\n window.sprintf = sprintf\n window.vsprintf = vsprintf\n\n if (typeof define === 'function' && define.amd) {\n define(function() {\n return {\n sprintf: sprintf,\n vsprintf: vsprintf\n }\n })\n }\n }\n})(typeof window === 'undefined' ? this : window);\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/resources/webroot/chat/assets/js/vertxbus.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | var vertx = vertx || {}; 18 | 19 | !function(factory) { 20 | if (typeof define === "function" && define.amd) { 21 | // Expose as an AMD module with SockJS dependency. 22 | // "vertxbus" and "sockjs" names are used because 23 | // AMD module names are derived from file names. 24 | define("vertxbus", ["sockjs"], factory); 25 | } else { 26 | // No AMD-compliant loader 27 | factory(SockJS); 28 | } 29 | }(function(SockJS) { 30 | 31 | vertx.EventBus = function(url, options) { 32 | 33 | var that = this; 34 | var sockJSConn = new SockJS(url, undefined, options); 35 | var handlerMap = {}; 36 | var replyHandlers = {}; 37 | var state = vertx.EventBus.CONNECTING; 38 | var sessionID = null; 39 | var pingTimerID = null; 40 | 41 | that.onopen = null; 42 | that.onclose = null; 43 | 44 | that.login = function(username, password, replyHandler) { 45 | sendOrPub("send", 'vertx.basicauthmanager.login', {username: username, password: password}, function(reply) { 46 | if (reply.status === 'ok') { 47 | that.sessionID = reply.sessionID; 48 | } 49 | if (replyHandler) { 50 | delete reply.sessionID; 51 | replyHandler(reply) 52 | } 53 | }); 54 | } 55 | 56 | that.send = function(address, message, replyHandler) { 57 | sendOrPub("send", address, message, replyHandler) 58 | } 59 | 60 | that.publish = function(address, message, replyHandler) { 61 | sendOrPub("publish", address, message, replyHandler) 62 | } 63 | 64 | that.registerHandler = function(address, handler) { 65 | checkSpecified("address", 'string', address); 66 | checkSpecified("handler", 'function', handler); 67 | checkOpen(); 68 | var handlers = handlerMap[address]; 69 | if (!handlers) { 70 | handlers = [handler]; 71 | handlerMap[address] = handlers; 72 | // First handler for this address so we should register the connection 73 | var msg = { type : "register", 74 | address: address }; 75 | sockJSConn.send(JSON.stringify(msg)); 76 | } else { 77 | handlers[handlers.length] = handler; 78 | } 79 | } 80 | 81 | that.unregisterHandler = function(address, handler) { 82 | checkSpecified("address", 'string', address); 83 | checkSpecified("handler", 'function', handler); 84 | checkOpen(); 85 | var handlers = handlerMap[address]; 86 | if (handlers) { 87 | var idx = handlers.indexOf(handler); 88 | if (idx != -1) handlers.splice(idx, 1); 89 | if (handlers.length == 0) { 90 | // No more local handlers so we should unregister the connection 91 | 92 | var msg = { type : "unregister", 93 | address: address}; 94 | sockJSConn.send(JSON.stringify(msg)); 95 | delete handlerMap[address]; 96 | } 97 | } 98 | } 99 | 100 | that.close = function() { 101 | checkOpen(); 102 | if (pingTimerID) clearInterval(pingTimerID); 103 | state = vertx.EventBus.CLOSING; 104 | sockJSConn.close(); 105 | } 106 | 107 | that.readyState = function() { 108 | return state; 109 | } 110 | 111 | sockJSConn.onopen = function() { 112 | // Send the first ping then send a ping every 5 seconds 113 | sendPing(); 114 | pingTimerID = setInterval(sendPing, 5000); 115 | state = vertx.EventBus.OPEN; 116 | if (that.onopen) { 117 | that.onopen(); 118 | } 119 | }; 120 | 121 | sockJSConn.onclose = function() { 122 | state = vertx.EventBus.CLOSED; 123 | if (that.onclose) { 124 | that.onclose(); 125 | } 126 | }; 127 | 128 | sockJSConn.onmessage = function(e) { 129 | var msg = e.data; 130 | var json = JSON.parse(msg); 131 | var body = json.body; 132 | var replyAddress = json.replyAddress; 133 | var address = json.address; 134 | var replyHandler; 135 | if (replyAddress) { 136 | replyHandler = function(reply, replyHandler) { 137 | // Send back reply 138 | that.send(replyAddress, reply, replyHandler); 139 | }; 140 | } 141 | var handlers = handlerMap[address]; 142 | if (handlers) { 143 | // We make a copy since the handler might get unregistered from within the 144 | // handler itself, which would screw up our iteration 145 | var copy = handlers.slice(0); 146 | for (var i = 0; i < copy.length; i++) { 147 | copy[i](body, replyHandler); 148 | } 149 | } else { 150 | // Might be a reply message 151 | var handler = replyHandlers[address]; 152 | if (handler) { 153 | delete replyHandlers[address]; 154 | handler(body, replyHandler); 155 | } 156 | } 157 | } 158 | 159 | function sendPing() { 160 | var msg = { 161 | type: "ping" 162 | } 163 | sockJSConn.send(JSON.stringify(msg)); 164 | } 165 | 166 | function sendOrPub(sendOrPub, address, message, replyHandler) { 167 | checkSpecified("address", 'string', address); 168 | checkSpecified("replyHandler", 'function', replyHandler, true); 169 | checkOpen(); 170 | var envelope = { type : sendOrPub, 171 | address: address, 172 | body: message }; 173 | if (that.sessionID) { 174 | envelope.sessionID = that.sessionID; 175 | } 176 | if (replyHandler) { 177 | var replyAddress = makeUUID(); 178 | envelope.replyAddress = replyAddress; 179 | replyHandlers[replyAddress] = replyHandler; 180 | } 181 | var str = JSON.stringify(envelope); 182 | sockJSConn.send(str); 183 | } 184 | 185 | function checkOpen() { 186 | if (state != vertx.EventBus.OPEN) { 187 | throw new Error('INVALID_STATE_ERR'); 188 | } 189 | } 190 | 191 | function checkSpecified(paramName, paramType, param, optional) { 192 | if (!optional && !param) { 193 | throw new Error("Parameter " + paramName + " must be specified"); 194 | } 195 | if (param && typeof param != paramType) { 196 | throw new Error("Parameter " + paramName + " must be of type " + paramType); 197 | } 198 | } 199 | 200 | function isFunction(obj) { 201 | return !!(obj && obj.constructor && obj.call && obj.apply); 202 | } 203 | 204 | function makeUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" 205 | .replace(/[xy]/g,function(a,b){return b=Math.random()*16,(a=="y"?b&3|8:b|0).toString(16)})} 206 | 207 | } 208 | 209 | vertx.EventBus.CONNECTING = 0; 210 | vertx.EventBus.OPEN = 1; 211 | vertx.EventBus.CLOSING = 2; 212 | vertx.EventBus.CLOSED = 3; 213 | 214 | return vertx.EventBus; 215 | 216 | }); -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/resources/webroot/chat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | Chat System 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | What is your name? 23 | Join 24 | 25 | 26 | 27 | 28 | 29 | Chat System 30 | 31 | 32 | 33 | 34 | 35 | RECENT CHAT HISTORY 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | Message 48 | 49 | Alex Deo 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 66 | 67 | 68 | 69 | 70 | 71 | ONLINE USERS 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Alex Deo 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/src/main/resources/webroot/error/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 6 | 7 | 8 | Not found! 9 | 10 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Maven-Artifact-Id: slime-http 3 | Built-By: pgmnle 4 | Maven-Version: 0.0.1-SNAPSHOT 5 | Build-Jdk: 1.8.0_25 6 | Created-By: Maven Integration for Eclipse 7 | Maven-Group-Id: io.slime.workshop 8 | 9 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/META-INF/maven/io.slime.workshop/slime-http/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Sun Feb 26 15:08:16 KST 2017 3 | version=0.0.1-SNAPSHOT 4 | groupId=io.slime.workshop 5 | m2e.projectName=slime-http 6 | m2e.projectLocation=/Users/pgmnle/git/slime/slime-microservice-chat/slime-http 7 | artifactId=slime-http 8 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/META-INF/maven/io.slime.workshop/slime-http/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | io.slime.workshop 5 | slime-microservice-chat 6 | 0.0.1-SNAPSHOT 7 | 8 | 9 | slime-http 10 | 11 | 12 | io.slime.chat.http.HttpServer 13 | 14 | 15 | 16 | 17 | io.slime.workshop 18 | slime-common 19 | ${project.version} 20 | 21 | 22 | 23 | 24 | 25 | 26 | maven-shade-plugin 27 | 28 | 29 | maven-dependency-plugin 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unlogicaldev/slime/3fb52f60e08b4c97f9ff5dec2107f9f19bbb4ad8/slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/img/favicon.png -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/img/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unlogicaldev/slime/3fb52f60e08b4c97f9ff5dec2107f9f19bbb4ad8/slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/img/user.png -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/img/user_offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unlogicaldev/slime/3fb52f60e08b4c97f9ff5dec2107f9f19bbb4ad8/slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/img/user_offline.png -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/js/chat.js: -------------------------------------------------------------------------------- 1 | var ChannelType = { 2 | NEW_USER: "/user", 3 | NEW_MESSAGE: "/message", 4 | OFFLINE: "/offline" 5 | }; 6 | var serverIp = "localhost"; 7 | 8 | var page = { 9 | 10 | sockJSClient: null, 11 | 12 | $msgList: $("#lstMsg"), 13 | $msgModel: $("#msgModel").detach().removeAttr("id"), 14 | 15 | $userList: $("#lstUsers"), 16 | $userModel: $("#userModel").detach().removeAttr("id"), 17 | 18 | init: function() { 19 | page.initView(); 20 | page.bindEvent(); 21 | }, 22 | 23 | initView: function() { 24 | 25 | }, 26 | 27 | connect: function(userId, successCallback) { 28 | var url = sprintf("http://%s:8383/sockjs", serverIp, userId) 29 | page.sockJSClient = new vertx.EventBus(url); 30 | 31 | page.sockJSClient.onopen = function () { 32 | page.sockJSClient.login(userId, "password", function(response) { 33 | successCallback(response); 34 | }); 35 | }; 36 | }, 37 | 38 | bindEvent: function() { 39 | 40 | $("#txtName").keyup(function(e){ 41 | if(e.keyCode == 13) 42 | { 43 | $("#btnJoin").click(); 44 | } 45 | }); 46 | $("#btnJoin").on("click", function() { 47 | var userId = $("#txtName").val(); 48 | 49 | page.connect(userId, function(response){ 50 | 51 | $(".loginDiv").hide(); 52 | $(".container").show(); 53 | 54 | var users = response.list; 55 | $.each(users, function(index, user){ 56 | page.renderUser({userId: user}); 57 | }); 58 | 59 | // emphasize current user 60 | page.$userList.find("#" + userId).find("h5").css("font-weight", "bold").css("font-style", "italic") 61 | 62 | 63 | // handle event of server close current connection 64 | page.sockJSClient.onclose = function(){ 65 | $(".loginDiv").show(); 66 | $(".container").hide(); 67 | }; 68 | 69 | 70 | var channel = "topic/chat".concat(ChannelType.NEW_MESSAGE); 71 | page.sockJSClient.registerHandler(channel, function(msg){ 72 | page.renderMessage(msg) 73 | }); 74 | 75 | 76 | var channel = "topic/chat".concat(ChannelType.NEW_USER); 77 | page.sockJSClient.registerHandler(channel, function(user){ 78 | page.renderUser(user); 79 | }); 80 | 81 | var channel = "topic/chat".concat(ChannelType.OFFLINE); 82 | page.sockJSClient.registerHandler(channel, function(user){ 83 | page.removeUser(user); 84 | }); 85 | 86 | }) 87 | }); 88 | 89 | 90 | 91 | $("#txtMessage").keyup(function(e){ 92 | if(e.keyCode == 13) 93 | { 94 | $("#btnSend").click(); 95 | } 96 | }); 97 | 98 | $("#btnSend").on("click", function(){ 99 | var $txtMessage = $("#txtMessage"); 100 | var msg = $txtMessage.val(); 101 | $txtMessage.val(""); 102 | 103 | var address = "topic/chat".concat(ChannelType.NEW_MESSAGE); 104 | page.sockJSClient.publish(address, msg, function(response) {}); 105 | }); 106 | }, 107 | 108 | renderMessage: function(msg) { 109 | var $msgModel = page.$msgModel.clone(); 110 | $msgModel.find(".lblMsg").text(msg.message); 111 | $msgModel.find(".lblUser").text(msg.sender); 112 | page.$msgList.append($msgModel); 113 | }, 114 | 115 | renderUser: function(user) { 116 | var $userModel = page.$userModel.clone(); 117 | $userModel.prop("id", user.userId); 118 | $userModel.find(".lblUser").text(user.userId); 119 | page.$userList.append($userModel); 120 | }, 121 | 122 | removeUser: function(user) { 123 | page.$userList.find("#" + user.userId).remove(); 124 | } 125 | }; 126 | 127 | $(document).ready(function(){ 128 | page.init(); 129 | 130 | window.onbeforeunload = function (event) { 131 | 132 | // demonstrate before closing browser, 133 | // no need to call this, disconnect is called when tab/browser is close 134 | if(page.sockJSClient != null) { 135 | page.sockJSClient.close(); 136 | } 137 | }; 138 | 139 | }) -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/js/sprintf.min.js: -------------------------------------------------------------------------------- 1 | /*! sprintf-js v1.0.3 | Copyright (c) 2007-present, Alexandru Marasteanu | BSD-3-Clause */ 2 | !function(e){"use strict";function t(){var e=arguments[0],r=t.cache;return r[e]&&r.hasOwnProperty(e)||(r[e]=t.parse(e)),t.format.call(null,r[e],arguments)}function r(e){return"number"==typeof e?"number":"string"==typeof e?"string":Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}function n(e,t){return t>=0&&7>=t&&i[e]?i[e][t]:Array(t+1).join(e)}var s={not_string:/[^s]/,not_bool:/[^t]/,not_type:/[^T]/,not_primitive:/[^v]/,number:/[diefg]/,numeric_arg:/bcdiefguxX/,json:/[j]/,not_json:/[^j]/,text:/^[^\x25]+/,modulo:/^\x25{2}/,placeholder:/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/,key:/^([a-z_][a-z_\d]*)/i,key_access:/^\.([a-z_][a-z_\d]*)/i,index_access:/^\[(\d+)\]/,sign:/^[\+\-]/};t.format=function(e,a){var i,o,l,c,p,f,u,g=1,_=e.length,d="",b=[],h=!0,x="";for(o=0;_>o;o++)if(d=r(e[o]),"string"===d)b[b.length]=e[o];else if("array"===d){if(c=e[o],c[2])for(i=a[g],l=0;l=0),c[8]){case"b":i=parseInt(i,10).toString(2);break;case"c":i=String.fromCharCode(parseInt(i,10));break;case"d":case"i":i=parseInt(i,10);break;case"j":i=JSON.stringify(i,null,c[6]?parseInt(c[6]):0);break;case"e":i=c[7]?parseFloat(i).toExponential(c[7]):parseFloat(i).toExponential();break;case"f":i=c[7]?parseFloat(i).toFixed(c[7]):parseFloat(i);break;case"g":i=c[7]?parseFloat(i).toPrecision(c[7]):parseFloat(i);break;case"o":i=i.toString(8);break;case"s":i=String(i),i=c[7]?i.substring(0,c[7]):i;break;case"t":i=String(!!i),i=c[7]?i.substring(0,c[7]):i;break;case"T":i=r(i),i=c[7]?i.substring(0,c[7]):i;break;case"u":i=parseInt(i,10)>>>0;break;case"v":i=i.valueOf(),i=c[7]?i.substring(0,c[7]):i;break;case"x":i=parseInt(i,10).toString(16);break;case"X":i=parseInt(i,10).toString(16).toUpperCase()}s.json.test(c[8])?b[b.length]=i:(!s.number.test(c[8])||h&&!c[3]?x="":(x=h?"+":"-",i=i.toString().replace(s.sign,"")),f=c[4]?"0"===c[4]?"0":c[4].charAt(1):" ",u=c[6]-(x+i).length,p=c[6]&&u>0?n(f,u):"",b[b.length]=c[5]?x+i+p:"0"===f?x+p+i:p+x+i)}return b.join("")},t.cache={},t.parse=function(e){for(var t=e,r=[],n=[],a=0;t;){if(null!==(r=s.text.exec(t)))n[n.length]=r[0];else if(null!==(r=s.modulo.exec(t)))n[n.length]="%";else{if(null===(r=s.placeholder.exec(t)))throw new SyntaxError("[sprintf] unexpected placeholder");if(r[2]){a|=1;var i=[],o=r[2],l=[];if(null===(l=s.key.exec(o)))throw new SyntaxError("[sprintf] failed to parse named argument key");for(i[i.length]=l[1];""!==(o=o.substring(l[0].length));)if(null!==(l=s.key_access.exec(o)))i[i.length]=l[1];else{if(null===(l=s.index_access.exec(o)))throw new SyntaxError("[sprintf] failed to parse named argument key");i[i.length]=l[1]}r[2]=i}else a|=2;if(3===a)throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported");n[n.length]=r}t=t.substring(r[0].length)}return n};var a=function(e,r,n){return n=(r||[]).slice(0),n.splice(0,0,e),t.apply(null,n)},i={0:["","0","00","000","0000","00000","000000","0000000"]," ":[""," "," "," "," "," "," "," "],_:["","_","__","___","____","_____","______","_______"]};"undefined"!=typeof exports?(exports.sprintf=t,exports.vsprintf=a):(e.sprintf=t,e.vsprintf=a,"function"==typeof define&&define.amd&&define(function(){return{sprintf:t,vsprintf:a}}))}("undefined"==typeof window?this:window); 3 | //# sourceMappingURL=sprintf.min.js.map -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/js/sprintf.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["sprintf.min.js","sprintf.js"],"names":["window","sprintf","key","arguments","cache","hasOwnProperty","parse","format","call","get_type","variable","Object","prototype","toString","slice","toLowerCase","str_repeat","input","multiplier","preformattedPadding","Array","join","re","not_string","not_bool","not_type","not_primitive","number","numeric_arg","json","not_json","text","modulo","placeholder","key_access","index_access","sign","parse_tree","argv","arg","i","k","match","pad","pad_character","pad_length","cursor","tree_length","length","node_type","output","is_positive","Error","test","isNaN","TypeError","parseInt","String","fromCharCode","JSON","stringify","parseFloat","toExponential","toFixed","toPrecision","substring","valueOf","toUpperCase","replace","charAt","fmt","_fmt","arg_names","exec","SyntaxError","field_list","replacement_field","field_match","vsprintf","_argv","splice","apply","0"," ","_","exports","define","amd","this"],"mappings":"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","file":"sprintf.min.js","sourcesContent":[null,"/* globals window, exports, define */\n\n(function(window) {\n 'use strict'\n\n var re = {\n not_string: /[^s]/,\n not_bool: /[^t]/,\n not_type: /[^T]/,\n not_primitive: /[^v]/,\n number: /[diefg]/,\n numeric_arg: /bcdiefguxX/,\n json: /[j]/,\n not_json: /[^j]/,\n text: /^[^\\x25]+/,\n modulo: /^\\x25{2}/,\n placeholder: /^\\x25(?:([1-9]\\d*)\\$|\\(([^\\)]+)\\))?(\\+)?(0|'[^$])?(-)?(\\d+)?(?:\\.(\\d+))?([b-gijostTuvxX])/,\n key: /^([a-z_][a-z_\\d]*)/i,\n key_access: /^\\.([a-z_][a-z_\\d]*)/i,\n index_access: /^\\[(\\d+)\\]/,\n sign: /^[\\+\\-]/\n }\n\n function sprintf() {\n var key = arguments[0], cache = sprintf.cache\n if (!(cache[key] && cache.hasOwnProperty(key))) {\n cache[key] = sprintf.parse(key)\n }\n return sprintf.format.call(null, cache[key], arguments)\n }\n\n sprintf.format = function(parse_tree, argv) {\n var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = ''\n for (i = 0; i < tree_length; i++) {\n node_type = get_type(parse_tree[i])\n if (node_type === 'string') {\n output[output.length] = parse_tree[i]\n }\n else if (node_type === 'array') {\n match = parse_tree[i] // convenience purposes only\n if (match[2]) { // keyword argument\n arg = argv[cursor]\n for (k = 0; k < match[2].length; k++) {\n if (!arg.hasOwnProperty(match[2][k])) {\n throw new Error(sprintf('[sprintf] property \"%s\" does not exist', match[2][k]))\n }\n arg = arg[match[2][k]]\n }\n }\n else if (match[1]) { // positional argument (explicit)\n arg = argv[match[1]]\n }\n else { // positional argument (implicit)\n arg = argv[cursor++]\n }\n\n if (re.not_type.test(match[8]) && re.not_primitive.test(match[8]) && get_type(arg) == 'function') {\n arg = arg()\n }\n\n if (re.numeric_arg.test(match[8]) && (get_type(arg) != 'number' && isNaN(arg))) {\n throw new TypeError(sprintf(\"[sprintf] expecting number but found %s\", get_type(arg)))\n }\n\n if (re.number.test(match[8])) {\n is_positive = arg >= 0\n }\n\n switch (match[8]) {\n case 'b':\n arg = parseInt(arg, 10).toString(2)\n break\n case 'c':\n arg = String.fromCharCode(parseInt(arg, 10))\n break\n case 'd':\n case 'i':\n arg = parseInt(arg, 10)\n break\n case 'j':\n arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0)\n break\n case 'e':\n arg = match[7] ? parseFloat(arg).toExponential(match[7]) : parseFloat(arg).toExponential()\n break\n case 'f':\n arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg)\n break\n case 'g':\n arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg)\n break\n case 'o':\n arg = arg.toString(8)\n break\n case 's':\n arg = String(arg)\n arg = (match[7] ? arg.substring(0, match[7]) : arg)\n break\n case 't':\n arg = String(!!arg)\n arg = (match[7] ? arg.substring(0, match[7]) : arg)\n break\n case 'T':\n arg = get_type(arg)\n arg = (match[7] ? arg.substring(0, match[7]) : arg)\n break\n case 'u':\n arg = parseInt(arg, 10) >>> 0\n break\n case 'v':\n arg = arg.valueOf()\n arg = (match[7] ? arg.substring(0, match[7]) : arg)\n break\n case 'x':\n arg = parseInt(arg, 10).toString(16)\n break\n case 'X':\n arg = parseInt(arg, 10).toString(16).toUpperCase()\n break\n }\n if (re.json.test(match[8])) {\n output[output.length] = arg\n }\n else {\n if (re.number.test(match[8]) && (!is_positive || match[3])) {\n sign = is_positive ? '+' : '-'\n arg = arg.toString().replace(re.sign, '')\n }\n else {\n sign = ''\n }\n pad_character = match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' '\n pad_length = match[6] - (sign + arg).length\n pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : '') : ''\n output[output.length] = match[5] ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg)\n }\n }\n }\n return output.join('')\n }\n\n sprintf.cache = {}\n\n sprintf.parse = function(fmt) {\n var _fmt = fmt, match = [], parse_tree = [], arg_names = 0\n while (_fmt) {\n if ((match = re.text.exec(_fmt)) !== null) {\n parse_tree[parse_tree.length] = match[0]\n }\n else if ((match = re.modulo.exec(_fmt)) !== null) {\n parse_tree[parse_tree.length] = '%'\n }\n else if ((match = re.placeholder.exec(_fmt)) !== null) {\n if (match[2]) {\n arg_names |= 1\n var field_list = [], replacement_field = match[2], field_match = []\n if ((field_match = re.key.exec(replacement_field)) !== null) {\n field_list[field_list.length] = field_match[1]\n while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {\n if ((field_match = re.key_access.exec(replacement_field)) !== null) {\n field_list[field_list.length] = field_match[1]\n }\n else if ((field_match = re.index_access.exec(replacement_field)) !== null) {\n field_list[field_list.length] = field_match[1]\n }\n else {\n throw new SyntaxError(\"[sprintf] failed to parse named argument key\")\n }\n }\n }\n else {\n throw new SyntaxError(\"[sprintf] failed to parse named argument key\")\n }\n match[2] = field_list\n }\n else {\n arg_names |= 2\n }\n if (arg_names === 3) {\n throw new Error(\"[sprintf] mixing positional and named placeholders is not (yet) supported\")\n }\n parse_tree[parse_tree.length] = match\n }\n else {\n throw new SyntaxError(\"[sprintf] unexpected placeholder\")\n }\n _fmt = _fmt.substring(match[0].length)\n }\n return parse_tree\n }\n\n var vsprintf = function(fmt, argv, _argv) {\n _argv = (argv || []).slice(0)\n _argv.splice(0, 0, fmt)\n return sprintf.apply(null, _argv)\n }\n\n /**\n * helpers\n */\n function get_type(variable) {\n if (typeof variable === 'number') {\n return 'number'\n }\n else if (typeof variable === 'string') {\n return 'string'\n }\n else {\n return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase()\n }\n }\n\n var preformattedPadding = {\n '0': ['', '0', '00', '000', '0000', '00000', '000000', '0000000'],\n ' ': ['', ' ', ' ', ' ', ' ', ' ', ' ', ' '],\n '_': ['', '_', '__', '___', '____', '_____', '______', '_______'],\n }\n function str_repeat(input, multiplier) {\n if (multiplier >= 0 && multiplier <= 7 && preformattedPadding[input]) {\n return preformattedPadding[input][multiplier]\n }\n return Array(multiplier + 1).join(input)\n }\n\n /**\n * export to either browser or node.js\n */\n if (typeof exports !== 'undefined') {\n exports.sprintf = sprintf\n exports.vsprintf = vsprintf\n }\n else {\n window.sprintf = sprintf\n window.vsprintf = vsprintf\n\n if (typeof define === 'function' && define.amd) {\n define(function() {\n return {\n sprintf: sprintf,\n vsprintf: vsprintf\n }\n })\n }\n }\n})(typeof window === 'undefined' ? this : window);\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/webroot/chat/assets/js/vertxbus.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | var vertx = vertx || {}; 18 | 19 | !function(factory) { 20 | if (typeof define === "function" && define.amd) { 21 | // Expose as an AMD module with SockJS dependency. 22 | // "vertxbus" and "sockjs" names are used because 23 | // AMD module names are derived from file names. 24 | define("vertxbus", ["sockjs"], factory); 25 | } else { 26 | // No AMD-compliant loader 27 | factory(SockJS); 28 | } 29 | }(function(SockJS) { 30 | 31 | vertx.EventBus = function(url, options) { 32 | 33 | var that = this; 34 | var sockJSConn = new SockJS(url, undefined, options); 35 | var handlerMap = {}; 36 | var replyHandlers = {}; 37 | var state = vertx.EventBus.CONNECTING; 38 | var sessionID = null; 39 | var pingTimerID = null; 40 | 41 | that.onopen = null; 42 | that.onclose = null; 43 | 44 | that.login = function(username, password, replyHandler) { 45 | sendOrPub("send", 'vertx.basicauthmanager.login', {username: username, password: password}, function(reply) { 46 | if (reply.status === 'ok') { 47 | that.sessionID = reply.sessionID; 48 | } 49 | if (replyHandler) { 50 | delete reply.sessionID; 51 | replyHandler(reply) 52 | } 53 | }); 54 | } 55 | 56 | that.send = function(address, message, replyHandler) { 57 | sendOrPub("send", address, message, replyHandler) 58 | } 59 | 60 | that.publish = function(address, message, replyHandler) { 61 | sendOrPub("publish", address, message, replyHandler) 62 | } 63 | 64 | that.registerHandler = function(address, handler) { 65 | checkSpecified("address", 'string', address); 66 | checkSpecified("handler", 'function', handler); 67 | checkOpen(); 68 | var handlers = handlerMap[address]; 69 | if (!handlers) { 70 | handlers = [handler]; 71 | handlerMap[address] = handlers; 72 | // First handler for this address so we should register the connection 73 | var msg = { type : "register", 74 | address: address }; 75 | sockJSConn.send(JSON.stringify(msg)); 76 | } else { 77 | handlers[handlers.length] = handler; 78 | } 79 | } 80 | 81 | that.unregisterHandler = function(address, handler) { 82 | checkSpecified("address", 'string', address); 83 | checkSpecified("handler", 'function', handler); 84 | checkOpen(); 85 | var handlers = handlerMap[address]; 86 | if (handlers) { 87 | var idx = handlers.indexOf(handler); 88 | if (idx != -1) handlers.splice(idx, 1); 89 | if (handlers.length == 0) { 90 | // No more local handlers so we should unregister the connection 91 | 92 | var msg = { type : "unregister", 93 | address: address}; 94 | sockJSConn.send(JSON.stringify(msg)); 95 | delete handlerMap[address]; 96 | } 97 | } 98 | } 99 | 100 | that.close = function() { 101 | checkOpen(); 102 | if (pingTimerID) clearInterval(pingTimerID); 103 | state = vertx.EventBus.CLOSING; 104 | sockJSConn.close(); 105 | } 106 | 107 | that.readyState = function() { 108 | return state; 109 | } 110 | 111 | sockJSConn.onopen = function() { 112 | // Send the first ping then send a ping every 5 seconds 113 | sendPing(); 114 | pingTimerID = setInterval(sendPing, 5000); 115 | state = vertx.EventBus.OPEN; 116 | if (that.onopen) { 117 | that.onopen(); 118 | } 119 | }; 120 | 121 | sockJSConn.onclose = function() { 122 | state = vertx.EventBus.CLOSED; 123 | if (that.onclose) { 124 | that.onclose(); 125 | } 126 | }; 127 | 128 | sockJSConn.onmessage = function(e) { 129 | var msg = e.data; 130 | var json = JSON.parse(msg); 131 | var body = json.body; 132 | var replyAddress = json.replyAddress; 133 | var address = json.address; 134 | var replyHandler; 135 | if (replyAddress) { 136 | replyHandler = function(reply, replyHandler) { 137 | // Send back reply 138 | that.send(replyAddress, reply, replyHandler); 139 | }; 140 | } 141 | var handlers = handlerMap[address]; 142 | if (handlers) { 143 | // We make a copy since the handler might get unregistered from within the 144 | // handler itself, which would screw up our iteration 145 | var copy = handlers.slice(0); 146 | for (var i = 0; i < copy.length; i++) { 147 | copy[i](body, replyHandler); 148 | } 149 | } else { 150 | // Might be a reply message 151 | var handler = replyHandlers[address]; 152 | if (handler) { 153 | delete replyHandlers[address]; 154 | handler(body, replyHandler); 155 | } 156 | } 157 | } 158 | 159 | function sendPing() { 160 | var msg = { 161 | type: "ping" 162 | } 163 | sockJSConn.send(JSON.stringify(msg)); 164 | } 165 | 166 | function sendOrPub(sendOrPub, address, message, replyHandler) { 167 | checkSpecified("address", 'string', address); 168 | checkSpecified("replyHandler", 'function', replyHandler, true); 169 | checkOpen(); 170 | var envelope = { type : sendOrPub, 171 | address: address, 172 | body: message }; 173 | if (that.sessionID) { 174 | envelope.sessionID = that.sessionID; 175 | } 176 | if (replyHandler) { 177 | var replyAddress = makeUUID(); 178 | envelope.replyAddress = replyAddress; 179 | replyHandlers[replyAddress] = replyHandler; 180 | } 181 | var str = JSON.stringify(envelope); 182 | sockJSConn.send(str); 183 | } 184 | 185 | function checkOpen() { 186 | if (state != vertx.EventBus.OPEN) { 187 | throw new Error('INVALID_STATE_ERR'); 188 | } 189 | } 190 | 191 | function checkSpecified(paramName, paramType, param, optional) { 192 | if (!optional && !param) { 193 | throw new Error("Parameter " + paramName + " must be specified"); 194 | } 195 | if (param && typeof param != paramType) { 196 | throw new Error("Parameter " + paramName + " must be of type " + paramType); 197 | } 198 | } 199 | 200 | function isFunction(obj) { 201 | return !!(obj && obj.constructor && obj.call && obj.apply); 202 | } 203 | 204 | function makeUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" 205 | .replace(/[xy]/g,function(a,b){return b=Math.random()*16,(a=="y"?b&3|8:b|0).toString(16)})} 206 | 207 | } 208 | 209 | vertx.EventBus.CONNECTING = 0; 210 | vertx.EventBus.OPEN = 1; 211 | vertx.EventBus.CLOSING = 2; 212 | vertx.EventBus.CLOSED = 3; 213 | 214 | return vertx.EventBus; 215 | 216 | }); -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/webroot/chat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | Chat System 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | What is your name? 23 | Join 24 | 25 | 26 | 27 | 28 | 29 | Chat System 30 | 31 | 32 | 33 | 34 | 35 | RECENT CHAT HISTORY 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | Message 48 | 49 | Alex Deo 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 66 | 67 | 68 | 69 | 70 | 71 | ONLINE USERS 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Alex Deo 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-http/target/classes/webroot/error/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 6 | 7 | 8 | Not found! 9 | 10 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | slime-publish 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/test/java=UTF-8 5 | encoding//src/test/resources=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.8 6 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | io.slime.workshop 5 | slime-microservice-chat 6 | 0.0.1-SNAPSHOT 7 | 8 | slime-publish 9 | 10 | 11 | io.slime.chat.publish.MessagePublishVerticle 12 | 13 | 14 | 15 | 16 | io.slime.workshop 17 | slime-common 18 | ${project.version} 19 | 20 | 21 | 22 | 23 | 24 | 25 | maven-shade-plugin 26 | 27 | 28 | maven-dependency-plugin 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/src/conf/config_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "daemon" 3 | } -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/src/main/java/io/slime/chat/publish/MessagePublishVerticle.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.publish; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | import io.slime.chat.common.redis.JedisConnectionPool; 8 | import io.slime.chat.common.redis.RedisDaemonClient; 9 | import io.slime.chat.common.redis.RedisKeyStore; 10 | import io.vertx.core.AbstractVerticle; 11 | import io.vertx.core.json.JsonObject; 12 | import redis.clients.jedis.Jedis; 13 | 14 | public class MessagePublishVerticle extends AbstractVerticle{ 15 | 16 | @Override 17 | public void start() throws Exception { 18 | System.out.println("MessagePublishVerticle Start [" + Thread.currentThread().getId() + "]"); 19 | String deploymentID = this.deploymentID(); 20 | RedisDaemonClient.pingDaemonInstance(deploymentID, true); 21 | 22 | vertx.executeBlocking(future -> { 23 | int i = 0; 24 | while (i < 5) { 25 | String resStr = null; 26 | if(i > 0){ 27 | List res = RedisDaemonClient.getPublishMaster(5); 28 | if(res != null && res.size() > 0){ 29 | resStr = res.get(1); 30 | } 31 | }else{ 32 | resStr = RedisDaemonClient.getPublishMasterD(); 33 | } 34 | 35 | if(resStr != null && !resStr.equals("")){ 36 | System.out.println("[ work something 111"+deploymentID+"]"); 37 | System.out.println(resStr); 38 | 39 | /* 40 | * Manage Functions 41 | */ 42 | if(RedisDaemonClient.daemonManageFunction(resStr, vertx)){ 43 | 44 | final Jedis jedis = JedisConnectionPool.getJedisConnection(10); 45 | try{ 46 | JsonObject msg = new JsonObject(resStr); 47 | String address = msg.getString("address"); 48 | Set set = jedis.zrangeByScore(RedisKeyStore.REGIST + ":SERVERS:" + address, "-inf", "(0"); 49 | 50 | jedis.select(0); 51 | set.forEach(action -> { 52 | System.out.println("publish sockjs server : " +action); 53 | jedis.lpush("CLIENT:"+action, msg.toString()); 54 | }); 55 | }catch(Exception e){ 56 | e.printStackTrace(); 57 | }finally{ 58 | if(jedis != null) JedisConnectionPool.close(jedis); 59 | } 60 | } 61 | i = 0; 62 | }else{ 63 | System.out.println("[ daemon "+deploymentID+" is alive noe : "+new Date()+"]"); 64 | i++; 65 | } 66 | } 67 | future.complete(deploymentID); 68 | }, result -> { 69 | System.out.println("[ end verticle : "+ result.result() +"]"); 70 | try { 71 | 72 | this.stop(); 73 | this.start(); 74 | 75 | } catch (Exception e) { 76 | e.printStackTrace(); 77 | } 78 | }); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/target/.gitignore: -------------------------------------------------------------------------------- 1 | /classes/ 2 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/target/classes/META-INF/maven/io.slime.workshop/slime-publish/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Sun Feb 26 15:08:10 KST 2017 3 | version=0.0.1-SNAPSHOT 4 | groupId=io.slime.workshop 5 | m2e.projectName=slime-publish 6 | m2e.projectLocation=/Users/pgmnle/git/slime/slime-microservice-chat/slime-publish 7 | artifactId=slime-publish 8 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-publish/target/classes/META-INF/maven/io.slime.workshop/slime-publish/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | io.slime.workshop 5 | slime-microservice-chat 6 | 0.0.1-SNAPSHOT 7 | 8 | slime-publish 9 | 10 | 11 | io.slime.chat.publish.MessagePublishVerticle 12 | 13 | 14 | 15 | 16 | io.slime.workshop 17 | slime-common 18 | ${project.version} 19 | 20 | 21 | 22 | 23 | 24 | 25 | maven-shade-plugin 26 | 27 | 28 | maven-dependency-plugin 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-search/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-search/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | slime-search 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-search/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/test/java=UTF-8 5 | encoding//src/test/resources=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-search/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.8 6 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-search/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-search/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | io.slime.workshop 5 | slime-microservice-chat 6 | 0.0.1-SNAPSHOT 7 | 8 | slime-search 9 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-search/target/.gitignore: -------------------------------------------------------------------------------- 1 | /classes/ 2 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | slime-sockjs 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/test/java=UTF-8 5 | encoding//src/test/resources=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.8 6 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | io.slime.workshop 5 | slime-microservice-chat 6 | 0.0.1-SNAPSHOT 7 | 8 | slime-sockjs 9 | 10 | 11 | io.slime.chat.sockjs.PubSubSockJsServer 12 | 13 | 14 | 15 | 16 | io.slime.workshop 17 | slime-common 18 | ${project.version} 19 | 20 | 21 | 22 | 23 | 24 | 25 | maven-shade-plugin 26 | 27 | 28 | maven-dependency-plugin 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/conf/config_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "sockjs", 3 | "port" : 8383 4 | } -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/PubSubSockJsServer.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs; 2 | 3 | 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.stereotype.Component; 7 | 8 | import io.slime.chat.common.redis.RedisSockjsClient; 9 | import io.slime.chat.common.spring.SpringConfiguration; 10 | import io.slime.chat.common.util.VertxHolder; 11 | import io.slime.chat.sockjs.eventbridge.EventBridgeChain; 12 | import io.slime.chat.sockjs.eventbridge.EventBridgeChainResponse; 13 | import io.slime.chat.sockjs.subscribe.MessageSubscribeVerticle; 14 | import io.vertx.core.AbstractVerticle; 15 | import io.vertx.core.DeploymentOptions; 16 | import io.vertx.core.Handler; 17 | import io.vertx.core.http.HttpServer; 18 | import io.vertx.ext.web.Router; 19 | import io.vertx.ext.web.handler.sockjs.BridgeEvent; 20 | import io.vertx.ext.web.handler.sockjs.BridgeEventType; 21 | import io.vertx.ext.web.handler.sockjs.BridgeOptions; 22 | import io.vertx.ext.web.handler.sockjs.PermittedOptions; 23 | import io.vertx.ext.web.handler.sockjs.SockJSHandler; 24 | 25 | @Component 26 | public class PubSubSockJsServer extends AbstractVerticle { 27 | private static final Logger logger = LoggerFactory.getLogger(PubSubSockJsServer.class); 28 | private int serverPort = 8383; 29 | 30 | public static boolean isStart = false; 31 | 32 | private EventBridgeChain eventBridgeChain = (EventBridgeChain) SpringConfiguration.getBean(EventBridgeChain.class); 33 | 34 | @Override 35 | public void start() throws Exception{ 36 | 37 | if( VertxHolder.getVertx() == null ) VertxHolder.setVertx(vertx); 38 | logger.info("Pub/Sub SockJs Server started on port {}", serverPort); 39 | 40 | Router router = Router.router(vertx); 41 | SockJSHandler socketHandler = SockJSHandler.create(vertx) 42 | .bridge(new BridgeOptions() 43 | .addOutboundPermitted(new PermittedOptions().setAddressRegex("^topic/.*")) 44 | 45 | // use to set client ping timeout -> will result closing connection if no ping sent 46 | /*.setPingTimeout(60000)*/, 47 | new Handler() { 48 | @Override 49 | public void handle(BridgeEvent event) { 50 | boolean isResult = true; 51 | String message = "Oops!"; 52 | 53 | System.out.println(event.type()); 54 | 55 | EventBridgeChainResponse processInChain = eventBridgeChain.processInChain(event); 56 | if(processInChain.isProcesssed()) { 57 | if(processInChain.getException() != null) { 58 | isResult = false; 59 | logger.error(processInChain.getException().getMessage(), 60 | processInChain.getException()); 61 | message = processInChain.getException().getMessage(); 62 | } 63 | } 64 | 65 | 66 | 67 | if(isResult) { 68 | 69 | if(event.type().equals(BridgeEventType.REGISTER)){ 70 | System.out.println(event.getRawMessage()); 71 | RedisSockjsClient.REGISTER(event); 72 | } 73 | 74 | 75 | event.complete(isResult); 76 | } 77 | else { 78 | event.fail(new Exception(message)); 79 | } 80 | 81 | } 82 | }); 83 | 84 | 85 | router.route("/sockjs/*").handler( 86 | socketHandler 87 | ); 88 | 89 | /* 90 | * subscribe published message 91 | */ 92 | vertx.deployVerticle(new MessageSubscribeVerticle(), new DeploymentOptions().setWorker(true).setMultiThreaded(true)); 93 | vertx.deployVerticle(new MessageSubscribeVerticle(), new DeploymentOptions().setWorker(true).setMultiThreaded(true)); 94 | vertx.deployVerticle(new MessageSubscribeVerticle(), new DeploymentOptions().setWorker(true).setMultiThreaded(true)); 95 | 96 | HttpServer server = vertx.createHttpServer().requestHandler(router::accept); 97 | 98 | 99 | server.listen(serverPort); 100 | 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/eventbridge/EventBridgeChain.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs.eventbridge; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import io.vertx.ext.web.handler.sockjs.BridgeEvent; 7 | 8 | public class EventBridgeChain { 9 | List handlers = new ArrayList<>(); 10 | 11 | public void regisger(EventBridgeChainHandler handler) { 12 | handlers.add(handler); 13 | } 14 | 15 | 16 | public EventBridgeChainResponse processInChain(BridgeEvent event) { 17 | EventBridgeChainResponse response = new EventBridgeChainResponse(); 18 | 19 | for (EventBridgeChainHandler handler : handlers) { 20 | boolean handle = Boolean.FALSE; 21 | try { 22 | handle = handler.handle(event); 23 | if(handle) { 24 | response.setProcesssed(Boolean.TRUE); 25 | response.setHandler(handler); 26 | break; 27 | } 28 | } catch (EventBridgeChainException e) { 29 | handle = e.isProccessed(); 30 | if(handle) { 31 | response.setHandler(handler); 32 | response.setException(e); 33 | response.setProcesssed(Boolean.TRUE); 34 | break; 35 | } 36 | } 37 | } 38 | 39 | 40 | return response; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/eventbridge/EventBridgeChainException.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs.eventbridge; 2 | 3 | public class EventBridgeChainException extends Throwable { 4 | private static final long serialVersionUID = -4375961428621249366L; 5 | 6 | private boolean proccessed; 7 | 8 | 9 | public EventBridgeChainException(boolean isProccess, String message) { 10 | super(message); 11 | this.proccessed = isProccess; 12 | } 13 | 14 | public EventBridgeChainException(boolean isProccess) { 15 | super(); 16 | this.proccessed = isProccess; 17 | } 18 | 19 | public boolean isProccessed() { 20 | return proccessed; 21 | } 22 | 23 | public void setProccessed(boolean proccessed) { 24 | this.proccessed = proccessed; 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/eventbridge/EventBridgeChainHandler.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs.eventbridge; 2 | 3 | import io.vertx.ext.web.handler.sockjs.BridgeEvent; 4 | 5 | public interface EventBridgeChainHandler { 6 | boolean handle(BridgeEvent event) throws EventBridgeChainException; 7 | } 8 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/eventbridge/EventBridgeChainResponse.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs.eventbridge; 2 | 3 | public class EventBridgeChainResponse { 4 | private EventBridgeChainHandler handler; 5 | private boolean processsed; 6 | private EventBridgeChainException exception; 7 | 8 | public EventBridgeChainResponse() {} 9 | 10 | /*public EventBridgeChainResponse(EventBridgeChainHandler handler, boolean isProccessed) { 11 | this.processsed = isProccessed; 12 | this.handler = handler; 13 | } 14 | 15 | 16 | public EventBridgeChainResponse(EventBridgeChainHandler handler, EventBridgeChainException exception) { 17 | this.processsed = Boolean.FALSE; 18 | this.handler = handler; 19 | this.exception = exception; 20 | }*/ 21 | 22 | public EventBridgeChainHandler getHandler() { 23 | return handler; 24 | } 25 | public void setHandler(EventBridgeChainHandler handler) { 26 | this.handler = handler; 27 | } 28 | 29 | 30 | 31 | public boolean isProcesssed() { 32 | return processsed; 33 | } 34 | 35 | public void setProcesssed(boolean processsed) { 36 | this.processsed = processsed; 37 | } 38 | 39 | public EventBridgeChainException getException() { 40 | return exception; 41 | } 42 | public void setException(EventBridgeChainException exception) { 43 | this.exception = exception; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/eventbridge/chain/ChatMessageChainHandler.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs.eventbridge.chain; 2 | 3 | import java.util.Map; 4 | 5 | import io.slime.chat.common.redis.RedisSockjsClient; 6 | import io.slime.chat.common.util.VertxHolder; 7 | import io.slime.chat.common.util.WebSocketSessionHolder; 8 | import io.slime.chat.sockjs.eventbridge.EventBridgeChainException; 9 | import io.slime.chat.sockjs.eventbridge.EventBridgeChainHandler; 10 | import io.vertx.core.Vertx; 11 | import io.vertx.core.json.JsonObject; 12 | import io.vertx.ext.web.handler.sockjs.BridgeEvent; 13 | import io.vertx.ext.web.handler.sockjs.BridgeEventType; 14 | import io.vertx.ext.web.handler.sockjs.SockJSSocket; 15 | 16 | public class ChatMessageChainHandler implements EventBridgeChainHandler { 17 | 18 | @Override 19 | public boolean handle(BridgeEvent event) throws EventBridgeChainException { 20 | boolean isHandle = Boolean.FALSE; 21 | 22 | if(BridgeEventType.PUBLISH == event.type()) { 23 | Vertx vertx = VertxHolder.getVertx(); 24 | SockJSSocket sockJSSocket = event.socket(); 25 | Map rawMessage = event.getRawMessage().getMap(); 26 | 27 | String senderId = sockJSSocket.headers().get(WebSocketSessionHolder.USER_KEY); 28 | String address = (String) rawMessage.get("address"); 29 | String msg = (String) rawMessage.get("body"); 30 | 31 | RedisSockjsClient.PUBLISH(address, 32 | new JsonObject() 33 | .put("message", msg) 34 | .put("sender", senderId)); 35 | // vertx.eventBus().publish(address, 36 | // new JsonObject() 37 | // .put("message", msg) 38 | // .put("sender", senderId)); 39 | 40 | isHandle = Boolean.TRUE; 41 | 42 | } 43 | 44 | return isHandle; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/eventbridge/chain/LoginChainHandler.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs.eventbridge.chain; 2 | 3 | import java.util.Map; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | import io.slime.chat.common.redis.RedisSockjsClient; 10 | import io.slime.chat.common.spring.SpringConfiguration; 11 | import io.slime.chat.common.spring.service.RequestLogService; 12 | import io.slime.chat.common.util.VertxHolder; 13 | import io.slime.chat.common.util.WebSocketSessionHolder; 14 | import io.slime.chat.sockjs.eventbridge.EventBridgeChainException; 15 | import io.slime.chat.sockjs.eventbridge.EventBridgeChainHandler; 16 | import io.vertx.core.Vertx; 17 | import io.vertx.core.buffer.Buffer; 18 | import io.vertx.core.json.JsonObject; 19 | import io.vertx.ext.web.handler.sockjs.BridgeEvent; 20 | import io.vertx.ext.web.handler.sockjs.BridgeEventType; 21 | import io.vertx.ext.web.handler.sockjs.SockJSSocket; 22 | 23 | public class LoginChainHandler implements EventBridgeChainHandler { 24 | private static final Logger logger = LoggerFactory.getLogger(LoginChainHandler.class); 25 | 26 | @Autowired 27 | private RequestLogService requestLogService = (RequestLogService) SpringConfiguration.getBean("requestLogService"); 28 | 29 | @Override 30 | public boolean handle(BridgeEvent event) throws EventBridgeChainException { 31 | boolean isHandle = Boolean.FALSE; 32 | 33 | if(BridgeEventType.SEND == event.type()) { 34 | Vertx vertx = VertxHolder.getVertx(); 35 | SockJSSocket sockJSSocket = event.socket(); 36 | 37 | Map rawMessage = event.getRawMessage().getMap(); 38 | 39 | 40 | String replyAddress = (String) rawMessage.get("replyAddress"); 41 | String address = (String) rawMessage.get("address"); 42 | 43 | if("vertx.basicauthmanager.login".equals(address)) { 44 | @SuppressWarnings("unchecked") 45 | Map credential = (Map) rawMessage.get("body"); 46 | String userId = credential.get("username"); 47 | //String password = credential.get("password"); 48 | 49 | if(userId == null || "".equals(userId)) { 50 | logger.warn("Connection rejected"); 51 | sockJSSocket.close(); 52 | 53 | throw new EventBridgeChainException(true, "No user attached"); 54 | } 55 | else { 56 | 57 | boolean exists = WebSocketSessionHolder.exists(userId); 58 | if(exists) { 59 | throw new EventBridgeChainException(true, "User already registered"); 60 | } 61 | 62 | sockJSSocket.headers().set(WebSocketSessionHolder.USER_KEY, userId); 63 | requestLogService.logWebSocketConnection(sockJSSocket); 64 | 65 | WebSocketSessionHolder.add(userId, sockJSSocket); 66 | 67 | System.out.println(vertx); 68 | System.out.println(vertx.eventBus()); 69 | System.out.println(userId); 70 | 71 | RedisSockjsClient.PUBLISH("topic/chat/user", 72 | new JsonObject() 73 | .put("userId", userId)); 74 | // publish there is a new user coming 75 | // vertx.eventBus().publish("topic/chat/user", 76 | // new JsonObject() 77 | // .put("userId", userId)); 78 | 79 | // get all online and send back to 80 | JsonObject json = new JsonObject() 81 | .put("type", "login") // optional 82 | .put("address", replyAddress) 83 | .put("body", 84 | new JsonObject() 85 | .put("result", true) 86 | .put("list", WebSocketSessionHolder.getUsers())); 87 | String data = json.toString(); 88 | 89 | sockJSSocket.write(Buffer.buffer(data)); 90 | 91 | isHandle = Boolean.TRUE; 92 | } 93 | 94 | } 95 | 96 | } 97 | return isHandle; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/eventbridge/chain/OfflineChainHandler.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs.eventbridge.chain; 2 | 3 | 4 | import io.slime.chat.common.redis.RedisSockjsClient; 5 | import io.slime.chat.common.util.VertxHolder; 6 | import io.slime.chat.common.util.WebSocketSessionHolder; 7 | import io.slime.chat.sockjs.eventbridge.EventBridgeChainException; 8 | import io.slime.chat.sockjs.eventbridge.EventBridgeChainHandler; 9 | import io.vertx.core.Vertx; 10 | import io.vertx.core.json.JsonObject; 11 | import io.vertx.ext.web.handler.sockjs.BridgeEvent; 12 | import io.vertx.ext.web.handler.sockjs.BridgeEventType; 13 | import io.vertx.ext.web.handler.sockjs.SockJSSocket; 14 | 15 | public class OfflineChainHandler implements EventBridgeChainHandler { 16 | 17 | @Override 18 | public boolean handle(BridgeEvent event) throws EventBridgeChainException { 19 | boolean isHandle = Boolean.FALSE; 20 | 21 | if(BridgeEventType.SOCKET_CLOSED == event.type()) { 22 | Vertx vertx = VertxHolder.getVertx(); 23 | 24 | isHandle = Boolean.TRUE; 25 | 26 | SockJSSocket sockJSSocket = event.socket(); 27 | 28 | // notify user offline 29 | String address = "topic/chat/offline"; 30 | String userId = sockJSSocket.headers().get(WebSocketSessionHolder.USER_KEY); 31 | 32 | WebSocketSessionHolder.remove(userId); 33 | 34 | RedisSockjsClient.PUBLISH(address, 35 | new JsonObject() 36 | .put("userId", userId)); 37 | 38 | // vertx.eventBus().publish(address, 39 | // new JsonObject() 40 | // .put("userId", userId)); 41 | 42 | } 43 | 44 | return isHandle; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/spring/SpringConfigurationSockjs.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs.spring; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | import io.slime.chat.sockjs.eventbridge.EventBridgeChain; 7 | import io.slime.chat.sockjs.eventbridge.chain.ChatMessageChainHandler; 8 | import io.slime.chat.sockjs.eventbridge.chain.LoginChainHandler; 9 | import io.slime.chat.sockjs.eventbridge.chain.OfflineChainHandler; 10 | 11 | 12 | @Configuration 13 | public class SpringConfigurationSockjs { 14 | @Bean 15 | public EventBridgeChain getEventBridgeChain() { 16 | EventBridgeChain eventBridgeChain = new EventBridgeChain(); 17 | 18 | eventBridgeChain.regisger(getLoginChainHandler()); 19 | eventBridgeChain.regisger(getChatMessageChainHandler()); 20 | eventBridgeChain.regisger(getOfflineChainHandler()); 21 | 22 | return eventBridgeChain; 23 | } 24 | 25 | @Bean 26 | public ChatMessageChainHandler getChatMessageChainHandler() { 27 | return new ChatMessageChainHandler(); 28 | } 29 | 30 | 31 | @Bean 32 | public LoginChainHandler getLoginChainHandler() { 33 | return new LoginChainHandler(); 34 | } 35 | 36 | @Bean 37 | public OfflineChainHandler getOfflineChainHandler() { 38 | return new OfflineChainHandler(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/src/main/java/io/slime/chat/sockjs/subscribe/MessageSubscribeVerticle.java: -------------------------------------------------------------------------------- 1 | package io.slime.chat.sockjs.subscribe; 2 | 3 | import java.util.List; 4 | 5 | import io.slime.chat.common.redis.RedisSockjsClient; 6 | import io.vertx.core.AbstractVerticle; 7 | import io.vertx.core.json.JsonObject; 8 | 9 | public class MessageSubscribeVerticle extends AbstractVerticle{ 10 | 11 | @Override 12 | public void start() throws Exception { 13 | System.out.println("MessageSubscribeVerticle Start [" + this.deploymentID() + "]"); 14 | RedisSockjsClient.pingClientInstance(this.deploymentID(), true); 15 | 16 | vertx.executeBlocking(future -> { 17 | int i = 0; 18 | while (i < 10) { 19 | String resStr = null; 20 | if(i > 0){ 21 | List res = RedisSockjsClient.getClientNotify(10); // 3 --> Channel Store 22 | if(res != null && res.size() > 0){ 23 | resStr = res.get(1); 24 | } 25 | }else{ 26 | resStr = RedisSockjsClient.getClientNotifyD(); // 3 --> Channel Store 27 | } 28 | 29 | if(resStr != null && !resStr.trim().equals("")){ 30 | System.out.println("["+Thread.currentThread().getId()+"]"); 31 | System.out.println(resStr); 32 | 33 | /* 34 | * Manage Functions 35 | */ 36 | if(RedisSockjsClient.clientManageFunction(resStr, vertx)){ 37 | 38 | /** 39 | * publish Message 40 | */ 41 | JsonObject msg = new JsonObject(resStr); 42 | if(msg.getValue("address") != null){ 43 | String address = msg.getString("address"); 44 | msg.remove("address"); 45 | vertx.eventBus().publish(address, msg); 46 | } 47 | 48 | } 49 | i = 0; 50 | }else{ 51 | i++; 52 | } 53 | } 54 | future.complete(true); 55 | }, result -> { 56 | try { 57 | this.stop(); 58 | this.start(); 59 | } catch (Exception e) { 60 | e.printStackTrace(); 61 | } 62 | }); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/target/classes/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Maven-Artifact-Id: slime-sockjs 3 | Built-By: pgmnle 4 | Maven-Version: 0.0.1-SNAPSHOT 5 | Build-Jdk: 1.8.0_25 6 | Created-By: Maven Integration for Eclipse 7 | Maven-Group-Id: io.slime.workshop 8 | 9 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/target/classes/META-INF/maven/io.slime.workshop/slime-sockjs/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Sun Feb 26 15:08:16 KST 2017 3 | version=0.0.1-SNAPSHOT 4 | groupId=io.slime.workshop 5 | m2e.projectName=slime-sockjs 6 | m2e.projectLocation=/Users/pgmnle/git/slime/slime-microservice-chat/slime-sockjs 7 | artifactId=slime-sockjs 8 | -------------------------------------------------------------------------------- /slime-microservice-chat/slime-sockjs/target/classes/META-INF/maven/io.slime.workshop/slime-sockjs/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | io.slime.workshop 5 | slime-microservice-chat 6 | 0.0.1-SNAPSHOT 7 | 8 | slime-sockjs 9 | 10 | 11 | io.slime.chat.sockjs.PubSubSockJsServer 12 | 13 | 14 | 15 | 16 | io.slime.workshop 17 | slime-common 18 | ${project.version} 19 | 20 | 21 | 22 | 23 | 24 | 25 | maven-shade-plugin 26 | 27 | 28 | maven-dependency-plugin 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /slime-microservice-chat/target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Apache Maven 2 | #Fri Feb 24 22:37:29 KST 2017 3 | version=0.0.1-SNAPSHOT 4 | groupId=io.slime.workshop 5 | artifactId=slime-microservice-chat 6 | -------------------------------------------------------------------------------- /slime-microservice-chat/target/slime-microservice-chat-0.0.1-SNAPSHOT-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unlogicaldev/slime/3fb52f60e08b4c97f9ff5dec2107f9f19bbb4ad8/slime-microservice-chat/target/slime-microservice-chat-0.0.1-SNAPSHOT-sources.jar -------------------------------------------------------------------------------- /slime-microservice-chat/target/slime-microservice-chat-0.0.1-SNAPSHOT-tests.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unlogicaldev/slime/3fb52f60e08b4c97f9ff5dec2107f9f19bbb4ad8/slime-microservice-chat/target/slime-microservice-chat-0.0.1-SNAPSHOT-tests.jar --------------------------------------------------------------------------------