├── .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 | 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 | } --------------------------------------------------------------------------------