├── .gitignore ├── 1_helloworld ├── HelloRoute.java ├── HelloWorld.java ├── SayItAgain.java ├── helloworld.js └── readme.md ├── 2_helloworld_mvn ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── README.adoc ├── pom.xml ├── redeploy.bat ├── redeploy.sh └── src │ ├── main │ └── java │ │ └── io │ │ └── vertx │ │ └── starter │ │ └── MainVerticle.java │ └── test │ └── java │ └── io │ └── vertx │ └── starter │ └── MainVerticleTest.java ├── 3_webserver ├── MyWebServer.java └── webroot │ └── index.html ├── 4_eventbus ├── MyConsumer.groovy ├── MyConsumer.java ├── MyPublisher.java ├── cluster.xml ├── myconsumer.js ├── myconsumer.rb ├── mypublisher.rb └── readme.md ├── 5_browserbus ├── Server.java ├── cluster.xml └── webroot │ ├── index.html │ └── vertx-eventbus.js ├── 6_circuitbreaker ├── BadBadVerticle.java ├── InvokerProtected.java ├── InvokerUnprotected.java └── cluster.xml └── 7_httpinvoker ├── Client.java ├── Server.java └── cluster.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .vertx 2 | .DS_Store 3 | target 4 | -------------------------------------------------------------------------------- /1_helloworld/HelloRoute.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | import io.vertx.ext.web.Router; 3 | import io.vertx.core.http.HttpServerResponse; 4 | 5 | public class HelloRoute extends AbstractVerticle { 6 | @Override 7 | public void start() { 8 | 9 | // Create a router object. 10 | Router router = Router.router(vertx); 11 | 12 | router.route("/").handler(routingContext -> { 13 | HttpServerResponse response = routingContext.response(); 14 | response 15 | .putHeader("content-type", "text/html") 16 | .end("

Hello

" + java.time.LocalDateTime.now()); 17 | }); 18 | 19 | router.route("/goodbye").handler(routingContext -> { 20 | HttpServerResponse response = routingContext.response(); 21 | response 22 | .putHeader("content-type", "text/html") 23 | .end("

Goodbye

" + java.time.LocalDateTime.now()); 24 | }); 25 | 26 | vertx.createHttpServer() 27 | .requestHandler(router::accept) 28 | .listen(8080); 29 | } // start 30 | 31 | } -------------------------------------------------------------------------------- /1_helloworld/HelloWorld.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | 3 | public class HelloWorld extends AbstractVerticle { 4 | @Override 5 | public void start() { 6 | vertx.createHttpServer() 7 | .requestHandler(req -> req.response().end("Hello Vert.x Java " + new java.util.Date())) 8 | .listen(8080); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /1_helloworld/SayItAgain.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | 3 | public class SayItAgain extends AbstractVerticle { 4 | @Override 5 | public void start() { 6 | vertx.setPeriodic(1000, id -> { 7 | // This handler will get called every second 8 | System.out.println("Hello World " + new java.util.Date()); 9 | }); 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /1_helloworld/helloworld.js: -------------------------------------------------------------------------------- 1 | vertx.createHttpServer().requestHandler(function (request) { 2 | 3 | var response = request.response(); 4 | response.putHeader("content-type", "text/plain"); 5 | 6 | response.end("Hello Vert.x JavaScript " + Date.now()); 7 | }).listen(8080); 8 | 9 | -------------------------------------------------------------------------------- /1_helloworld/readme.md: -------------------------------------------------------------------------------- 1 | HelloWorld.java 2 | 3 | vertx run HelloWorld.java 4 | 5 | In your browser 6 | 7 | http://localhost:8080 8 | 9 | http://screencast.com/t/7cGi330v 10 | 11 | 12 | helloworld.js 13 | 14 | vertx run helloworld.js 15 | http://localhost:8080 16 | 17 | 18 | -------------------------------------------------------------------------------- /2_helloworld_mvn/.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 | -------------------------------------------------------------------------------- /2_helloworld_mvn/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | vertx-start-project 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 | -------------------------------------------------------------------------------- /2_helloworld_mvn/.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 | -------------------------------------------------------------------------------- /2_helloworld_mvn/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /2_helloworld_mvn/README.adoc: -------------------------------------------------------------------------------- 1 | = Vert.x Maven Starter 2 | 3 | This project is a template to start your own Vert.x project using Apache Maven. 4 | 5 | == Prerequisites 6 | 7 | * Apache Maven 8 | * JDK 8+ 9 | 10 | == Getting started 11 | 12 | Create your project with: 13 | 14 | [source] 15 | ---- 16 | git clone https://github.com/cescoffier/vertx-maven-starter.git PROJECT_NAME 17 | ---- 18 | 19 | Replace `PROJECT_NAME` with the name of your project. 20 | 21 | On Linux and MacOSx (or Windows with `bash`), if you want to go faster and generate an already configured project run: 22 | 23 | [source] 24 | ---- 25 | # Bash 26 | curl https://gist.githubusercontent.com/cescoffier/cfd46c2614f54d5e2a88d5fdc4b828ed/raw/c31b5ac5b86f39b93bd8508e80aa40e880e207b5/create-project-maven.sh -o vertx-create-maven-project.sh && bash vertx-create-maven-project.sh 27 | 28 | # Fish 29 | curl https://gist.githubusercontent.com/cescoffier/cfd46c2614f54d5e2a88d5fdc4b828ed/raw/c31b5ac5b86f39b93bd8508e80aa40e880e207b5/create-project-maven.sh -o vertx-create-maven-project.sh; bash vertx-create-maven-project.sh 30 | ---- 31 | 32 | == Running the project 33 | 34 | Once you have retrieved the project, you can check that everything works with: 35 | 36 | [source] 37 | ---- 38 | mvn test exec:java 39 | ---- 40 | 41 | The command compiles the project and runs the tests, then it launches the application, so you can check by yourself. Open your browser to http://localhost:8080. You should see a _Hello World_ message. 42 | 43 | == Anatomy of the project 44 | 45 | The project contains: 46 | 47 | * a `pom.xml` file 48 | * a _main_ verticle file (src/main/java/io/vertx/starter/MainVerticle.java) 49 | * an unit test (src/main/test/io/vertx/starter/MainVerticleTest.java) 50 | 51 | == Start to hack 52 | 53 | 1. Delete the `.git` directory 54 | 2. Open the `pom.xml` file and customize the `groupId`, `artifactId` and `version`. You can also change the `main.verticle` property to use your own package name and verticle class. 55 | 3. Run `redeploy.sh` (or `redeploy.bat` on Windows) and the project recompiles while editing. 56 | 57 | NOTE: the `redeploy` script are also configurable 58 | 59 | == Building the project 60 | 61 | To build the project, just use: 62 | 63 | ---- 64 | mvn clean package 65 | ---- 66 | 67 | It generates a _fat-jar_ in the `target` directory. 68 | 69 | java -jar target/yourproject-fat.jar 70 | 71 | http://localhost:8080 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /2_helloworld_mvn/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | io.vertx.starter 9 | vertx-start-project 10 | 1.0-SNAPSHOT 11 | 12 | 13 | 3.3.2 14 | io.vertx.starter.MainVerticle 15 | 16 | 17 | 18 | 19 | 20 | io.vertx 21 | vertx-dependencies 22 | ${vertx.version} 23 | pom 24 | import 25 | 26 | 27 | 28 | 29 | 30 | 31 | io.vertx 32 | vertx-core 33 | 34 | 35 | junit 36 | junit 37 | 4.12 38 | test 39 | 40 | 41 | io.vertx 42 | vertx-unit 43 | test 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | maven-compiler-plugin 52 | 3.5.1 53 | 54 | 1.8 55 | 1.8 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-shade-plugin 65 | 2.4.3 66 | 67 | 68 | package 69 | 70 | shade 71 | 72 | 73 | 74 | 75 | 76 | io.vertx.core.Launcher 77 | ${main.verticle} 78 | 79 | 80 | 81 | META-INF/services/io.vertx.core.spi.VerticleFactory 82 | 83 | 84 | 85 | 86 | ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar 87 | 88 | 89 | 90 | 91 | 92 | 93 | org.codehaus.mojo 94 | exec-maven-plugin 95 | 1.5.0 96 | 97 | io.vertx.core.Launcher 98 | 99 | run 100 | ${main.verticle} 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /2_helloworld_mvn/redeploy.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | SET LAUNCHER="io.vertx.core.Launcher" 4 | SET VERTICLE="io.vertx.starter.MainVerticle" 5 | SET CMD="mvn compile" 6 | SET VERTX_CMD="run" 7 | SET CMD_LINE_ARGS=%* 8 | 9 | call mvn compile dependency:copy-dependencies 10 | 11 | java -cp "target\dependency\*;target\classes" %LAUNCHER% %VERTX_CMD% %VERTICLE% --redeploy="src\main\**\*" --on-redeploy=%CMD% --launcher-class=%LAUNCHER% %CMD_LINE_ARGS% 12 | -------------------------------------------------------------------------------- /2_helloworld_mvn/redeploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export LAUNCHER="io.vertx.core.Launcher" 4 | export VERTICLE="io.vertx.starter.MainVerticle" 5 | export CMD="mvn compile" 6 | export VERTX_CMD="run" 7 | 8 | mvn compile dependency:copy-dependencies 9 | java \ 10 | -cp $(echo target/dependency/*.jar | tr ' ' ':'):"target/classes" \ 11 | $LAUNCHER $VERTX_CMD $VERTICLE \ 12 | --redeploy="src/main/**/*" --on-redeploy=$CMD \ 13 | --launcher-class=$LAUNCHER \ 14 | $@ 15 | -------------------------------------------------------------------------------- /2_helloworld_mvn/src/main/java/io/vertx/starter/MainVerticle.java: -------------------------------------------------------------------------------- 1 | package io.vertx.starter; 2 | 3 | import io.vertx.core.AbstractVerticle; 4 | 5 | public class MainVerticle extends AbstractVerticle { 6 | 7 | @Override 8 | public void start() { 9 | vertx.createHttpServer() 10 | .requestHandler(req -> req.response().end("Hello Vert.x! " + new java.util.Date())) 11 | .listen(8080); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /2_helloworld_mvn/src/test/java/io/vertx/starter/MainVerticleTest.java: -------------------------------------------------------------------------------- 1 | package io.vertx.starter; 2 | 3 | import io.vertx.core.Vertx; 4 | import io.vertx.ext.unit.Async; 5 | import io.vertx.ext.unit.TestContext; 6 | import io.vertx.ext.unit.junit.VertxUnitRunner; 7 | import org.junit.After; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | 12 | @RunWith(VertxUnitRunner.class) 13 | public class MainVerticleTest { 14 | 15 | private Vertx vertx; 16 | 17 | @Before 18 | public void setUp(TestContext tc) { 19 | vertx = Vertx.vertx(); 20 | vertx.deployVerticle(MainVerticle.class.getName(), tc.asyncAssertSuccess()); 21 | } 22 | 23 | @After 24 | public void tearDown(TestContext tc) { 25 | vertx.close(tc.asyncAssertSuccess()); 26 | } 27 | 28 | @Test 29 | public void testThatTheServerIsStarted(TestContext tc) { 30 | Async async = tc.async(); 31 | vertx.createHttpClient().getNow(8080, "localhost", "/", response -> { 32 | tc.assertEquals(response.statusCode(), 200); 33 | response.bodyHandler(body -> { 34 | tc.assertTrue(body.length() > 0); 35 | async.complete(); 36 | }); 37 | }); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /3_webserver/MyWebServer.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | import io.vertx.ext.web.Router; 3 | import io.vertx.core.http.HttpServerResponse; 4 | import io.vertx.ext.web.RoutingContext; 5 | import io.vertx.ext.web.handler.StaticHandler; 6 | 7 | public class MyWebServer extends AbstractVerticle { 8 | @Override 9 | public void start() { 10 | 11 | // Create a router object. 12 | Router router = Router.router(vertx); 13 | 14 | router.get("/").handler(this::getRoot); 15 | 16 | router.get("/goodbye").handler(this::getGoodbye); 17 | 18 | router.get("/endpoint").handler(this::getEndpoint); 19 | router.put("/endpoint").handler(this::putEndpoint); 20 | router.delete("/endpoint").handler(this::deleteEndpoint); 21 | 22 | // static assets in local folder "webroot" 23 | // at http://localhost:8080/webroot/ 24 | router.route("/webroot/*").handler(StaticHandler.create("webroot")); 25 | 26 | vertx.createHttpServer() 27 | .requestHandler(router::accept) 28 | .listen(8080); 29 | } // start 30 | 31 | private void getRoot(RoutingContext routingContext) { 32 | HttpServerResponse response = routingContext.response(); 33 | response 34 | .putHeader("content-type", "text/html") 35 | .end("

Hello

" + java.time.LocalDateTime.now()); 36 | } 37 | private void getGoodbye(RoutingContext routingContext) { 38 | HttpServerResponse response = routingContext.response(); 39 | response 40 | .putHeader("content-type", "text/html") 41 | .end("

Goodbye

" + java.time.LocalDateTime.now()); 42 | } 43 | 44 | private void getEndpoint(RoutingContext routingContext) { 45 | HttpServerResponse response = routingContext.response(); 46 | String responseBody = 47 | " {" + 48 | " \"employees\": [{ " + 49 | " \"firstName\": \"John\", " + 50 | " \"lastName\": \"Doe\" " + 51 | " }, { " + 52 | " \"firstName\": \"Anna\", " + 53 | " \"lastName\": \"Smith\" " + 54 | " }, { " + 55 | " \"firstName\": \"Peter\", " + 56 | " \"lastName\": \"Jones\" " + 57 | " }]" + 58 | " } "; 59 | 60 | response 61 | .setStatusCode(200) 62 | .putHeader("content-type", "application/json") 63 | .end(responseBody); 64 | } 65 | private void putEndpoint(RoutingContext routingContext) { 66 | HttpServerResponse response = routingContext.response(); 67 | response 68 | .setStatusCode(200) 69 | .putHeader("content-type", "application/json") 70 | .end(); 71 | 72 | } 73 | private void deleteEndpoint(RoutingContext routingContext) { 74 | HttpServerResponse response = routingContext.response(); 75 | response 76 | .setStatusCode(204) 77 | .putHeader("content-type", "application/json") 78 | .end(); 79 | 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /3_webserver/webroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Index.html 4 | 5 | 6 |

Wassup!

7 | 8 | -------------------------------------------------------------------------------- /4_eventbus/MyConsumer.groovy: -------------------------------------------------------------------------------- 1 | def eb = vertx.eventBus() 2 | 3 | eb.consumer("my-feed", { message -> 4 | println("MyConsumer.groovy received: ${message.body()}") 5 | }) 6 | 7 | -------------------------------------------------------------------------------- /4_eventbus/MyConsumer.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | import io.vertx.core.eventbus.Message; 3 | 4 | public class MyConsumer extends AbstractVerticle { 5 | @Override 6 | public void start() throws Exception { 7 | vertx.eventBus().consumer("my-feed").handler(this::myhandler); 8 | } // start 9 | private void myhandler(Message message) { 10 | String msg = message.body(); 11 | System.out.println("MyConsumer.java received: " + msg); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /4_eventbus/MyPublisher.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | import io.vertx.core.eventbus.Message; 3 | 4 | public class MyPublisher extends AbstractVerticle { 5 | @Override 6 | public void start() throws Exception { 7 | vertx.setPeriodic(1000, id -> { 8 | // This handler will get called every second 9 | String msg = "Java Now " + new java.util.Date(); 10 | System.out.println(msg); 11 | vertx.eventBus().publish("my-feed", msg); 12 | }); 13 | 14 | } // start 15 | } -------------------------------------------------------------------------------- /4_eventbus/cluster.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | false 7 | false 8 | false 9 | 0 10 | jdk 11 | 12 | 13 | 14 | 5701 15 | 16 | 20 | 0 21 | 22 | 23 | 24 | 224.2.2.3 25 | 54327 26 | 27 | 28 | 127.0.0.1 29 | 30 | 31 | 32 | 127.0.0.1 33 | 34 | 35 | 36 | 37 | 45 | PBEWithMD5AndDES 46 | 47 | thesalt 48 | 49 | thepass 50 | 51 | 19 52 | 53 | 54 | 55 | 56 | 16 57 | 58 | 0 59 | 60 | 61 | 62 | 67 | 1 68 | 74 | 0 75 | 81 | 0 82 | 89 | NONE 90 | 96 | 0 97 | 103 | 25 104 | 119 | com.hazelcast.map.merge.LatestUpdateMapMergePolicy 120 | 121 | 122 | 123 | 124 | 125 | 1 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /4_eventbus/myconsumer.js: -------------------------------------------------------------------------------- 1 | var eb = vertx.eventBus(); 2 | 3 | eb.consumer("my-feed", function (message) { 4 | console.log("myconsumer.js received: " + message.body()); 5 | }); 6 | 7 | 8 | -------------------------------------------------------------------------------- /4_eventbus/myconsumer.rb: -------------------------------------------------------------------------------- 1 | eb = $vertx.event_bus() 2 | 3 | eb.consumer("my-feed") { |message| 4 | puts "myconsumer.rb received: #{message.body()}" 5 | } 6 | -------------------------------------------------------------------------------- /4_eventbus/mypublisher.rb: -------------------------------------------------------------------------------- 1 | require "date" 2 | 3 | eb = $vertx.event_bus() 4 | 5 | $vertx.set_periodic(1000) { |v| 6 | msg = "Ruby Now " + DateTime.now.strftime("%H:%M:%S") 7 | puts(msg) 8 | eb.publish("my-feed", msg) 9 | } 10 | -------------------------------------------------------------------------------- /4_eventbus/readme.md: -------------------------------------------------------------------------------- 1 | Terminal Window 1: 2 | vertx run MyPublisher.java -cluster 3 | 4 | Terminal Window 2: 5 | vertx run MyConsumer.java -cluster 6 | 7 | Note: cluster.xml in the root folder, needed to make life easier on Mac OSX 8 | you might remove it from the directory 9 | 10 | High Availability (HA) 11 | In 3 different terminal windows: 12 | vertx run MyPublisher.java -ha 13 | vertx run MyConsumer.java -ha 14 | vertx run myconsumer.js -ha 15 | 16 | In a 4th terminal window: 17 | jps 18 | find the process id of a Launcher 19 | kill -9 65647 20 | http://screencast.com/t/O4uKMRdKveS 21 | 22 | and one of the remaining JVMs/nodes will start 23 | running the killed Verticle 24 | http://screencast.com/t/CdZdP9qD5T7m 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /5_browserbus/Server.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | import io.vertx.ext.web.Router; 3 | import io.vertx.ext.web.handler.StaticHandler; 4 | import io.vertx.ext.web.handler.sockjs.BridgeOptions; 5 | import io.vertx.ext.web.handler.sockjs.PermittedOptions; 6 | import io.vertx.ext.web.handler.sockjs.SockJSHandler; 7 | import io.vertx.ext.web.handler.sockjs.BridgeEventType; 8 | 9 | public class Server extends AbstractVerticle { 10 | @Override 11 | public void start() throws Exception { 12 | 13 | Router router = Router.router(vertx); 14 | 15 | BridgeOptions options = new BridgeOptions().addOutboundPermitted(new PermittedOptions().setAddress("my-feed")); 16 | router.route("/eventbus/*").handler(SockJSHandler.create(vertx).bridge(options, event -> { 17 | 18 | if (event.type() == BridgeEventType.SOCKET_CREATED) { 19 | System.out.println("A socket was created"); 20 | } 21 | event.complete(true); 22 | })); 23 | 24 | // static assets in local folder "webroot" 25 | // and available at http://localhost:8080/ 26 | router.route().handler(StaticHandler.create()); 27 | 28 | vertx.createHttpServer() 29 | .requestHandler(router::accept) 30 | .listen(8080); 31 | 32 | System.out.println("Everyting is non-blocking Async :-)"); 33 | 34 | vertx.setPeriodic(1000, t -> vertx.eventBus().publish("my-feed", "Server Now " + new java.util.Date())); 35 | 36 | } // start 37 | } -------------------------------------------------------------------------------- /5_browserbus/cluster.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | false 7 | false 8 | false 9 | 0 10 | jdk 11 | 12 | 13 | 14 | 5701 15 | 16 | 20 | 0 21 | 22 | 23 | 24 | 224.2.2.3 25 | 54327 26 | 27 | 28 | 127.0.0.1 29 | 30 | 31 | 32 | 127.0.0.1 33 | 34 | 35 | 36 | 37 | 45 | PBEWithMD5AndDES 46 | 47 | thesalt 48 | 49 | thepass 50 | 51 | 19 52 | 53 | 54 | 55 | 56 | 16 57 | 58 | 0 59 | 60 | 61 | 62 | 67 | 1 68 | 74 | 0 75 | 81 | 0 82 | 89 | NONE 90 | 96 | 0 97 | 103 | 25 104 | 119 | com.hazelcast.map.merge.LatestUpdateMapMergePolicy 120 | 121 | 122 | 123 | 124 | 125 | 1 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /5_browserbus/webroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Browser Vert.x Event Bus 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 |

Wassup!

17 | 18 |
Messages from Server
19 |
20 | 21 |
22 | 23 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /5_browserbus/webroot/vertx-eventbus.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2015 The original author or authors 3 | * ------------------------------------------------------ 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Apache License v2.0 which accompanies this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * 11 | * The Apache License v2.0 is available at 12 | * http://www.opensource.org/licenses/apache2.0.php 13 | * 14 | * You may elect to redistribute this code under either of these licenses. 15 | */ 16 | !function (factory) { 17 | if (typeof require === 'function' && typeof module !== 'undefined') { 18 | // CommonJS loader 19 | var SockJS = require('sockjs-client'); 20 | if(!SockJS) { 21 | throw new Error('vertx-eventbus.js requires sockjs-client, see http://sockjs.org'); 22 | } 23 | factory(SockJS); 24 | } else if (typeof define === 'function' && define.amd) { 25 | // AMD loader 26 | define('vertx-eventbus', ['sockjs'], factory); 27 | } else { 28 | // plain old include 29 | if (typeof this.SockJS === 'undefined') { 30 | throw new Error('vertx-eventbus.js requires sockjs-client, see http://sockjs.org'); 31 | } 32 | 33 | EventBus = factory(this.SockJS); 34 | } 35 | }(function (SockJS) { 36 | 37 | function makeUUID() { 38 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (a, b) { 39 | return b = Math.random() * 16, (a == 'y' ? b & 3 | 8 : b | 0).toString(16); 40 | }); 41 | } 42 | 43 | function mergeHeaders(defaultHeaders, headers) { 44 | if (defaultHeaders) { 45 | if(!headers) { 46 | return defaultHeaders; 47 | } 48 | 49 | for (var headerName in defaultHeaders) { 50 | if (defaultHeaders.hasOwnProperty(headerName)) { 51 | // user can overwrite the default headers 52 | if (typeof headers[headerName] === 'undefined') { 53 | headers[headerName] = defaultHeaders[headerName]; 54 | } 55 | } 56 | } 57 | } 58 | 59 | // headers are required to be a object 60 | return headers || {}; 61 | } 62 | 63 | /** 64 | * EventBus 65 | * 66 | * @param url 67 | * @param options 68 | * @constructor 69 | */ 70 | var EventBus = function (url, options) { 71 | var self = this; 72 | 73 | options = options || {}; 74 | 75 | var pingInterval = options.vertxbus_ping_interval || 5000; 76 | var pingTimerID; 77 | 78 | // attributes 79 | this.sockJSConn = new SockJS(url, null, options); 80 | this.state = EventBus.CONNECTING; 81 | this.handlers = {}; 82 | this.replyHandlers = {}; 83 | this.defaultHeaders = null; 84 | 85 | // default event handlers 86 | this.onerror = function (err) { 87 | try { 88 | console.error(err); 89 | } catch (e) { 90 | // dev tools are disabled so we cannot use console on IE 91 | } 92 | }; 93 | 94 | var sendPing = function () { 95 | self.sockJSConn.send(JSON.stringify({type: 'ping'})); 96 | }; 97 | 98 | this.sockJSConn.onopen = function () { 99 | // Send the first ping then send a ping every pingInterval milliseconds 100 | sendPing(); 101 | pingTimerID = setInterval(sendPing, pingInterval); 102 | self.state = EventBus.OPEN; 103 | self.onopen && self.onopen(); 104 | }; 105 | 106 | this.sockJSConn.onclose = function (e) { 107 | self.state = EventBus.CLOSED; 108 | if (pingTimerID) clearInterval(pingTimerID); 109 | self.onclose && self.onclose(e); 110 | }; 111 | 112 | this.sockJSConn.onmessage = function (e) { 113 | var json = JSON.parse(e.data); 114 | 115 | // define a reply function on the message itself 116 | if (json.replyAddress) { 117 | Object.defineProperty(json, 'reply', { 118 | value: function (message, headers, callback) { 119 | self.send(json.replyAddress, message, headers, callback); 120 | } 121 | }); 122 | } 123 | 124 | if (self.handlers[json.address]) { 125 | // iterate all registered handlers 126 | var handlers = self.handlers[json.address]; 127 | for (var i = 0; i < handlers.length; i++) { 128 | if (json.type === 'err') { 129 | handlers[i]({failureCode: json.failureCode, failureType: json.failureType, message: json.message}); 130 | } else { 131 | handlers[i](null, json); 132 | } 133 | } 134 | } else if (self.replyHandlers[json.address]) { 135 | // Might be a reply message 136 | var handler = self.replyHandlers[json.address]; 137 | delete self.replyHandlers[json.address]; 138 | if (json.type === 'err') { 139 | handler({failureCode: json.failureCode, failureType: json.failureType, message: json.message}); 140 | } else { 141 | handler(null, json); 142 | } 143 | } else { 144 | if (json.type === 'err') { 145 | self.onerror(json); 146 | } else { 147 | try { 148 | console.warn('No handler found for message: ', json); 149 | } catch (e) { 150 | // dev tools are disabled so we cannot use console on IE 151 | } 152 | } 153 | } 154 | } 155 | }; 156 | 157 | /** 158 | * Send a message 159 | * 160 | * @param {String} address 161 | * @param {Object} message 162 | * @param {Object} [headers] 163 | * @param {Function} [callback] 164 | */ 165 | EventBus.prototype.send = function (address, message, headers, callback) { 166 | // are we ready? 167 | if (this.state != EventBus.OPEN) { 168 | throw new Error('INVALID_STATE_ERR'); 169 | } 170 | 171 | if (typeof headers === 'function') { 172 | callback = headers; 173 | headers = {}; 174 | } 175 | 176 | var envelope = { 177 | type: 'send', 178 | address: address, 179 | headers: mergeHeaders(this.defaultHeaders, headers), 180 | body: message 181 | }; 182 | 183 | if (callback) { 184 | var replyAddress = makeUUID(); 185 | envelope.replyAddress = replyAddress; 186 | this.replyHandlers[replyAddress] = callback; 187 | } 188 | 189 | this.sockJSConn.send(JSON.stringify(envelope)); 190 | }; 191 | 192 | /** 193 | * Publish a message 194 | * 195 | * @param {String} address 196 | * @param {Object} message 197 | * @param {Object} [headers] 198 | */ 199 | EventBus.prototype.publish = function (address, message, headers) { 200 | // are we ready? 201 | if (this.state != EventBus.OPEN) { 202 | throw new Error('INVALID_STATE_ERR'); 203 | } 204 | 205 | this.sockJSConn.send(JSON.stringify({ 206 | type: 'publish', 207 | address: address, 208 | headers: mergeHeaders(this.defaultHeaders, headers), 209 | body: message 210 | })); 211 | }; 212 | 213 | /** 214 | * Register a new handler 215 | * 216 | * @param {String} address 217 | * @param {Object} [headers] 218 | * @param {Function} callback 219 | */ 220 | EventBus.prototype.registerHandler = function (address, headers, callback) { 221 | // are we ready? 222 | if (this.state != EventBus.OPEN) { 223 | throw new Error('INVALID_STATE_ERR'); 224 | } 225 | 226 | if (typeof headers === 'function') { 227 | callback = headers; 228 | headers = {}; 229 | } 230 | 231 | // ensure it is an array 232 | if (!this.handlers[address]) { 233 | this.handlers[address] = []; 234 | // First handler for this address so we should register the connection 235 | this.sockJSConn.send(JSON.stringify({ 236 | type: 'register', 237 | address: address, 238 | headers: mergeHeaders(this.defaultHeaders, headers) 239 | })); 240 | } 241 | 242 | this.handlers[address].push(callback); 243 | }; 244 | 245 | /** 246 | * Unregister a handler 247 | * 248 | * @param {String} address 249 | * @param {Object} [headers] 250 | * @param {Function} callback 251 | */ 252 | EventBus.prototype.unregisterHandler = function (address, headers, callback) { 253 | // are we ready? 254 | if (this.state != EventBus.OPEN) { 255 | throw new Error('INVALID_STATE_ERR'); 256 | } 257 | 258 | var handlers = this.handlers[address]; 259 | 260 | if (handlers) { 261 | 262 | if (typeof headers === 'function') { 263 | callback = headers; 264 | headers = {}; 265 | } 266 | 267 | var idx = handlers.indexOf(callback); 268 | if (idx != -1) { 269 | handlers.splice(idx, 1); 270 | if (handlers.length === 0) { 271 | // No more local handlers so we should unregister the connection 272 | this.sockJSConn.send(JSON.stringify({ 273 | type: 'unregister', 274 | address: address, 275 | headers: mergeHeaders(this.defaultHeaders, headers) 276 | })); 277 | 278 | delete this.handlers[address]; 279 | } 280 | } 281 | } 282 | }; 283 | 284 | /** 285 | * Closes the connection to the EvenBus Bridge. 286 | */ 287 | EventBus.prototype.close = function () { 288 | this.state = EventBus.CLOSING; 289 | this.sockJSConn.close(); 290 | }; 291 | 292 | EventBus.CONNECTING = 0; 293 | EventBus.OPEN = 1; 294 | EventBus.CLOSING = 2; 295 | EventBus.CLOSED = 3; 296 | 297 | if (typeof exports !== 'undefined') { 298 | if (typeof module !== 'undefined' && module.exports) { 299 | exports = module.exports = EventBus; 300 | } else { 301 | exports.EventBus = EventBus; 302 | } 303 | } else { 304 | return EventBus; 305 | } 306 | }); -------------------------------------------------------------------------------- /6_circuitbreaker/BadBadVerticle.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | import io.vertx.core.eventbus.Message; 3 | 4 | public class BadBadVerticle extends AbstractVerticle { 5 | @Override 6 | public void start() throws Exception { 7 | vertx.eventBus().consumer("callmemaybe").handler(this::myhandler); 8 | } // start 9 | 10 | private void myhandler(Message message) { 11 | String msg = message.body(); 12 | System.out.println("Received: " + msg); 13 | System.out.println("Going to Sleep " + new java.util.Date()); 14 | try { 15 | Thread.sleep(5000); // NEVER DO THIS :-) 16 | System.out.println("Waking from Sleep " + new java.util.Date()); 17 | // another way to break things is to never reply 18 | // just comment out the line below 19 | message.reply(message.body() + " OUTPUT"); 20 | } catch (InterruptedException e) { 21 | System.err.println(e); 22 | } 23 | } // myHandler 24 | 25 | } -------------------------------------------------------------------------------- /6_circuitbreaker/InvokerProtected.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | import io.vertx.circuitbreaker.CircuitBreaker; 3 | import io.vertx.circuitbreaker.CircuitBreakerOptions; 4 | import io.vertx.core.Future; 5 | 6 | 7 | public class InvokerProtected extends AbstractVerticle { 8 | @Override 9 | public void start() throws Exception { 10 | /* 11 | vertx.setPeriodic(1000, id -> { 12 | // This handler will get called every second 13 | String msg = "Java Now " + new java.util.Date(); 14 | System.out.println(msg); 15 | }); // setPeriodic 16 | */ 17 | CircuitBreakerOptions options = new CircuitBreakerOptions() 18 | .setMaxFailures(1) 19 | .setTimeout(2000) 20 | .setFallbackOnFailure(true); 21 | 22 | CircuitBreaker breaker = CircuitBreaker.create( 23 | "my-breaker", vertx, options 24 | ); 25 | vertx.setPeriodic(1000, v -> { 26 | Future result = breaker.executeWithFallback( 27 | future -> { 28 | System.out.println("Calling..."); 29 | vertx.eventBus().send("callmemaybe", "INPUT", response -> { 30 | if (response.failed()) { 31 | future.fail(response.cause()); 32 | } else { 33 | System.out.println("Else: " + response.result().body()); 34 | if (! future.isComplete()) { 35 | future.complete(); 36 | } // if 37 | } // else 38 | }); 39 | }, v -> { 40 | return "Fallback"; 41 | }); 42 | result.setHandler(ar -> { 43 | // Do something with the result 44 | System.out.println("Result: " + ar.result()); 45 | }); 46 | }); // setPeriodic 47 | } // start 48 | } -------------------------------------------------------------------------------- /6_circuitbreaker/InvokerUnprotected.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | 3 | public class InvokerUnprotected extends AbstractVerticle { 4 | @Override 5 | public void start() throws Exception { 6 | String msg = "INPUT"; 7 | 8 | vertx.setPeriodic(1000, v -> { 9 | System.out.println("Calling..."); 10 | vertx.eventBus().send("callmemaybe", msg, reply -> { 11 | if (reply.succeeded()) { 12 | System.out.println("Received reply " + reply.result().body()); 13 | } else { 14 | System.out.println("No reply"); 15 | } 16 | }); // send 17 | }); // setPeriodic 18 | } // start 19 | } -------------------------------------------------------------------------------- /6_circuitbreaker/cluster.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | false 7 | false 8 | false 9 | 0 10 | jdk 11 | 12 | 13 | 14 | 5701 15 | 16 | 20 | 0 21 | 22 | 23 | 24 | 224.2.2.3 25 | 54327 26 | 27 | 28 | 127.0.0.1 29 | 30 | 31 | 32 | 127.0.0.1 33 | 34 | 35 | 36 | 37 | 45 | PBEWithMD5AndDES 46 | 47 | thesalt 48 | 49 | thepass 50 | 51 | 19 52 | 53 | 54 | 55 | 56 | 16 57 | 58 | 0 59 | 60 | 61 | 62 | 67 | 1 68 | 74 | 0 75 | 81 | 0 82 | 89 | NONE 90 | 96 | 0 97 | 103 | 25 104 | 119 | com.hazelcast.map.merge.LatestUpdateMapMergePolicy 120 | 121 | 122 | 123 | 124 | 125 | 1 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /7_httpinvoker/Client.java: -------------------------------------------------------------------------------- 1 | 2 | import io.vertx.circuitbreaker.CircuitBreaker; 3 | import io.vertx.circuitbreaker.CircuitBreakerOptions; 4 | import io.vertx.core.AbstractVerticle; 5 | import io.vertx.core.Future; 6 | import io.vertx.core.Launcher; 7 | 8 | 9 | public class Client extends AbstractVerticle { 10 | 11 | @Override 12 | public void start() { 13 | CircuitBreakerOptions options = new CircuitBreakerOptions() 14 | .setMaxFailures(5) 15 | .setTimeout(5000) 16 | .setFallbackOnFailure(true); 17 | 18 | CircuitBreaker breaker = 19 | CircuitBreaker.create("my-circuit-breaker", vertx, options) 20 | .openHandler(v -> { 21 | System.out.println("Circuit opened"); 22 | }).closeHandler(v -> { 23 | System.out.println("Circuit closed"); 24 | }); 25 | 26 | Future result = breaker.executeWithFallback(future -> { 27 | vertx.createHttpClient().getNow(8080, "localhost", "/", response -> { 28 | if (response.statusCode() != 200) { 29 | future.fail("HTTP error"); 30 | } else { 31 | response.exceptionHandler(future::fail).bodyHandler(buffer -> { 32 | future.complete(buffer.toString()); 33 | }); 34 | } 35 | }); 36 | }, v -> { 37 | // Executed when the circuit is opened 38 | return "Hello (fallback)"; 39 | }); 40 | 41 | result.setHandler(ar -> { 42 | // Do something with the result 43 | System.out.println("Result: " + ar.result()); 44 | }); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /7_httpinvoker/Server.java: -------------------------------------------------------------------------------- 1 | import io.vertx.core.AbstractVerticle; 2 | import io.vertx.core.Launcher; 3 | 4 | public class Server extends AbstractVerticle { 5 | 6 | @Override 7 | public void start() { 8 | vertx.createHttpServer() 9 | .requestHandler(req -> req.response().end("Bonjour")) 10 | .listen(8080); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /7_httpinvoker/cluster.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | false 7 | false 8 | false 9 | 0 10 | jdk 11 | 12 | 13 | 14 | 5701 15 | 16 | 20 | 0 21 | 22 | 23 | 24 | 224.2.2.3 25 | 54327 26 | 27 | 28 | 127.0.0.1 29 | 30 | 31 | 32 | 127.0.0.1 33 | 34 | 35 | 36 | 37 | 45 | PBEWithMD5AndDES 46 | 47 | thesalt 48 | 49 | thepass 50 | 51 | 19 52 | 53 | 54 | 55 | 56 | 16 57 | 58 | 0 59 | 60 | 61 | 62 | 67 | 1 68 | 74 | 0 75 | 81 | 0 82 | 89 | NONE 90 | 96 | 0 97 | 103 | 25 104 | 119 | com.hazelcast.map.merge.LatestUpdateMapMergePolicy 120 | 121 | 122 | 123 | 124 | 125 | 1 126 | 127 | 128 | 129 | --------------------------------------------------------------------------------