© 2016-2024 The original authors.

1. Introduction

Eclipse Vert.x is a toolkit to build reactive and distributed systems on the top of the JVM.

The Vert.x Maven Plugin is a plugin for Apache Maven that helps to develop and/or to package Vert.x applications.

The last version of the Vert.x Maven Plugin is 2.0.0.

1.1. Using the plugin

The plugin provides a set of goals such as:

  • setup - create a new project or adds the Vert.x Maven Plugin to an existing one

  • initialize - manage js dependencies and webjars, and initiate redeployment if needed

  • package - package a Vert.x application as an executable uber-jar

  • run - run the Vert.x application as part of the Maven build, in a separate process

Generally, you will use the following configuration:

<project>
  <properties>
    <vertx.verticle>org.acme.MyVerticle</vertx.verticle>
  </properties>
  ...
  <build>
    <plugins>
        ...
        <plugin>
            <groupId>io.reactiverse</groupId>
            <artifactId>vertx-maven-plugin</artifactId>
            <version>2.0.0</version>
            <executions>
                <execution>
                    <id>vmp</id>
                    <goals>
                        <goal>initialize</goal>
                        <goal>package</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        ...
    </plugins>
  </build>
  ...
</project>

2. Goals

2.1. Common Configurations

All goals share the following configuration:

Table 1. Package configuration
Element Description Default Property

verticle

The main verticle class name.

 

vertx.verticle

launcher

The launcher or application main class name.

Depends on the Vert.x version (see below).

vertx.launcher

skip

Skip the processing executed by this plugin

false

vertx.skip

The Vert.x Maven Plugin computes a default launcher value as follows:

  • For a Vert.x 4 application, the default is io.vertx.core.Launcher

  • For a Vert.x 5 application:

    • If the io.vertx:vertx-launcher-application dependency is present, the default is io.vertx.launcher.application.VertxApplication

    • Otherwise, if the io.vertx:vertx-launcher-legacy-cli dependency is present, the default is io.vertx.core.Launcher

2.2. vertx:setup

This goal creates a new project, or adds the Vert.x Maven Plugin to an existing one.

2.2.1. Usage

mvn io.reactiverse:vertx-maven-plugin:2.0.0:setup

This will configure Vert.x and its dependencies to 4.5.8, i.e. the Maven project property vertx.version will be set to 4.5.8.

If you wish to override the default Vert.x version, then you can run the same command as above with -DvertxVersion=<your-vertx-version>:

mvn io.reactiverse:vertx-maven-plugin:2.0.0:setup -DvertxVersion=

You can also generate a project if you don’t have a pom.xml file:

mvn io.reactiverse:vertx-maven-plugin:2.0.0:setup \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=acme-project \
    -DprojectVersion=1.0-SNAPSHOT \
    -Dverticle=org.acme.Foo

The verticle parameter creates a new verticle class file.

When creating a new project, the java.specification.version system property is used to configure the Maven compiler plugin in the new POM file. To set a different Java version, use the javaVersion property:

mvn io.reactiverse:vertx-maven-plugin:2.0.0:setup -DjavaVersion=11

2.3. vertx:initialize

This goal has several aims:

  • copy js dependencies to the webroot directory

  • unpack webjars dependencies to the webroot directory (optional)

  • initialize the recording of the build used for the redeployment

2.3.1. Configuration

The initialize goal has the following parameters apart from the ones mentioned in Common Configuration:

Table 2. Initialize Configuration
Element Description Property Default

webRoot

The location where js dependencies and webjars are copied.

 

${project.baseDir}/target/classes/webroot

unpackWebJar

Whether webjars are unpacked to webRoot. If not unpacked, webjars can be served from the classpath.

 

false

stripWebJarVersion

Whether the version is stripped when unpacking webjars

 

true

stripJavaScriptDependencyVersion

Whether the version is stripped when copying the JavaScript file

 

true

The webroot directory is generally used by the StaticHandler from Vert.x Web.

2.3.2. Redeployment

