diff --git a/README.md b/README.md index ecc73122..3fef2f41 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ You can provide the following query parameters to customize the project - `vertxDependencies`: a comma separated list of artifactIds of the vert.x modules - `packageName`: code package name, derived from `groupId` and `artifactId` by default - `jdkVersion`: which version of the JDK to use, defaults to `1.8` +- `flavor`: `vert.x` or `mutiny`, defaults to `vert.x` Full example: diff --git a/src/main/java/io/vertx/starter/ValidationHandler.java b/src/main/java/io/vertx/starter/ValidationHandler.java index 79a5eb9b..768e6881 100644 --- a/src/main/java/io/vertx/starter/ValidationHandler.java +++ b/src/main/java/io/vertx/starter/ValidationHandler.java @@ -43,7 +43,8 @@ public class ValidationHandler implements Handler { private final JsonObject defaults; private final Set versions; private final Map> exclusions; - private final Set dependencies; + private final Map vertxStackDependencies; + private final Map mutinyStackDependencies; public ValidationHandler(JsonObject defaults, JsonArray versions, JsonArray stack) { this.defaults = defaults; @@ -57,12 +58,27 @@ public ValidationHandler(JsonObject defaults, JsonArray versions, JsonArray stac obj -> obj.getString("number"), obj -> obj.getJsonArray("exclusions", new JsonArray()).stream().map(String.class::cast).collect(toList())) ); - dependencies = stack.stream() + vertxStackDependencies = stack.stream() .map(JsonObject.class::cast) .flatMap(category -> category.getJsonArray("items").stream()) .map(JsonObject.class::cast) - .map(item -> item.getString("artifactId")) - .collect(toSet()); + .collect(toMap( + item -> item.getString("artifactId"), + item -> new Dependency() + .setGroupId(item.getString("groupId")) + .setArtifactId(item.getString("artifactId"))) + ); + mutinyStackDependencies = stack.stream() + .map(JsonObject.class::cast) + .flatMap(category -> category.getJsonArray("items").stream()) + .map(JsonObject.class::cast) + .filter(item -> item.getBoolean("mutinyBindings")) + .collect(toMap( + item -> item.getString("artifactId"), + item -> new Dependency() + .setGroupId("io.smallrye.reactive") + .setArtifactId("smallrye-mutiny-" + item.getString("artifactId"))) + ); } @Override @@ -86,6 +102,10 @@ public void handle(RoutingContext rc) { return; } + if (!validateAndSetEnum(rc, FLAVOR, ProjectFlavor::fromId, vertxProject::setFlavor)) { + return; + } + String vertxVersion = getQueryParam(rc, VERTX_VERSION); if (isNotBlank(vertxVersion)) { if (!versions.contains(vertxVersion)) { @@ -103,8 +123,26 @@ public void handle(RoutingContext rc) { .map(String::toLowerCase) .collect(toSet()); - if (!dependencies.containsAll(vertxDependencies) || - !Collections.disjoint(exclusions.get(vertxProject.getVertxVersion()), vertxDependencies)) { + Set unsatisfiableDependencies; + if (vertxProject.getFlavor() == ProjectFlavor.VERTX) { + unsatisfiableDependencies = vertxDependencies.stream() + .filter(dependency -> !vertxStackDependencies.containsKey(dependency)) + .collect(toSet()); + } else if (vertxProject.getFlavor() == ProjectFlavor.MUTINY) { + unsatisfiableDependencies = vertxDependencies.stream() + .filter(artifactId -> !isArtifactAvailableForMutinyFlavor(artifactId)) + .collect(toSet()); + } else { + throw new IllegalArgumentException("There's no stack for flavor " + vertxProject.getFlavor()); + } + + if (!unsatisfiableDependencies.isEmpty()) { + String capitalizedProjectFlavor = vertxProject.getFlavor().capitalizedId(); + String message = "The following artifacts are not available for the Vert.x API '" + capitalizedProjectFlavor + "': " + unsatisfiableDependencies; + WebVerticle.fail(rc, 400, message); + } + + if (!Collections.disjoint(exclusions.get(vertxProject.getVertxVersion()), vertxDependencies)) { fail(rc, VERTX_DEPENDENCIES, deps); return; } @@ -114,7 +152,25 @@ public void handle(RoutingContext rc) { return; } - vertxProject.setVertxDependencies(vertxDependencies); + Set flavoredDependencies; + if (vertxProject.getFlavor() == ProjectFlavor.VERTX) { + flavoredDependencies = vertxDependencies.stream() + .map(vertxStackDependencies::get) + .collect(toSet()); + } else if (vertxProject.getFlavor() == ProjectFlavor.MUTINY) { + flavoredDependencies = vertxDependencies.stream() + .map(dependency -> mutinyStackDependencies.keySet().stream() + .filter(mutinyDependency -> mutinyDependency.endsWith(dependency)) + .findFirst()) + .filter(Optional::isPresent) + .map(Optional::get) + .map(mutinyStackDependencies::get) + .collect(toSet()); + } else { + throw new IllegalArgumentException("Unknown project flavor " + vertxProject.getFlavor()); + } + + vertxProject.setVertxDependencies(flavoredDependencies); } ArchiveFormat archiveFormat = ArchiveFormat.fromFilename(rc.request().path()); @@ -141,6 +197,11 @@ public void handle(RoutingContext rc) { rc.next(); } + private boolean isArtifactAvailableForMutinyFlavor(String artifactId) { + return mutinyStackDependencies.keySet().stream() + .anyMatch(dependency -> dependency.endsWith(artifactId)); + } + private boolean validateAndSetId(RoutingContext rc, String name, Consumer setter) { String value = getQueryParam(rc, name); if (isNotBlank(value)) { diff --git a/src/main/java/io/vertx/starter/config/ProjectConstants.java b/src/main/java/io/vertx/starter/config/ProjectConstants.java index 13d2192f..c9e36ad6 100644 --- a/src/main/java/io/vertx/starter/config/ProjectConstants.java +++ b/src/main/java/io/vertx/starter/config/ProjectConstants.java @@ -29,4 +29,5 @@ public interface ProjectConstants { String ARCHIVE_FORMAT = "archiveFormat"; String PACKAGE_NAME = "packageName"; String JDK_VERSION = "jdkVersion"; + String FLAVOR = "flavor"; } diff --git a/src/main/java/io/vertx/starter/model/Dependency.java b/src/main/java/io/vertx/starter/model/Dependency.java new file mode 100644 index 00000000..5a1e3c81 --- /dev/null +++ b/src/main/java/io/vertx/starter/model/Dependency.java @@ -0,0 +1,54 @@ +package io.vertx.starter.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.util.Objects; + +public class Dependency { + private String groupId; + private String artifactId; + + public String getGroupId() { + return groupId; + } + + public Dependency setGroupId(String groupId) { + this.groupId = groupId; + return this; + } + + public String getArtifactId() { + return artifactId; + } + + public Dependency setArtifactId(String artifactId) { + this.artifactId = artifactId; + return this; + } + + @JsonIgnore + public boolean isVertxDependency() { + return ProjectFlavor.VERTX.getGroupId().equals(groupId); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Dependency that = (Dependency) o; + return Objects.equals(groupId, that.groupId) && Objects.equals(artifactId, that.artifactId); + } + + @Override + public int hashCode() { + return Objects.hash(groupId, artifactId); + } + + @Override + public String toString() { + return "Dependency{" + + "groupId='" + groupId + '\'' + + ", artifactId='" + artifactId + '\'' + + '}'; + } +} diff --git a/src/main/java/io/vertx/starter/model/ProjectFlavor.java b/src/main/java/io/vertx/starter/model/ProjectFlavor.java new file mode 100644 index 00000000..98b30fd7 --- /dev/null +++ b/src/main/java/io/vertx/starter/model/ProjectFlavor.java @@ -0,0 +1,44 @@ +package io.vertx.starter.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Locale; + +public enum ProjectFlavor { + VERTX("vert.x", "io.vertx"), + MUTINY("mutiny", "io.smallrye.reactive"); + + private final String id; + private final String groupId; + + ProjectFlavor(String id, String groupId) { + this.id = id; + this.groupId = groupId; + } + + @JsonValue + public String getId() { + return id; + } + + public String getGroupId() { + return groupId; + } + + @JsonIgnore + public String capitalizedId() { + return id.substring(0, 1).toUpperCase(Locale.ROOT) + id.substring(1); + } + + public static ProjectFlavor fromId(String id) { + switch (id.toLowerCase(Locale.ROOT)) { + case "mutiny": + return MUTINY; + case "vert.x": + return VERTX; + default: + return null; + } + } +} diff --git a/src/main/java/io/vertx/starter/model/VertxProject.java b/src/main/java/io/vertx/starter/model/VertxProject.java index 82e288e3..858579c9 100644 --- a/src/main/java/io/vertx/starter/model/VertxProject.java +++ b/src/main/java/io/vertx/starter/model/VertxProject.java @@ -27,12 +27,13 @@ public class VertxProject { private Language language; private BuildTool buildTool; private String vertxVersion; - private Set vertxDependencies; + private Set vertxDependencies; private ArchiveFormat archiveFormat; private String packageName; private JdkVersion jdkVersion; private String operatingSystem; private Instant createdOn; + private ProjectFlavor flavor; public String getId() { return id; @@ -88,11 +89,11 @@ public VertxProject setVertxVersion(String vertxVersion) { return this; } - public Set getVertxDependencies() { + public Set getVertxDependencies() { return vertxDependencies; } - public VertxProject setVertxDependencies(Set vertxDependencies) { + public VertxProject setVertxDependencies(Set vertxDependencies) { this.vertxDependencies = vertxDependencies; return this; } @@ -142,6 +143,15 @@ public VertxProject setCreatedOn(Instant createdOn) { return this; } + public ProjectFlavor getFlavor() { + return flavor; + } + + public VertxProject setFlavor(ProjectFlavor flavor) { + this.flavor = flavor; + return this; + } + @Override public String toString() { // DO NOT RETURN USER RELATED-DATA (groupId, artifactId, packageName) @@ -155,6 +165,7 @@ public String toString() { ", jdkVersion=" + jdkVersion + ", operatingSystem=" + operatingSystem + ", createdOn=" + createdOn + + ", flavor='" + flavor + '\'' + '}'; } } diff --git a/src/main/java/io/vertx/starter/service/GeneratorService.java b/src/main/java/io/vertx/starter/service/GeneratorService.java index 1a1a8411..810be011 100644 --- a/src/main/java/io/vertx/starter/service/GeneratorService.java +++ b/src/main/java/io/vertx/starter/service/GeneratorService.java @@ -20,7 +20,9 @@ import io.vertx.core.buffer.Buffer; import io.vertx.ext.web.templ.freemarker.FreeMarkerTemplateEngine; import io.vertx.starter.model.ArchiveFormat; +import io.vertx.starter.model.Dependency; import io.vertx.starter.model.Language; +import io.vertx.starter.model.ProjectFlavor; import io.vertx.starter.model.VertxProject; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveOutputStream; @@ -117,26 +119,26 @@ private void createProject(VertxProject project, TempDir tempDir) throws IOExcep Language language = project.getLanguage(); ctx.put("language", language.name().toLowerCase()); ctx.put("vertxVersion", project.getVertxVersion()); - Set vertxDependencies = project.getVertxDependencies(); + Set vertxDependencies = project.getVertxDependencies(); if (vertxDependencies == null) { vertxDependencies = new HashSet<>(); } - boolean hasVertxUnit = vertxDependencies.remove("vertx-unit"); + boolean hasVertxUnit = vertxDependencies + .removeIf(dependency -> dependency.getArtifactId().endsWith("vertx-unit")); ctx.put("hasVertxUnit", hasVertxUnit); - boolean hasVertxJUnit5 = vertxDependencies.remove("vertx-junit5") || !hasVertxUnit; - ctx.put("hasVertxJUnit5", hasVertxJUnit5); + boolean hasVertxJUnit5 = vertxDependencies + .removeIf(dependency -> dependency.getArtifactId().endsWith("vertx-junit5")) || !hasVertxUnit; + ctx.put("hasVertxJUnit5", hasVertxJUnit5 || project.getFlavor() == ProjectFlavor.MUTINY); if (hasVertxUnit && hasVertxJUnit5) { throw new RuntimeException("You cannot generate a project which depends on both vertx-unit and vertx-junit5."); } - vertxDependencies.addAll(language.getLanguageDependencies()); + ctx.put("languageDependencies", language.getLanguageDependencies()); ctx.put("vertxDependencies", vertxDependencies); + ctx.put("flavor", project.getFlavor().getId()); String packageName = packageName(project); ctx.put("packageName", packageName); ctx.put("jdkVersion", project.getJdkVersion().getValue()); - Path tempDirPath = tempDir.path(); - String tempDirPathStr = tempDirPath.toString(); - copy(tempDir, "files", "_editorconfig"); copy(tempDir, "files", "_gitignore"); @@ -163,9 +165,11 @@ private void createProject(VertxProject project, TempDir tempDir) throws IOExcep String packageDir = packageName.replace('.', '/'); String srcDir = "src/main/" + language.getName(); - render(tempDir, ctx, srcDir, "MainVerticle" + language.getExtension(), srcDir + "/" + packageDir); + String srcFile = "MainVerticle." + project.getFlavor().getId() + language.getExtension(); + render(tempDir, ctx, srcDir, srcFile, srcDir + "/" + packageDir, "MainVerticle" + language.getExtension()); String testSrcDir = "src/test/" + language.getName(); - render(tempDir, ctx, testSrcDir, "TestMainVerticle" + language.getExtension(), testSrcDir + "/" + packageDir); + String testSrcFile = "TestMainVerticle." + project.getFlavor().getId() + language.getExtension(); + render(tempDir, ctx, testSrcDir, testSrcFile, testSrcDir + "/" + packageDir, "TestMainVerticle" + language.getExtension()); render(tempDir, ctx, ".", "README.adoc"); } @@ -191,14 +195,14 @@ private void copy(TempDir tempDir, String base, String filename) throws IOExcept } private void render(TempDir tempDir, Map ctx, String sourceDir, String filename) throws IOException { - render(tempDir, ctx, sourceDir, filename, sourceDir); + render(tempDir, ctx, sourceDir, filename, sourceDir, filename); } - private void render(TempDir tempDir, Map ctx, String sourceDir, String filename, String destDir) throws IOException { + private void render(TempDir tempDir, Map ctx, String sourceDir, String filename, String destDir, String destFilename) throws IOException { Path dest = tempDir.path().resolve(destDir); Files.createDirectories(dest); Buffer data = renderBlocking(ctx, "templates/" + sourceDir + "/" + filename + ".ftl"); - vertx.fileSystem().writeFileBlocking(dest.resolve(filename).toString(), data); + vertx.fileSystem().writeFileBlocking(dest.resolve(destFilename).toString(), data); } private Buffer renderBlocking(Map context, String templateFileName) { diff --git a/src/main/java/io/vertx/starter/service/MetadataHandler.java b/src/main/java/io/vertx/starter/service/MetadataHandler.java index 041f4ecf..dd60a8e8 100644 --- a/src/main/java/io/vertx/starter/service/MetadataHandler.java +++ b/src/main/java/io/vertx/starter/service/MetadataHandler.java @@ -25,6 +25,7 @@ import io.vertx.starter.model.BuildTool; import io.vertx.starter.model.JdkVersion; import io.vertx.starter.model.Language; +import io.vertx.starter.model.ProjectFlavor; import java.util.Arrays; import java.util.function.Function; @@ -44,6 +45,7 @@ public MetadataHandler(JsonObject defaults, JsonArray versions, JsonArray stack) .put("buildTools", values(BuildTool.values(), BuildTool::getValue)) .put("languages", values(Language.values(), Language::getName)) .put("jdkVersions", values(JdkVersion.values(), JdkVersion::getValue)) + .put("flavors", values(ProjectFlavor.values(), ProjectFlavor::getId)) .put("vertxDependencies", stack) // deprecated .put("vertxVersions", versions.stream() // deprecated .map(JsonObject.class::cast) diff --git a/src/main/resources/starter.json b/src/main/resources/starter.json index dea35726..b72a386a 100644 --- a/src/main/resources/starter.json +++ b/src/main/resources/starter.json @@ -6,7 +6,8 @@ "buildTool": "maven", "vertxVersion": "4.1.1", "archiveFormat": "zip", - "jdkVersion": "11" + "jdkVersion": "11", + "flavor": "vert.x" }, "versions": [ { @@ -53,77 +54,111 @@ "category": "Web", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-web", "name": "Vert.x Web", + "mutinyBindings": true, "description": "Vert.x-Web is a tool-kit for writing sophisticated modern web applications and HTTP microservices." }, { + "groupId": "io.vertx", "artifactId": "vertx-web-client", "name": "Vert.x Web Client", + "mutinyBindings": true, "description": "Vert.x Web Client is an easy to use advanced HTTP client." }, { + "groupId": "io.vertx", "artifactId": "vertx-web-graphql", "name": "Web GraphQL Handler", + "mutinyBindings": true, "description": "Create GraphQL servers with Vert.x Web and the GraphQL-Java library." }, { + "groupId": "io.vertx", "artifactId": "vertx-web-api-contract", "name": "Web API Contract", + "mutinyBindings": false, "description": "Web API Contract supports OpenApi 3 specification for a design first approach and provides a validation framework." }, { + "groupId": "io.vertx", "artifactId": "vertx-web-templ-thymeleaf", - "name": "Thymeleaf template engine" + "name": "Thymeleaf template engine", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-web-templ-handlebars", - "name": "Handlebars template engine" + "name": "Handlebars template engine", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-web-templ-jade", - "name": "Jade template engine" + "name": "Jade template engine", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-web-templ-mvel", - "name": "MVEL template engine" + "name": "MVEL template engine", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-web-templ-pebble", - "name": "Pebble template engine" + "name": "Pebble template engine", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-web-templ-freemarker", - "name": "Apache FreeMarker template engine" + "name": "Apache FreeMarker template engine", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-web-templ-rocker", - "name": "Rocker template engine" + "name": "Rocker template engine", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-web-templ-httl", - "name": "HTTL template engine" + "name": "HTTL template engine", + "mutinyBindings": false }, { + "groupId": "io.vertx", "artifactId": "vertx-web-sstore-cookie", - "name": "Cookie session storage" + "name": "Cookie session storage", + "mutinyBindings": false }, { + "groupId": "io.vertx", "artifactId": "vertx-web-sstore-redis", - "name": "Redis session storage" + "name": "Redis session storage", + "mutinyBindings": false }, { + "groupId": "io.vertx", "artifactId": "vertx-web-sstore-infinispan", - "name": "Session storage with Infinispan Client" + "name": "Session storage with Infinispan Client", + "mutinyBindings": false }, { + "groupId": "io.vertx", "artifactId": "vertx-web-validation", "name": "Web Validation", + "mutinyBindings": true, "description": "A library to declaratively parse and validate incoming Vert.x Web HTTP requests." }, { + "groupId": "io.vertx", "artifactId": "vertx-web-openapi", "name": "Web OpenAPI", + "mutinyBindings": true, "description": "Extends Vert.x Web to support OpenAPI 3, bringing a simple interface for building web routers that conform to OpenAPI contracts." } ] @@ -134,40 +169,58 @@ "description": "Vert.x provides a few different asynchronous clients for accessing various data stores from your application. You don't have to use these clients - you could use clients direct from the vendor if you prefer (e.g. MongoDB provide their own cool async and reactive clients), but these provide a simple async API which is available in various languages.", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-pg-client", - "name": "Reactive PostgreSQL client" + "name": "Reactive PostgreSQL client", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-mysql-client", - "name": "Reactive MySQL client" + "name": "Reactive MySQL client", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-db2-client", - "name": "Reactive DB2 client" + "name": "Reactive DB2 client", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-mssql-client", - "name": "Reactive MSSQL client" + "name": "Reactive MSSQL client", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-mongo-client", - "name": "MongoDB client" + "name": "MongoDB client", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-jdbc-client", - "name": "JDBC client" + "name": "JDBC client", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-redis-client", - "name": "Redis client" + "name": "Redis client", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-cassandra-client", - "name": "Cassandra client" + "name": "Cassandra client", + "mutinyBindings": true }, { + "groupId": "io.vertx", "artifactId": "vertx-sql-client-templates", "name": "SQL Client Templates", + "mutinyBindings": true, "description": "A small library designed to facilitate the execution and data manipulation of SQL queries." } ] @@ -178,33 +231,45 @@ "description": "Vert.x provides a few components to make your applications more reactive.", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-rx-java", "name": "Vert.x RxJava v1", + "mutinyBindings": false, "description": "Vert.x API for RxJava 1." }, { + "groupId": "io.vertx", "artifactId": "vertx-rx-java2", "name": "Vert.x RxJava v2", + "mutinyBindings": false, "description": "Vert.x API for RxJava 2." }, { + "groupId": "io.vertx", "artifactId": "vertx-rx-java3", "name": "Vert.x RxJava v3", + "mutinyBindings": false, "description": "Vert.x API for RxJava 3." }, { + "groupId": "io.vertx", "artifactId": "vertx-reactive-streams", "name": "Reactive streams", + "mutinyBindings": false, "description": "Vert.x supports reactive streams so your applications can interoperate with other reactive systems such as Akka or Project Reactor." }, { + "groupId": "io.vertx", "artifactId": "vertx-sync", "name": "Vert.x Sync", + "mutinyBindings": false, "description": "Vertx-sync allows you to deploy verticles that run using fibers. Fibers are very lightweight threads that can be blocked without blocking a kernel thread. This enables you to write your verticle code in a familiar synchronous style." }, { + "groupId": "io.vertx", "artifactId": "vertx-lang-kotlin-coroutines", "name": "Vert.x Kotlin coroutines", + "mutinyBindings": false, "description": "Kotlin coroutines for Vert.x, gives you super powers such as async/await or Go-like channels. This enables you to write your verticle code in a familiar sequential style." } ] @@ -215,18 +280,24 @@ "description": "Vert.x offers various component to build microservice-based applications.", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-service-discovery", "name": "Vert.x Service Discovery", + "mutinyBindings": true, "description": "This component lets you publish, lookup and bind to any type of services." }, { + "groupId": "io.vertx", "artifactId": "vertx-circuit-breaker", "name": "Vert.x Circuit Breaker", + "mutinyBindings": true, "description": "This component provides an implementation of the circuit breaker pattern for Vert.x" }, { + "groupId": "io.vertx", "artifactId": "vertx-config", "name": "Vert.x Config", + "mutinyBindings": true, "description": "This component provides an extensible way to configure Vert.x applications." } ] @@ -236,8 +307,10 @@ "category": "IoT", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-mqtt", "name": "MQTT", + "mutinyBindings": true, "description": "Vert.x MQTT (client and server) is able to handle connections, communication and messages exchange with remote MQTT clients. Its API provides a bunch of events related to protocol messages received by clients and exposes allow to send messages to them." } ] @@ -248,58 +321,80 @@ "description": "Vert.x provides simple APIs for auth in your applications. We also provide a few out of the box implementations.", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-auth-jdbc", "name": "JDBC auth", + "mutinyBindings": true, "description": "Auth implementation backed by JDBC" }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-jwt", "name": "JWT auth", + "mutinyBindings": true, "description": "Auth implementation using JSON web tokens (JWT)" }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-shiro", "name": "Shiro auth", + "mutinyBindings": true, "description": "Auth implementation using Apache Shiro" }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-mongo", "name": "MongoDB auth", + "mutinyBindings": true, "description": "Auth implementation using MongoDB" }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-oauth2", "name": "OAuth 2", + "mutinyBindings": true, "description": "Auth implementation for OAuth2" }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-htdigest", "name": ".htdigest Auth", + "mutinyBindings": true, "description": "Authentication and authorization support based on .htdigest files." }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-properties", "name": "Properties Auth", + "mutinyBindings": true, "description": "Authentication and authorization support based on Java properties files." }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-ldap", "name": "LDAP Auth", + "mutinyBindings": true, "description": "Implementation using JDK built-in LDAP capabilities." }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-webauthn", "name": "Webauthn Auth", + "mutinyBindings": true, "description": "FIDO2 WebAuthn (password-less) implementation." }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-htpasswd", "name": ".htpasswd Auth", + "mutinyBindings": true, "description": "Authentication and authorization support based on .htpasswd files." }, { + "groupId": "io.vertx", "artifactId": "vertx-auth-sql-client", "name": "Sql Client Auth", + "mutinyBindings": true, "description": "Authentication and authorization support based on the Vert.x SQL client and a relational database." } ] @@ -309,23 +404,31 @@ "category": "Messaging", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-amqp-client", "name": "AMQP Client", + "mutinyBindings": true, "description": "A client for interacting with an AMQP 1.0 broker or router." }, { + "groupId": "io.vertx", "artifactId": "vertx-stomp", "name": "STOMP Client and Server", + "mutinyBindings": true, "description": "Vert.x provides an implementation of the STOMP protocol." }, { + "groupId": "io.vertx", "artifactId": "vertx-rabbitmq-client", "name": "RabbitMQ Client", + "mutinyBindings": true, "description": "A client to interact with RabbitMQ." }, { + "groupId": "io.vertx", "artifactId": "vertx-amqp-bridge", "name": "AMQP Bridge", + "mutinyBindings": false, "description": "A bridge for interacting with an AMQP 1.0 broker or router." } ] @@ -335,23 +438,31 @@ "category": "Integration", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-mail-client", "name": "Mail Client", + "mutinyBindings": true, "description": "Vert.x provides a simple SMTP mail client so you can send emails from your applications." }, { + "groupId": "io.vertx", "artifactId": "vertx-jca", "name": "JCA Adaptor", + "mutinyBindings": false, "description": "Vert.x provides a Java Connector Architecture (JCA) adaptor which allows it to interoperate with any JavaEE application server." }, { + "groupId": "io.vertx", "artifactId": "vertx-kafka-client", "name": "Kafka Client", + "mutinyBindings": true, "description": "A client to interact with Apache Kafka." }, { + "groupId": "io.vertx", "artifactId": "vertx-consul-client", "name": "Consul Client", + "mutinyBindings": true, "description": "A client to interact with Consul." } ] @@ -362,13 +473,17 @@ "description": "Vert.x offers various bridges to extend the Event Bus beyond the JVM", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-tcp-eventbus-bridge", "name": "TCP Eventbus Bridge", + "mutinyBindings": true, "description": "An eventbus bridge that lets you interact with Vert.x from any application thanks to a TCP socket." }, { + "groupId": "io.vertx", "artifactId": "vertx-camel-bridge", "name": "Camel Bridge", + "mutinyBindings": false, "description": "An eventbus bridge that lets you interact with Apache Camel endpoints and routes" } ] @@ -379,33 +494,45 @@ "description": "Vert.x offers various component to keep your Vert.x application on track when running in production", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-dropwizard-metrics", "name": "Metrics using Dropwizard", + "mutinyBindings": false, "description": "This component captures metrics from Vert.x core components and exposes them using Dropwizard." }, { + "groupId": "io.vertx", "artifactId": "vertx-micrometer-metrics", "name": "Metrics using Micrometer", + "mutinyBindings": true, "description": "This component captures metrics from Vert.x core components and exposes them using Micrometer." }, { + "groupId": "io.vertx", "artifactId": "vertx-health-check", "name": "Vert.x Health Check", + "mutinyBindings": false, "description": "This component provides a simple way to expose health checks." }, { + "groupId": "io.vertx", "artifactId": "vertx-zipkin", "name": "Tracing using Zipkin", + "mutinyBindings": false, "description": "Distributed tracing with Zipkin." }, { + "groupId": "io.vertx", "artifactId": "vertx-opentracing", "name": "Tracing using OpenTracing", + "mutinyBindings": false, "description": "Distributed tracing with OpenTracing." }, { + "groupId": "io.vertx", "artifactId": "vertx-opentelemetry", "name": "Tracing using OpenTelemetry", + "mutinyBindings": false, "description": "Distributed tracing with OpenTelemetry." } ] @@ -416,11 +543,15 @@ "description": "Vert.x-Unit is an unit testing tool-kit especially design to work well with asynchronous code.", "items": [ { + "groupId": "io.vertx", "name": "Vert.x Unit", + "mutinyBindings": false, "artifactId": "vertx-unit" }, { + "groupId": "io.vertx", "name": "Vert.x JUnit5", + "mutinyBindings": true, "artifactId": "vertx-junit5" } ] @@ -431,22 +562,30 @@ "description": "Vert.x supports clustering and HA out of the box. Cluster group management is implemented in cluster managers which are pluggable.", "items": [ { + "groupId": "io.vertx", "name": "Hazelcast Cluster Manager", + "mutinyBindings": false, "artifactId": "vertx-hazelcast", "description": "Cluster manager implementation that uses Hazelcast." }, { + "groupId": "io.vertx", "name": "Infinispan Cluster Manager", + "mutinyBindings": false, "artifactId": "vertx-infinispan", "description": "Cluster manager implementation that uses Infinispan." }, { + "groupId": "io.vertx", "name": "Apache Ignite Cluster Manager", + "mutinyBindings": false, "artifactId": "vertx-ignite", "description": "Cluster manager implementation that uses Apache Ignite." }, { + "groupId": "io.vertx", "name": "Apache Zookeper Cluster Manager", + "mutinyBindings": false, "artifactId": "vertx-zookeeper", "description": "Cluster manager implementation that uses Apache Zookeeper." } @@ -458,32 +597,44 @@ "description": "Vert.x services are a simple and effective way to encapsulate reusable functionality for use elsewhere. Services are deployed using a service identifier which decouples the user from details of the implementation.", "items": [ { + "groupId": "io.vertx", "name": "Service Proxies", + "mutinyBindings": false, "artifactId": "vertx-service-proxy", "description": "Proxies allow remote event bus services to be called as if they were local." }, { + "groupId": "io.vertx", "name": "SockJS Service Proxies", + "mutinyBindings": false, "artifactId": "vertx-sockjs-service-proxy", "description": "Allow event bus services to be called from JavaScript (browser or Node.js)." }, { + "groupId": "io.vertx", "name": "gRPC", + "mutinyBindings": false, "artifactId": "vertx-grpc", "description": "Implement gRPC Clients and Servers for Vert.x." }, { + "groupId": "io.vertx", "name": "Service Factories", + "mutinyBindings": false, "artifactId": "vertx-service-factory", "description": "How to package and deploy Vert.x independent services." }, { + "groupId": "io.vertx", "name": "Maven Service Factory", + "mutinyBindings": false, "artifactId": "vertx-maven-service-factory", "description": "This lets you dynamically install and deploy services from Maven at run-time." }, { + "groupId": "io.vertx", "name": "HTTP Service Factory", + "mutinyBindings": false, "artifactId": "vertx-http-service-factory", "description": "This lets you dynamically install and deploy services from an HTTP server (for example Bintray at run-time." } @@ -494,8 +645,10 @@ "category": "Standards", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-json-schema", "name": "JSON Schema", + "mutinyBindings": true, "description": "An extensible implementation of the Json Schema specification to validate every JSON data structure, asynchronously." } ] @@ -505,8 +658,10 @@ "category": "Devops", "items": [ { + "groupId": "io.vertx", "artifactId": "vertx-shell", "name": "Shell", + "mutinyBindings": true, "description": "This component lets you interact with your Vert.x application using a CLI interface." } ] diff --git a/src/main/resources/templates/build.gradle.kts.ftl b/src/main/resources/templates/build.gradle.kts.ftl index d605c8fb..8bca971c 100644 --- a/src/main/resources/templates/build.gradle.kts.ftl +++ b/src/main/resources/templates/build.gradle.kts.ftl @@ -30,6 +30,9 @@ repositories { } val vertxVersion = "${vertxVersion}" +<#if flavor == "mutiny"> +val mutinyVersion = "2.9.0" + val junitJupiterVersion = "5.7.0" val mainVerticleName = "${packageName}.MainVerticle" @@ -45,17 +48,31 @@ application { } dependencies { +<#if flavor == "vert.x"> implementation(platform("io.vertx:vertx-stack-depchain:$vertxVersion")) -<#if !vertxDependencies?has_content> + +<#if flavor == "vert.x" && !vertxDependencies?has_content> implementation("io.vertx:vertx-core") +<#elseif flavor == "mutiny" && !vertxDependencies?has_content> + implementation("io.smallrye.reactive:smallrye-mutiny-vertx-core:$mutinyVersion") <#list vertxDependencies as dependency> - implementation("io.vertx:${dependency}") + <#if flavor == "mutiny" && !dependency.vertxDependency> + implementation("${dependency.groupId}:${dependency.artifactId}:$mutinyVersion") + <#else> + implementation("${dependency.groupId}:${dependency.artifactId}") + <#if language == "kotlin"> implementation(kotlin("stdlib-jdk8")) -<#if hasVertxJUnit5> +<#list languageDependencies as dependency> + implementation("io.vertx:${dependency}<#if flavor != "vert.x">:$vertxVersion") + +<#if flavor == "mutiny"> + testImplementation("io.smallrye.reactive:smallrye-mutiny-vertx-junit5:$mutinyVersion") + testImplementation("org.junit.jupiter:junit-jupiter:$junitJupiterVersion") +<#elseif hasVertxJUnit5> testImplementation("io.vertx:vertx-junit5") testImplementation("org.junit.jupiter:junit-jupiter:$junitJupiterVersion") <#elseif hasVertxUnit> diff --git a/src/main/resources/templates/pom.xml.ftl b/src/main/resources/templates/pom.xml.ftl index 73b7698d..6cc85803 100644 --- a/src/main/resources/templates/pom.xml.ftl +++ b/src/main/resources/templates/pom.xml.ftl @@ -30,11 +30,15 @@ <#if hasVertxJUnit5> 5.7.0 +<#if flavor == "mutiny"> + 2.9.0 + ${packageName}.MainVerticle io.vertx.core.Launcher +<#if flavor == "vert.x"> @@ -48,19 +52,34 @@ + -<#if !vertxDependencies?has_content> +<#if flavor == "vert.x" && !vertxDependencies?has_content> io.vertx vertx-core +<#elseif flavor == "mutiny" && !vertxDependencies?has_content> + + io.smallrye.reactive + smallrye-mutiny-vertx-core + <#noparse>${mutiny.version} + <#list vertxDependencies as dependency> + <#if flavor == "mutiny" && !dependency.vertxDependency> - io.vertx - ${dependency} + ${dependency.groupId} + ${dependency.artifactId} + <#noparse>${mutiny.version} + + <#else> + + ${dependency.groupId} + ${dependency.artifactId} + <#if language == "kotlin"> <#noparse> @@ -71,8 +90,30 @@ +<#list languageDependencies as dependency> + + io.vertx + ${dependency} + <#if flavor != "vert.x">${vertxVersion} + + -<#if hasVertxJUnit5> +<#if flavor == "mutiny"> + + io.smallrye.reactive + smallrye-mutiny-vertx-junit5 + <#noparse>${mutiny.version} + test + + + org.junit.jupiter + junit-jupiter-api +<#noparse> + ${junit-jupiter.version} + + test + +<#elseif hasVertxJUnit5> io.vertx vertx-junit5 diff --git a/src/main/resources/templates/src/main/java/MainVerticle.mutiny.java.ftl b/src/main/resources/templates/src/main/java/MainVerticle.mutiny.java.ftl new file mode 100644 index 00000000..b9bc9e74 --- /dev/null +++ b/src/main/resources/templates/src/main/java/MainVerticle.mutiny.java.ftl @@ -0,0 +1,18 @@ +package ${packageName}; + +import io.smallrye.mutiny.Uni; +import io.smallrye.mutiny.vertx.core.AbstractVerticle; + +public class MainVerticle extends AbstractVerticle { + + @Override + public Uni asyncStart() { + return vertx.createHttpServer().requestHandler(req -> { + req.response() + .putHeader("content-type", "text/plain") + .endAndForget("Hello from Vert.x!"); + }).listen(8888) + .onItem().invoke(() -> System.out.println("HTTP server started on port 8888")) + .replaceWithVoid(); + } +} diff --git a/src/main/resources/templates/src/main/java/MainVerticle.java.ftl b/src/main/resources/templates/src/main/java/MainVerticle.vert.x.java.ftl similarity index 100% rename from src/main/resources/templates/src/main/java/MainVerticle.java.ftl rename to src/main/resources/templates/src/main/java/MainVerticle.vert.x.java.ftl diff --git a/src/main/resources/templates/src/main/kotlin/MainVerticle.mutiny.kt.ftl b/src/main/resources/templates/src/main/kotlin/MainVerticle.mutiny.kt.ftl new file mode 100644 index 00000000..1eb90fee --- /dev/null +++ b/src/main/resources/templates/src/main/kotlin/MainVerticle.mutiny.kt.ftl @@ -0,0 +1,17 @@ +package ${packageName} + +import io.smallrye.mutiny.Uni +import io.smallrye.mutiny.vertx.core.AbstractVerticle + +class MainVerticle : AbstractVerticle() { + + override fun asyncStart(): Uni { + return vertx.createHttpServer().requestHandler { req -> + req.response() + .putHeader("content-type", "text/plain") + .endAndForget("Hello from Vert.x!") + }.listen(8888) + .onItem().invoke(Runnable { println("HTTP server started on port 8888") }) + .replaceWithVoid() + } +} diff --git a/src/main/resources/templates/src/main/kotlin/MainVerticle.kt.ftl b/src/main/resources/templates/src/main/kotlin/MainVerticle.vert.x.kt.ftl similarity index 100% rename from src/main/resources/templates/src/main/kotlin/MainVerticle.kt.ftl rename to src/main/resources/templates/src/main/kotlin/MainVerticle.vert.x.kt.ftl diff --git a/src/main/resources/templates/src/test/java/TestMainVerticle.mutiny.java.ftl b/src/main/resources/templates/src/test/java/TestMainVerticle.mutiny.java.ftl new file mode 100644 index 00000000..aa4671d2 --- /dev/null +++ b/src/main/resources/templates/src/test/java/TestMainVerticle.mutiny.java.ftl @@ -0,0 +1,23 @@ +package ${packageName}; + +import io.vertx.junit5.VertxExtension; +import io.vertx.junit5.VertxTestContext; +import io.vertx.mutiny.core.Vertx; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(VertxExtension.class) +public class TestMainVerticle { + + @BeforeEach + void deploy_verticle(Vertx vertx, VertxTestContext testContext) { + vertx.deployVerticle(new MainVerticle()) + .subscribe().with(id -> testContext.completeNow()); + } + + @Test + void verticle_deployed(Vertx vertx, VertxTestContext testContext) throws Throwable { + testContext.completeNow(); + } +} diff --git a/src/main/resources/templates/src/test/java/TestMainVerticle.java.ftl b/src/main/resources/templates/src/test/java/TestMainVerticle.vert.x.java.ftl similarity index 100% rename from src/main/resources/templates/src/test/java/TestMainVerticle.java.ftl rename to src/main/resources/templates/src/test/java/TestMainVerticle.vert.x.java.ftl diff --git a/src/main/resources/templates/src/test/kotlin/TestMainVerticle.mutiny.kt.ftl b/src/main/resources/templates/src/test/kotlin/TestMainVerticle.mutiny.kt.ftl new file mode 100644 index 00000000..08bb54cd --- /dev/null +++ b/src/main/resources/templates/src/test/kotlin/TestMainVerticle.mutiny.kt.ftl @@ -0,0 +1,23 @@ +package ${packageName} + +import io.vertx.junit5.VertxExtension +import io.vertx.junit5.VertxTestContext +import io.vertx.mutiny.core.Vertx +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(VertxExtension::class) +class TestMainVerticle { + + @BeforeEach + fun deploy_verticle(vertx: Vertx, testContext: VertxTestContext) { + vertx.deployVerticle(MainVerticle()) + .subscribe().with { testContext.completeNow() } + } + + @Test + fun verticle_deployed(vertx: Vertx, testContext: VertxTestContext) { + testContext.completeNow() + } +} diff --git a/src/main/resources/templates/src/test/kotlin/TestMainVerticle.kt.ftl b/src/main/resources/templates/src/test/kotlin/TestMainVerticle.vert.x.kt.ftl similarity index 100% rename from src/main/resources/templates/src/test/kotlin/TestMainVerticle.kt.ftl rename to src/main/resources/templates/src/test/kotlin/TestMainVerticle.vert.x.kt.ftl diff --git a/src/main/resources/webroot/index.html b/src/main/resources/webroot/index.html index 7da54c8c..9bd1b31b 100644 --- a/src/main/resources/webroot/index.html +++ b/src/main/resources/webroot/index.html @@ -108,6 +108,15 @@

Create a new Vert.x application

+
+ +
+
+ +
+
+
diff --git a/src/main/resources/webroot/main.js b/src/main/resources/webroot/main.js index baf5d9d3..f3c45d44 100644 --- a/src/main/resources/webroot/main.js +++ b/src/main/resources/webroot/main.js @@ -48,7 +48,8 @@ angular vertxVersion: vertxProject.vertxVersion, vertxDependencies: vertxProject.vertxDependencies, packageName: vertxProject.packageName, - jdkVersion: vertxProject.jdkVersion + jdkVersion: vertxProject.jdkVersion, + flavor: vertxProject.flavor } }); }, @@ -80,7 +81,7 @@ angular argSeparator: "; " } }, - args: ["groupId", "artifactId", "packageName", "vertxVersion", "vertxDependencies", "language", "jdkVersion", "buildTool"] + args: ["groupId", "artifactId", "packageName", "vertxVersion", "vertxDependencies", "language", "jdkVersion", "buildTool", "flavor"] }) .filter('capitalize', function () { return function (input) { @@ -100,6 +101,7 @@ angular vm.languages = []; vm.buildTools = []; vm.jdkVersions = []; + vm.flavors = []; vm.advancedCollapsed = true; vm.isWindows = bowser.windows; @@ -169,6 +171,7 @@ angular vm.buildTools = data.buildTools; vm.languages = data.languages; vm.jdkVersions = data.jdkVersions; + vm.flavors = data.flavors; vm.selectedPanel = data.stack && data.stack.length > 0 ? data.stack[0].code : 'none'; vm.vertxVersions = data.versions.map(function (version) { return version.number; @@ -186,6 +189,7 @@ angular vm.vertxProject.vertxDependencies = []; vm.vertxProject.packageName = ""; vm.vertxProject.jdkVersion = defaults.jdkVersion; + vm.vertxProject.flavor = defaults.flavor; vm.disableDependencies(defaults.vertxVersion); refreshAvailableDependencies(defaults.vertxVersion, false); diff --git a/src/test/java/io/vertx/starter/MetadataHandlerTest.java b/src/test/java/io/vertx/starter/MetadataHandlerTest.java index d818e5bd..a86e296e 100644 --- a/src/test/java/io/vertx/starter/MetadataHandlerTest.java +++ b/src/test/java/io/vertx/starter/MetadataHandlerTest.java @@ -68,6 +68,7 @@ public void shouldReturnStarterMetadata(Vertx vertx, VertxTestContext testContex assertThat(metadata.getJsonArray("buildTools")).contains("maven", "gradle"); assertThat(metadata.getJsonArray("languages")).contains("java", "kotlin"); assertThat(metadata.getJsonArray("jdkVersions")).contains("1.8", "11", "16"); + assertThat(metadata.getJsonArray("flavors")).contains("vert.x", "mutiny"); assertThat(metadata.getJsonArray("vertxDependencies")).isEqualTo(stack); assertThat(metadata.getJsonArray("vertxVersions")).isEqualTo(versions.stream() .map(JsonObject.class::cast) diff --git a/src/test/java/io/vertx/starter/ValidationHandlerTest.java b/src/test/java/io/vertx/starter/ValidationHandlerTest.java index 76ec4856..2dabb88f 100644 --- a/src/test/java/io/vertx/starter/ValidationHandlerTest.java +++ b/src/test/java/io/vertx/starter/ValidationHandlerTest.java @@ -31,6 +31,7 @@ import io.vertx.ext.web.client.WebClientOptions; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; +import io.vertx.starter.model.Dependency; import io.vertx.starter.model.VertxProject; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -38,6 +39,7 @@ import java.io.IOException; import java.util.Collections; +import java.util.Set; import static io.vertx.starter.config.ProjectConstants.*; import static io.vertx.starter.model.ArchiveFormat.ZIP; @@ -103,7 +105,8 @@ void testUnknownDependency(Vertx vertx, VertxTestContext testContext) { @Test void testDependencyIncluded(Vertx vertx, VertxTestContext testContext) { validator = new ValidationHandler(defaults, versions, stack); - VertxProject expected = defaults.mapTo(VertxProject.class).setVertxDependencies(Collections.singleton("vertx-web")); + Set dependencies = Collections.singleton(new Dependency().setGroupId("io.vertx").setArtifactId("vertx-web")); + VertxProject expected = defaults.mapTo(VertxProject.class).setVertxDependencies(dependencies); expectSuccess(vertx, testContext, validator, params.add(VERTX_DEPENDENCIES, "vertx-web"), ZIP.getFileExtension(), expected); } @@ -115,7 +118,7 @@ void testDependencyExcluded(Vertx vertx, VertxTestContext testContext) { stack = new JsonArray() .add(new JsonObject() .put("category", "Web") - .put("items", new JsonArray().add(new JsonObject().put("artifactId", "vertx-web-graphql"))) + .put("items", new JsonArray().add(new JsonObject().put("artifactId", "vertx-web-graphql").put("mutinyBindings", true))) ); validator = new ValidationHandler(defaults, versions, stack); expectFailure(vertx, testContext, validator, params.add(VERTX_DEPENDENCIES, "vertx-web-graphql"), ZIP.getFileExtension(), VERTX_DEPENDENCIES); @@ -136,6 +139,11 @@ void testUnknownJdkVersion(Vertx vertx, VertxTestContext testContext) { expectFailure(vertx, testContext, validator, params.add(JDK_VERSION, "9"), ZIP.getFileExtension(), JDK_VERSION); } + @Test + void testUnknownFlavor(Vertx vertx, VertxTestContext testContext) { + expectFailure(vertx, testContext, validator, params.add(FLAVOR, "RxJava"), ZIP.getFileExtension(), JDK_VERSION); + } + @Test void testTwoJunitVersions(Vertx vertx, VertxTestContext testContext) { MultiMap params = this.params.add(VERTX_DEPENDENCIES, "vertx-unit,vertx-junit5"); diff --git a/src/test/java/io/vertx/starter/service/GeneratorTest.java b/src/test/java/io/vertx/starter/service/GeneratorTest.java index c314b740..b202749f 100644 --- a/src/test/java/io/vertx/starter/service/GeneratorTest.java +++ b/src/test/java/io/vertx/starter/service/GeneratorTest.java @@ -32,10 +32,7 @@ import io.vertx.starter.Util; import io.vertx.starter.VertxProjectCodec; import io.vertx.starter.config.Topics; -import io.vertx.starter.model.BuildTool; -import io.vertx.starter.model.JdkVersion; -import io.vertx.starter.model.Language; -import io.vertx.starter.model.VertxProject; +import io.vertx.starter.model.*; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; @@ -123,7 +120,8 @@ static VertxProject defaultProject() { .setBuildTool(MAVEN) .setVertxVersion("4.1.1") .setArchiveFormat(TGZ) - .setJdkVersion(JdkVersion.JDK_1_8); + .setJdkVersion(JdkVersion.JDK_1_8) + .setFlavor(ProjectFlavor.VERTX); } @ParameterizedTest @@ -140,20 +138,26 @@ static Stream testProjectsJdk8() throws IOException { .filter(version -> !version.endsWith("-SNAPSHOT")) .collect(toList()); - List> testDeps = Arrays.asList(Collections.singleton("vertx-unit"), Collections.singleton("vertx-junit5")); + List> testDeps = Arrays.asList( + Collections.singleton(new Dependency().setArtifactId("vertx-unit")), + Collections.singleton(new Dependency().setArtifactId("vertx-junit5")) + ); Stream.Builder builder = Stream.builder(); for (BuildTool buildTool : BuildTool.values()) { for (Language language : Language.values()) { for (String version : versions) { - for (Set vertxDependencies : testDeps) { - VertxProject vertxProject = defaultProject() - .setBuildTool(buildTool) - .setLanguage(language) - .setVertxVersion(version) - .setVertxDependencies(new HashSet<>(vertxDependencies)) - .setPackageName("com.mycompany.project.special"); - builder.add(vertxProject); + for (Set vertxDependencies : testDeps) { + for (ProjectFlavor flavor : ProjectFlavor.values()) { + VertxProject vertxProject = defaultProject() + .setBuildTool(buildTool) + .setLanguage(language) + .setVertxVersion(version) + .setVertxDependencies(new HashSet<>(vertxDependencies)) + .setPackageName("com.mycompany.project.special") + .setFlavor(flavor); + builder.add(vertxProject); + } } } }