├── .editorconfig
├── .gitignore
├── README.adoc
├── pom.xml
├── redeploy.bat
├── redeploy.sh
└── src
├── main
├── conf
│ └── config.json
├── java
│ └── com
│ │ └── tidyjava
│ │ └── example
│ │ ├── ActivityModule.java
│ │ ├── MainVerticle.java
│ │ ├── callback
│ │ └── Callback.java
│ │ ├── entities
│ │ ├── Activity.java
│ │ └── Entity.java
│ │ ├── gateways
│ │ ├── ActivityGateway.java
│ │ └── ActivityGatewayImpl.java
│ │ └── usecases
│ │ └── listActivities
│ │ ├── ActivityDetails.java
│ │ ├── ListActivitiesInputBoundary.java
│ │ ├── ListActivitiesOutputBoundary.java
│ │ ├── ListActivitiesUseCase.java
│ │ └── ListActivitiesView.java
└── resources
│ └── templates
│ └── index.ftl
└── test
└── java
└── com
└── tidyjava
└── example
└── MainVerticleTest.java
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 | trim_trailing_whitespace = true
8 | end_of_line = lf
9 | insert_final_newline = true
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | pom.xml.tag
3 | pom.xml.releaseBackup
4 | pom.xml.versionsBackup
5 | pom.xml.next
6 | release.properties
7 | dependency-reduced-pom.xml
8 | buildNumber.properties
9 | .mvn/timing.properties
10 | .idea
11 | .vertx
--------------------------------------------------------------------------------
/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/vert-x3/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 | curl http://vertx.io/assets/starter-scripts/create-vertx-project-maven.sh -o vertx-create-maven-project.sh; bash vertx-create-maven-project.sh
26 | ----
27 |
28 | == Running the project
29 |
30 | Once you have retrieved the project, you can check that everything works with:
31 |
32 | [source]
33 | ----
34 | mvn test exec:java
35 | ----
36 |
37 | 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.
38 |
39 | == Anatomy of the project
40 |
41 | The project contains:
42 |
43 | * a `pom.xml` file
44 | * a _main_ verticle file (src/main/java/io/vertx/starter/MainVerticle.java)
45 | * an unit test (src/main/test/io/vertx/starter/MainVerticleTest.java)
46 |
47 | == Start to hack
48 |
49 | 1. Delete the `.git` directory
50 | 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.
51 | 3. Run `redeploy.sh` (or `redeploy.bat` on Windows) and the project recompiles while editing.
52 |
53 | NOTE: the `redeploy` script are also configurable
54 |
55 | == Building the project
56 |
57 | To build the project, just use:
58 |
59 | ----
60 | mvn clean package
61 | ----
62 |
63 | It generates a _fat-jar_ in the `target` directory.
64 |
--------------------------------------------------------------------------------
/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.4.0
14 | com.tidyjava.example.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 | com.google.inject
32 | guice
33 | 4.1.0
34 |
35 |
36 | io.vertx
37 | vertx-core
38 |
39 |
40 | io.vertx
41 | vertx-web
42 |
43 |
44 | io.vertx
45 | vertx-web-templ-freemarker
46 | shaded
47 |
48 |
49 | io.vertx
50 | vertx-jdbc-client
51 |
52 |
53 | com.h2database
54 | h2
55 | 1.4.193
56 |
57 |
58 | junit
59 | junit
60 | 4.12
61 | test
62 |
63 |
64 | io.vertx
65 | vertx-unit
66 | test
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | maven-compiler-plugin
75 | 3.5.1
76 |
77 | 1.8
78 | 1.8
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | org.apache.maven.plugins
87 | maven-shade-plugin
88 | 2.4.3
89 |
90 |
91 | package
92 |
93 | shade
94 |
95 |
96 |
97 |
99 |
100 | io.vertx.core.Launcher
101 | ${main.verticle}
102 |
103 |
104 |
106 | META-INF/services/io.vertx.core.spi.VerticleFactory
107 |
108 |
109 |
110 |
111 | ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | org.codehaus.mojo
120 | exec-maven-plugin
121 | 1.5.0
122 |
123 | io.vertx.core.Launcher
124 |
125 | run
126 | ${main.verticle}
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/redeploy.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | SET LAUNCHER="io.vertx.core.Launcher"
4 | SET VERTICLE="com.tidyjava.example.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 |
--------------------------------------------------------------------------------
/redeploy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export LAUNCHER="io.vertx.core.Launcher"
4 | export VERTICLE="com.tidyjava.example.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 |
--------------------------------------------------------------------------------
/src/main/conf/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "url": "jdbc:h2:mem:test",
3 | "driver_class": "org.h2.Driver"
4 | }
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/ActivityModule.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example;
2 |
3 | import com.google.inject.AbstractModule;
4 | import com.tidyjava.example.gateways.ActivityGateway;
5 | import com.tidyjava.example.gateways.ActivityGatewayImpl;
6 | import com.tidyjava.example.usecases.listActivities.ListActivitiesInputBoundary;
7 | import com.tidyjava.example.usecases.listActivities.ListActivitiesUseCase;
8 | import io.vertx.core.Vertx;
9 | import io.vertx.core.json.JsonObject;
10 | import io.vertx.ext.jdbc.JDBCClient;
11 |
12 | public class ActivityModule extends AbstractModule {
13 | private final Vertx vertx;
14 | private final JsonObject config;
15 |
16 | public ActivityModule(Vertx vertx, JsonObject config) {
17 | this.vertx = vertx;
18 | this.config = config;
19 | }
20 |
21 | @Override
22 | protected void configure() {
23 | bind(JDBCClient.class)
24 | .toInstance(JDBCClient.createShared(vertx, config));
25 | bind(ActivityGateway.class)
26 | .to(ActivityGatewayImpl.class);
27 | bind(ListActivitiesInputBoundary.class)
28 | .to(ListActivitiesUseCase.class);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/MainVerticle.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example;
2 |
3 | import com.google.inject.Guice;
4 | import com.google.inject.Injector;
5 | import com.tidyjava.example.usecases.listActivities.ListActivitiesInputBoundary;
6 | import com.tidyjava.example.usecases.listActivities.ListActivitiesUseCase;
7 | import com.tidyjava.example.usecases.listActivities.ListActivitiesView;
8 | import io.vertx.core.AbstractVerticle;
9 | import io.vertx.ext.jdbc.JDBCClient;
10 | import io.vertx.ext.sql.SQLConnection;
11 | import io.vertx.ext.web.Router;
12 |
13 | public class MainVerticle extends AbstractVerticle {
14 |
15 | @Override
16 | public void start() {
17 | initDatabase();
18 |
19 | Router router = Router.router(vertx);
20 | Injector injector = Guice.createInjector(new ActivityModule(vertx, config()));
21 |
22 | ListActivitiesInputBoundary listActivitiesUseCase = injector.getInstance(ListActivitiesUseCase.class);
23 | router.get().handler(ctx -> {
24 | ListActivitiesView view = new ListActivitiesView(ctx);
25 | listActivitiesUseCase.listActivities(view);
26 | });
27 |
28 | vertx.createHttpServer()
29 | .requestHandler(router::accept)
30 | .listen(8080);
31 | }
32 |
33 | private void initDatabase() {
34 | JDBCClient client = JDBCClient.createShared(vertx, config());
35 |
36 | client.getConnection(res -> {
37 | if (res.succeeded()) {
38 | SQLConnection connection = res.result();
39 | connection.update("CREATE TABLE ACTIVITIES(ID VARCHAR(255) PRIMARY KEY, NAME VARCHAR(255));", upres -> {
40 | if (upres.succeeded()) {
41 | System.out.println("Success 1!");
42 | } else {
43 | System.out.println("Almost 1!");
44 | }
45 | });
46 | connection.update("INSERT INTO ACTIVITIES(id, name) VALUES ('id1', 'name1');", upres -> {
47 | if (upres.succeeded()) {
48 | System.out.println("Success 2!");
49 | } else {
50 | System.out.println("Almost 2!");
51 | }
52 | });
53 | } else {
54 | System.out.println("Holy Moly!");
55 | }
56 | });
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/callback/Callback.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.callback;
2 |
3 | import java.util.function.Consumer;
4 |
5 | public interface Callback {
6 |
7 | static Callback of(Consumer success, Consumer failure) {
8 | return new DelegatingCallback<>(success, failure);
9 | }
10 |
11 | void success(T t);
12 |
13 | void failure(Throwable throwable);
14 |
15 | class DelegatingCallback implements Callback {
16 | private final Consumer success;
17 | private final Consumer failure;
18 |
19 | private DelegatingCallback(Consumer success, Consumer failure) {
20 | this.success = success;
21 | this.failure = failure;
22 | }
23 |
24 | @Override
25 | public void success(T t) {
26 | success.accept(t);
27 | }
28 |
29 | @Override
30 | public void failure(Throwable throwable) {
31 | failure.accept(throwable);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/entities/Activity.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.entities;
2 |
3 | public class Activity extends Entity {
4 | private String name;
5 |
6 | public String getName() {
7 | return name;
8 | }
9 |
10 | public void setName(String name) {
11 | this.name = name;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/entities/Entity.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.entities;
2 |
3 | public class Entity {
4 | private String id;
5 |
6 | public String getId() {
7 | return id;
8 | }
9 |
10 | public void setId(String id) {
11 | this.id = id;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/gateways/ActivityGateway.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.gateways;
2 |
3 | import com.tidyjava.example.callback.Callback;
4 | import com.tidyjava.example.entities.Activity;
5 |
6 | import java.util.List;
7 |
8 | public interface ActivityGateway {
9 | void findAll(Callback> callback);
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/gateways/ActivityGatewayImpl.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.gateways;
2 |
3 | import com.tidyjava.example.callback.Callback;
4 | import com.tidyjava.example.entities.Activity;
5 | import io.vertx.core.json.JsonObject;
6 | import io.vertx.ext.jdbc.JDBCClient;
7 | import io.vertx.ext.sql.SQLConnection;
8 |
9 | import javax.inject.Inject;
10 | import java.util.List;
11 | import java.util.function.Consumer;
12 | import java.util.stream.Collectors;
13 |
14 | public class ActivityGatewayImpl implements ActivityGateway {
15 | private JDBCClient jdbcClient;
16 |
17 | @Inject
18 | public ActivityGatewayImpl(JDBCClient jdbcClient) {
19 | this.jdbcClient = jdbcClient;
20 | }
21 |
22 | @Override
23 | public void findAll(Callback> callback) {
24 | getConnection(connection -> connection.query("SELECT * FROM Activities;", asyncRs -> {
25 | if (asyncRs.succeeded()) {
26 | List activities = asyncRs.result()
27 | .getRows()
28 | .stream()
29 | .map(this::toActivity)
30 | .collect(Collectors.toList());
31 |
32 | callback.success(activities);
33 | } else {
34 | callback.failure(asyncRs.cause());
35 | }
36 | }), callback::failure);
37 | }
38 |
39 | private void getConnection(Consumer sqlConnectionConsumer, Consumer onFailure) {
40 | jdbcClient.getConnection(asyncConn -> {
41 | if (asyncConn.succeeded()) {
42 | SQLConnection connection = asyncConn.result();
43 | sqlConnectionConsumer.accept(connection);
44 | connection.close();
45 | } else {
46 | onFailure.accept(asyncConn.cause());
47 | }
48 | });
49 | }
50 |
51 | private Activity toActivity(JsonObject row) {
52 | Activity activity = new Activity();
53 | activity.setId(row.getString("ID"));
54 | activity.setName(row.getString("NAME"));
55 | return activity;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/usecases/listActivities/ActivityDetails.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.usecases.listActivities;
2 |
3 | public class ActivityDetails {
4 | private String name;
5 |
6 | public ActivityDetails(String name) {
7 | this.name = name;
8 | }
9 |
10 | public String getName() {
11 | return name;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/usecases/listActivities/ListActivitiesInputBoundary.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.usecases.listActivities;
2 |
3 | public interface ListActivitiesInputBoundary {
4 | void listActivities(ListActivitiesOutputBoundary presenter);
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/usecases/listActivities/ListActivitiesOutputBoundary.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.usecases.listActivities;
2 |
3 | import com.tidyjava.example.callback.Callback;
4 |
5 | import java.util.List;
6 |
7 | public interface ListActivitiesOutputBoundary extends Callback> {
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/usecases/listActivities/ListActivitiesUseCase.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.usecases.listActivities;
2 |
3 | import com.tidyjava.example.callback.Callback;
4 | import com.tidyjava.example.entities.Activity;
5 | import com.tidyjava.example.gateways.ActivityGateway;
6 |
7 | import javax.inject.Inject;
8 | import java.util.List;
9 | import java.util.stream.Collectors;
10 |
11 | public class ListActivitiesUseCase implements ListActivitiesInputBoundary {
12 | private final ActivityGateway activityGateway;
13 |
14 | @Inject
15 | public ListActivitiesUseCase(ActivityGateway activityGateway) {
16 | this.activityGateway = activityGateway;
17 | }
18 |
19 | @Override
20 | public void listActivities(ListActivitiesOutputBoundary presenter) {
21 | activityGateway.findAll(Callback.of(
22 | activities -> presenter.success(toResponseModel(activities)),
23 | presenter::failure));
24 | }
25 |
26 | private List toResponseModel(List activities) {
27 | return activities
28 | .stream()
29 | .map(Activity::getName)
30 | .map(ActivityDetails::new)
31 | .collect(Collectors.toList());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/tidyjava/example/usecases/listActivities/ListActivitiesView.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example.usecases.listActivities;
2 |
3 | import io.vertx.ext.web.RoutingContext;
4 | import io.vertx.ext.web.templ.FreeMarkerTemplateEngine;
5 |
6 | import java.util.List;
7 |
8 | public class ListActivitiesView implements ListActivitiesOutputBoundary {
9 | private final RoutingContext ctx;
10 |
11 | public ListActivitiesView(RoutingContext ctx) {
12 | this.ctx = ctx;
13 | }
14 |
15 | @Override
16 | public void success(List activityDetailsList) {
17 | FreeMarkerTemplateEngine engine = FreeMarkerTemplateEngine.create();
18 |
19 | ctx.put("activities", activityDetailsList);
20 |
21 | engine.render(ctx, "templates/index.ftl", res -> {
22 | if (res.succeeded()) {
23 | ctx.response().end(res.result());
24 | } else {
25 | ctx.fail(res.cause());
26 | }
27 | });
28 | }
29 |
30 | @Override
31 | public void failure(Throwable throwable) {
32 | ctx.fail(throwable);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/resources/templates/index.ftl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello World!
6 |
7 |
8 | <#list context.activities as activity>
9 | ${activity.name}
10 | #list>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/test/java/com/tidyjava/example/MainVerticleTest.java:
--------------------------------------------------------------------------------
1 | package com.tidyjava.example;
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 | }
--------------------------------------------------------------------------------