The initialize goal is used to configure the redeployment used in vertx:run. It starts observing the executed plugins in your build to replay them when a file changes.

2.4. vertx:package

This goal packages a Vert.x application as an executable uber-jar (a JAR file containing the files of the application and of its dependencies).

Being executable, it can be launched using: java -jar <my-app.jar>.

The packaging process adds certain MANIFEST.MF entries that control how the application is launched. The plugin takes care of adding the required entries to the MANIFEST.MF with values configured using the Common Configuration.

The following are the MANIFEST.MF entries that will be added based on the configuration elements:

Table 3. Manifest entries
Property Manifest Attribute Remarks

vertx.verticle

Main-Verticle

The main verticle, i.e. the entry point of your application. Used when the Main-Class is a Vert.x launcher.

vertx.launcher

Main-Class

The main class used to start the application.

2.4.1. Configuration

The package goal has the following parameters apart from the ones mentioned in Common Configuration:

Table 4. Package Configuration
Element Description Property Default

serviceProviderCombination

Whether SPI files (META-INF/services) need to be combined. Accepted valued as combine and none.

 

combine

classifier

The classifier to add to the artifact generated. If given, the artifact will be attached with that classifier and the main artifact will be deployed as the main artifact. If this is not given (default), it will replace the main artifact and only the Vert.x uber-jar artifact will be deployed (in the Maven sense). Attaching the artifact allows to deploy it alongside to the original one. Attachment is controlled using the attach parameter.

 

 

attach

Whether the created archive needs to be attached to the project. If attached, the uber-jar is installed and deployed alongside the main artifact (plain jar). Notice that you can’t disable attachment if the classifier is not set (it would mean detaching the main artifact).

 

true

2.5. vertx:run

This goal allows to run the Vert.x application as part of the Maven build, in a separate process.

By default, it monitors the src/main directory and, if the code changes, rebuilds the project and restarts the application. The plugin re-executes the mojos that ran between the generate-source and the process-classes phases.

So, to start a Vert.x application, just launch:

mvn vertx:run

If the sources aren’t compiled, the plugin executes mvn compile for you.

2.5.1. Configuration

The run goal has the following parameters apart from the ones mentioned in Common Configuration:

Table 5. Run Configuration
Element Description Property Default

redeploy

Whether redeployment is enabled.

vertx.redeploy.enabled

true

redeployRootDirectory

The root directory to scan for changes.

 

${project.basedir}/src/main

redeployIncludes

A list of Ant-like patterns of files/directories to include in change monitoring. The patterns must be expressed relatively to the rootDirectory.

 

 

redeployExcludes

A list of Ant-like patterns of files/directories to exclude from change monitoring. The patterns must be expressed relatively to the rootDirectory.

 

 

redeployScanPeriod

How often, in milliseconds, should the source files be scanned for file changes.

vertx.redeploy.scan.period

1000

redeployGracePeriod

How long, in milliseconds, the plugin should wait between two redeployments.

vertx.redeploy.grace.period

1000

jvmArgs

The JVM arguments that will be used when starting the Vert.x application.

vertx.jvmArguments

 

runArgs

The list of arguments that can be passed to the main class, if it is a Vert.x launcher. You can also pass the required run arguments using the system property. e.g. -Dvertx.runArgs="--worker --instances=2". The system property takes precedence over the plugin configurations

vertx.runArgs

 

options

The Vert.x configuration file path that will be passed to the main class, if it is a Vert.x launcher, as -options. If a YAML file is configured then it will be converted to JSON by the plugin. The converted file will be saved in ${project.outputDir}/conf directory.

vertx.options

src/main/options.json or src/main/options.yaml or src/main/options.yml

config

The verticle configuration file path that will be passed to the main class, if it is a Vert.x launcher, as -conf. If a YAML file is configured then it will be converted to JSON by the plugin. The converted file will be saved in ${project.outputDir}/conf directory.

vertx.config

src/main/config/application.json or src/main/config/application.yml or src/main/config/application.yaml

vertxWebEnvironment

