├── .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 |
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 |
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 |
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 |
122 |
123 |
124 |
125 | 1
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------