Vert.x Fat Jar Deployments
Fat jar deployments in Vert.x can simplify the delivery of your software greatly if you don’t need the fine-grained, runtime control of a full installation . One drawback is limited options for module dependencies, especially those created by programmatic deployment. This post will run through the options available for such scenarios. I have created a project with two verticles on Github for following along.
Having everything packaged into a single unit that only needs a Java command to run is ideal for many deployment pipelines, but it constrains the ability to manage modules. The scenario I’m focused on specifically is when you need to deploy modules programmatically. Take this verticle for example.
In a typical Vert.x setup, you can manage which modules are available easily with the command line tools and module lib. With fat jar deployments you don’t have this option, so you need to add the modules to the classpath somehow so Vert.x can resolve the correct modules and versions.
To demonstrate, I have created two Vert.x modules called “hello-mod” and “world-mod”. Hello-mod deploys world-mod on startup and then sends a message to the event bus saying “Hello”. World-mod registers a handler for that address and replies with a “world!” message when received. The first step to running this example:
This will install the module into your local maven repo. When running a module that deploys other modules, there are a handful of places Vert.x will look to resolve them (described in their documentation). Since we probably don’t want to bake manual dependency management processes into our deployment, maven is a convenient way to get the modules on the classpath and discoverable by the framework. Now that we have world-mod in our maven repo, we can build a fat jar from hello-mod and run it:
In the last log statement you should see this line:
INFO: Received message: world!
This works fine, but we obviously don’t want to deal with local building and installation of our modules in production. Along with your local maven repo, Vert.x will also search through a configurable list of repositories for the modules that it needs. If your project doesn’t have a src/main/resources/platform_lib/repos.txt file, copy it from the default repos.txt file located in the conf/ directory of your Vert.x installation. You will notice this file has several locations defined, one being your local maven repository which is why our previous example works. Unless you are building an open source project of some sort, you probably won’t be able to store your modules in the other public maven repos in the file, so we have to add our own. I went ahead and built the world-mod and uploaded it to bintray so we can test it out. Add this line to your repos.txt:
Now remove the module from your local maven repo so we know it isn’t finding it there:
Rebuild the fat jar and run the hello-mod again:
If you take a look at the log output, you will notice the world-mod was downloaded and installed by Vert.x at runtime. This works fine, but there are times when you need all dependencies pulled in before deployment (because of firewalls, private networks, etc.). This is made easy by Vert.x’s “pullInDeps” property. If you go to the gradle properties and set pullInDeps=true and add “deploys”:”com.objectpartners~world-mod~0.1 to the mod descriptor, world-mod will get downloaded and installed during build time instead of runtime.