The environment for Vert.x Web apps.

vertxweb.environment

Defaults to either the VERTXWEB_ENVIRONMENT environment variable value or, if absent, to dev.

workDirectory

The working directory for the Vert.x application.

vertx.directory

${project.basedir}

disableBlockedThreadChecker

Whether the Vert.x application should be started with its blocked thread checker disabled.

vertx.disable.blocked.thread.checker

true

debug

Whether the JVM running the Vert.x application should start a remote debug server.

vertx.debug

true

debugSuspend

Whether the application must wait until a debugger is attached before starting.

vertx.debug.suspend

false

debugPort

The remote debug server port.

vertx.debug.port

5005

For example, if the projects contains a web frontend built with Node in /src/main/frontend, you will have to exclude files that are changed as part of the frontend build:

<plugin>
<groupId>io.reactiverse</groupId>
<artifactId>vertx-maven-plugin</artifactId>
<version>${vertx-maven-plugin.version}</version>
<executions>
  <execution>
    <id>vmp</id>
    <goals>
      <goal>initialize</goal>
      <goal>package</goal>
    </goals>
  </execution>
</executions>
<configuration>
  <redeployRootDirectory>${project.basedir}/src/main</redeployRootDirectory>
  <redeployExcludes>
    <redeployExclude>frontend/node_modules/**</redeployExclude>
    <redeployExclude>frontend/dist/**</redeployExclude>
    <redeployExclude>frontend/package-lock.json</redeployExclude>
  </redeployExcludes>
</configuration>
</plugin>

2.6. Archive configuration

The Vert.x Maven Plugin lets you configure the content of the created archive. Typically, you can decide:

  • which dependency needs to be embedded

  • which files need to be included

  • which resources need to be combined

Besides, you can customize the manifest.

By default, the plugin:

  • embeds all compile dependencies

  • includes all files from target/classes (compiled classes from src/main/resources, processed resources from `src/main/resources)

  • combines resources from META-INF/services, META-INF/spring.* and META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat.

If the generated uber-jar contains files under /META-INF/versions/, the plugin creates a Multi-release JAR file. In practice, this happens if your project contains files under /META-INF/versions/ or depends on at least one Multi-release JAR file (e.g. Infinispan).

2.6.1. Using archive configuration

In your plugin configuration add the archive item:

<project>
  ...
  <build>
    <plugins>
        ...
        <plugin>
            <groupId>io.reactiverse</groupId>
            <artifactId>vertx-maven-plugin</artifactId>
            <version>${version}</version>
            <executions>
                <execution>
                    <id>vmp</id>
                    <goals>
                        <goal>initialize</goal>
                        <goal>package</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <archive>
                    <!-- archive configuration goes here -->
                </archive>
            </configuration>
        </plugin>
        ...
    </plugins>
  </build>
  ...
</project>
Configuring embedded dependencies

In the archive configuration, you can declare dependency sets which indicate which dependencies must be included and excluded. Also for each configure set, you can decide the file to include and exclude.

Here is an example:

<configuration>
   <archive>
       <dependencySets>
           <set>
              <excludes>
                  <exclude>*:commons-lang3</exclude>
              </excludes>
              <includes>
                  <include>*:log4j-core</include>
                  <include>*:vertx-core</include>
              </includes>
              <options>
                  <excludes>
                      <exclude>*.dtd</exclude>
                  </excludes>
              </options>
           </set>
       </dependencySets>
    </archive>
</configuration>

Notice that when a dependency set is configured, no other dependency is embedded, disabling the default. When you configure the archive without a dependency set, the default behavior (embedding all compile dependencies) is used.

On a dependency set you can configure:

  • includes: the set of dependencies to specifically include, if not set, include all dependencies not explicitly excluded

  • excludes: the set of dependencies to exclude

  • scope: the scope of the dependency to include, default to runtime

  • useTransitiveDependencies: a boolean indicating if transitive dependencies from included dependencies must be also included in the jar

  • option: configure the files to include / exclude from this dependency set

The option attribute enable fine-grain tuning of the file to embed. In the example above, the dtd files are excluded.

Embedding specific file

The archive can be configured with a set of external file to include. For instance:

<configuration>
   <archive>
       <files>
          <file>
              <source>src/ext/hello.txt</source>
              <outputDirectory>misc</outputDirectory>
              <destName>lorem-ipsum.txt</destName>
          </file>
       </files>
    </archive>
</configuration>

Each file contains:

  • the source - the location of the file

  • the outputDirectory - indicating where would be the file in the archive

  • the destName - indicating the final name

For instance, in the previous example, the file src/ext/hello.txt is embedded in the archive as misc/lorem-ipsum.txt.

Embedding file sets

While files allow embedding files individually, fileSets declare set of files:

<archive>
    <fileSets>
       <fileSet>
           <directory>src/ext</directory>
           <outputDirectory>misc</outputDirectory>
           <excludes>
               <exclude>h*.txt</exclude>
           </excludes>
       </fileSet>
    </fileSets>
</archive>

In a fileSet, you can configure:

  • the directory - the directory containing the files

  • the outputDirectory - indicating where would be the file in the archive

  • includes and excludes pattern to choose which files you want to embed in the archive.

  • useDefaultExcludes - indicating if you want to use the default exclusion list (enabled by default)

Customizing the manifest

You can also add entries into the MANIFEST.MF of the created archive using the manifest entry:

<executions>
    <execution>
        <goals>
            <goal>package</goal>
        </goals>
        <configuration>
            <archive>
               <manifest>
                   <key>value</key>
                   <name>${project.artifactId}</name>
               </manifest>
            </archive>
        </configuration>
    </execution>
</executions>
Resource combination

Resource combination is the process of merging the content of some files into a single file. It is particularly useful when building an archive embedding dependencies which contain the same files.

The files matching these patterns are combined by default:

  • META-INF/services/*

  • META-INF/spring*

  • META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat.

The fileCombinationPatterns attribute allows configuring which files need to be combined:

<archive>
    <fileCombinationPatterns>
        <pattern>misc/extension.*</pattern>
        <pattern>META-INF/services/*</pattern>
        <pattern>META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat</pattern>
    </fileCombinationPatterns>
</archive>
If you set the fileCombinationPatterns attribute, the defaults are ignored.

3. Miscellaneous

3.1. How does redeployment work

During the initialize phase, the plugin starts observing the mojos (Maven plugins) that are executed.

The Vert.x Maven Plugin watches for changes in src/main. When a file or directory is changed (created, updated or deleted):

  • it stops the Vert.x application

  • it replays the executed mojos (all the mojos from the generate-sources to the process-classes phases, using the same configuration as the initial (observed) one)

  • it stars the Vert.x application again

Such a mechanism lets you use any Maven plugin (executed in the right set of phases). The plugin is re-executed and then the Vert.x application is restarted.

3.2. Windows: command line is too long

The Vert.x Maven Plugin runs your Vert.x application in a forked process. This process command line can grow quickly depending on:

  1. the number of dependencies in the project,

  2. the length of the path to JVM,

  3. the length of the path to the Maven repository.

On Windows, there is a maximum length for command lines. When this maximum is reached the Vert.x application fails to start. You will see an error such as:

Command line is too long

As a workaround, you can either:

  • move the JVM and Maven repository paths closer to the root of the Windows drive, or

  • use subst to associate the JVM and Maven repository paths with a drive letter.

For example, you could associate the letter X with the JVM path and Y with the Maven repository path:

subst X: "C:\Program Files\AdoptOpenJDK\jdk-11.0.8.10-hotspot"
subst Y: "C:\Users\User\.m2\repository"
Virtual drives created with subst do not survive reboots. To make the setup somewhat persistent, put the subst commands in a batch file and add it to the startup folder.

Then:

  1. set the JAVA_HOME environment variable to X:

  2. open the Maven settings file and change the localRepository element value to Y:

Don’t forget to open a new terminal so that the environment variable change is visible.

4. References