Archive for the ‘vert.x’ Category

Starting with Vert.x 3 – Creating a new project
April 11, 2015

These are my first impressions on what have changed in Vert.x 3 from a regular java developer perspective.

Vert.x 3 has ripped off the old modules concepts in favor of a more straightforward approach. Now you don’t need to create a .zip file with an structure to deploy your application, instead, you run your application inside vert.x however you want. These is a great power and at first I found myself a little lost.

You can still download a vert.x distribution but, with the current state of the platform, I see it like an easy way to start making experiments (even in the many languages vert.x support) and it’s not necessary anymore for productive environments.

In Vert.x 3 you create your own main function, invoke a Vert.x factory, and voilà, you have the whole platform there to serve you. Indeed, you can see the io.vertx.core.Starter class, which is invoked by the executable bin/vertx in the distribution, to see there is nothing but CLI args parsing and building configurations for the factory I mentioned before.

From the v2 era I liked to have a main point written in javascript to deploying all my java verticles. I though it as my init script so it made sense to have it in an scripting language, I didn’t want to lose that. So now it’s my responsibility to create this structure. A few lines of code is worth a thousand words:
(Deprecated: see Update section below)

    public class Launcher {
        public static void main(String[] args) {
            Logger vertxLogger = LoggerFactory.getLogger(Launcher.class.getName());
            Vertx vertx = Vertx.vertx();
            vertx.deployVerticle("main.js", event -> {
                if (event.succeeded()) {
                    vertxLogger.info("Your Vert.x application is started!");
                } else {
                    vertxLogger.error("Unable to start your application", event.cause());
                }
            });

            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    final CountDownLatch latch = new CountDownLatch(1);
                    vertx.close(ar -> {
                        if (ar.succeeded()) {
                            vertxLogger.info("Your Vert.x application is stopped!");
                        } else {
                            vertxLogger.error("Failure in stopping Vert.x", ar.cause());
                        }
                        latch.countDown();
                    });
                    try {
                        if (!latch.await(2, TimeUnit.MINUTES)) {
                            vertxLogger.error("Timed out waiting to undeploy all");
                        }
                    } catch (InterruptedException e) {
                        throw new IllegalStateException(e);
                    }
                }
            });
        }
    }

In line 5 I deploy my main verticle.
Lines 13-32 are stolen from io.vertx.core.Starter to properly shutdown the application.

For this to run you just need a few dependencies: io.vertx:vertx-core:jar:3.0.0-milestone4:compile and io.vertx:vertx-lang-js:jar:3.0.0-milestone4:runtime

Packing your application

Now it’s just a matter of packing the application to make it runnable. There is a movement loving the concept of fatJar, I personally dislike it for various reasons, one of them is that I see it completely unnecessary, we are advanced Java developers, man up, setup you classpath and invoke the Main Class as the good lord says (well, that was too much).

In Maven this is extra easy, you just need to properly setup the maven-jar-plugin to write the MANIFEST and the maven-assembly-plugin to load an assembly descriptor. Then you can have a simple run.sh script for running it without even having to remember the name of your main jar. I use something like this:

    #!/usr/bin/env bash
    DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
    java -jar $DIR/libs/${project.build.finalName}.${project.packaging} $@

Here is a minimal pom.xml briefing all the above ideas:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

      <modelVersion>4.0.0</modelVersion>
      <groupId>com.locademiaz</groupId>
      <artifactId>initial-vertx-3-project</artifactId>
      <version>0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <dependencies>
        <dependency>
          <groupId>io.vertx</groupId>
          <artifactId>vertx-core</artifactId>
          <version>${vertx.version}</version>
        </dependency>
        <dependency>
          <groupId>io.vertx</groupId>
          <artifactId>vertx-lang-js</artifactId>
          <version>${vertx.version}</version>
          <scope>runtime</scope>
        </dependency>
      </dependencies>
    
      <build>
        <resources>
          <resource>
            <directory>src/main/js</directory>
          </resource>
        </resources>
        <plugins>
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.3</version>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.6</version>
            <configuration>
              <archive>
                <manifest>
                  <mainClass>com.locademiaz.Launcher</mainClass>
                  <addClasspath>true</addClasspath>
                </manifest>
              </archive>
            </configuration>
          </plugin>
          <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.5.3</version>
            <configuration>
              <descriptor>src/main/assembly/dist.xml</descriptor>
            </configuration>
            <executions>
              <execution>
                <id>make-assembly</id>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>

      <properties>
        <vertx.version>3.0.0-milestone4</vertx.version>
      </properties>
    </project>

And also the dist.xml:

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
      <id>dist</id>
      <formats>
        <format>tar.gz</format>
      </formats>
      <baseDirectory>${project.artifactId}</baseDirectory>
      <dependencySets>
        <dependencySet>
          <outputDirectory>libs/</outputDirectory>
          <scope>runtime</scope>
        </dependencySet>
      </dependencySets>
      <files>
        <file>
          <source>${project.build.directory}/${project.build.finalName}.${project.packaging}</source>
          <outputDirectory>libs/</outputDirectory>
          <fileMode>0664</fileMode>
        </file>
        <file>
          <source>src/main/sh/run.sh</source>
          <fileMode>0744</fileMode>
          <filtered>true</filtered>
        </file>
      </files>
    </assembly>

With this initial configuration, you run mvn package and you’ll got a tarball into the target/ folder, untar it and you’ll have a nice running script for your whole application.

Bonus track

I prefer to use Logback as my logging system, and in the old days we had to modify the vert.x distribution and the executable to get this support.
Nowadays you just add System.setProperty(LoggerFactory.LOGGER_DELEGATE_FACTORY_CLASS_NAME, SLF4JLogDelegateFactory.class.getName()); as the first line of your main, add the ch.qos.logback:logback-classic:jar:1.1.3:runtime dependency and you are there.
For the extra lazy, here is a simple logback.xml:

    <configuration>
      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender" level="INFO">
        <encoder>
          <pattern>[%-5level] %logger{15} - %msg%n</pattern>
        </encoder>
      </appender>
    
      <logger name="io.vertx" level="INFO">
        <appender-ref ref="STDOUT" />
      </logger>
      <logger name="com.hazelcast" level="ERROR">
        <appender-ref ref="STDOUT" />
      </logger>
      <logger name="io.netty.util.internal.PlatformDependent" level="ERROR">
        <appender-ref ref="STDOUT" />
      </logger>
      <root level="INFO">
      </root>
    </configuration>

I also like to have an user accessible logging configuration, for this, you must add the following to the dist.xml file

        <file>
          <source>src/main/resources/logback.xml</source>
          <fileMode>0644</fileMode>
        </file>

and modify the java invocation line in run.sh to include -Dlogback.configurationFile=file:$DIR/logback.xml

I hope you find this useful and enjoy the great things Vert.x 3 has to offer.

UPDATE:

I’ve been thinking and I rather see unnecessary to have my own main class which at the end will imitate the provided io.vertx.core.Starter. So I’ve simplified my initial deployment removing all references to my custom mainClass and with this run.sh

    #!/usr/bin/env bash
    DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
    java -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.impl.SLF4JLogDelegateFactory \
         -Dlogback.configurationFile=file:$DIR/logback.xml \
         -classpath "$DIR/libs/*" io.vertx.core.Starter run main.js \
         -conf $DIR/conf.json

Also, if you want to run your application using maven (useful for debugging) you just need to configure the org.codehaus.mojo:exec-maven-plugin like this:

    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>1.4.0</version>
      <configuration>
        <mainClass>io.vertx.core.Starter</mainClass>
        <systemProperties>
          <systemProperty>
            <key>vertx.logger-delegate-factory-class-name</key>
            <value>io.vertx.core.logging.impl.SLF4JLogDelegateFactory</value>
          </systemProperty>
        </systemProperties>
        <arguments>
          <argument>run</argument>
          <argument>main.js</argument>
          <argument>-conf</argument>
          <argument>${project.build.outputDirectory}/conf.json</argument>
        </arguments>
      </configuration>
    </plugin>
Advertisements

Vert.x – Async architectures presentation
February 13, 2015

I gave this presentation on 2014, in Japan at Rakuten and in Buenos Aires at IT Crowd Argentina Talks.

Hope you enjoy it.

Handling multiple verticle deployment
April 4, 2014

Every Vert.x module needs a single point of start.
Once your application has many verticles interacting you’ll need one verticle to start them all, one verticle to find them, one verticle to bring them all and in the darkness bind them (I’m sorry).
For this particular task I prefer to use javascript. I tend to think of this verticle as the start script of my application, so I like it to be easy to write and I found the javascript syntax to be a good fit on this.

My deployment verticle

I usually name it app-deployer.js and I place it in src/main/javascript (I’ll explain below how to add it to Maven).

var container = require("vertx/container")
var console = require("vertx/console")
var config = container.config;

var skipDeploy;
if (config.skipDeploy) {
  skipDeploy = config.skipDeploy;
} else {
  skipDeploy = [];
}

const verticles = [
  {
    name : "con.locademiaz.vertx.FirstVerticle",
    instances : 1,
    config : {
      foo_param : config.bar_param
    }
  }
];

deployVerticles(verticles, 0);

function deployVerticles(verticles, verticleIndexToDeploy) {
  if (verticleIndexToDeploy < verticles.length) {
    const verticle = verticles[verticleIndexToDeploy];
    const verticleName = verticle.name;
    if (skipDeploy.indexOf(verticleName) == -1 ) {
      container.deployVerticle(
        verticleName,
        verticle.instances,
        verticle.config,
        function(err, deployID) {
          if (!err) {
            console.log("[Ok] " + verticleName);
            deployVerticles(verticles, verticleIndexToDeploy + 1);
          } else {
            console.log("[Fail] " + verticleName + " -> " + err.getMessage());
          }
        }
      )
    } else {
      console.log("[Skip] " + verticleName);
      deployVerticles(verticles, verticleIndexToDeploy + 1);
    }
  }
}

In this file you can do all kinds of tricks.
One of my preferred ones is to add a list of blacklisted verticles. This is useful for testing because you can deploy this file, getting your all system deployed, and mock some behavior inside your test.
Also, as I like to keep my external configuration lean, it is here where I manipulate what is passed by the command line and adapt it to each verticle needs.

Extending your Maven configuration

Following what is explained in my previous post this is how you add your verticle deployer to your Maven configuration

pom.xml

Add the resource folder

<project>
  ...
  <build>
    ...
    <resources>
      ...
      <resource><directory>src/main/javascript</directory></resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>

And now, because I’m a control freak, I don’t like unnecessary files ends up in the jar for my project, so I exclude them from the package as follows:

<project>
  ...
  <build>
    ...
    <plugins>
      ...
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.4</version>
        <configuration>
          <excludes>
            <exclude>app-deployer.js</exclude>
          </excludes>
        </configuration>
      </plugin>
      ...
    </plugins>
    ...
  </build>
  ...
</project>

And that’s it, now you have a nice entry point for your module.
Enjoy.
.

Vert.x Java project – Quick start
April 3, 2014

After having 41 successful-n-productive™ Vert.x systems running, I have distilled a few practices which makes worth to share.

Building environment

I’ve decided to go with Maven for managing dependencies and build cycle. Vert.x has support for Gradle but I dropped this option because I just wanted a simple descriptive language for my project, instead of a full imperative language for this purpose. Nothing against Gradle though.

Vert.x modules

Vert.x recommends to organize your application as modules. Beside all the technical benefits of this practice (classloader isolation, dependency management, etc), I would also like to add that this is a great way to define different areas of development across your team. This, along with a clear document of the services provided and exposed by the modules within its interfaces, will help you to isolate different application concerns as the building blocks for the whole system.

Initial setup

Vert.x has a Maven Archetype for getting started, but IMHO it doesn’t do well with Maven files, and it also generates a single project containing examples for every supported language. BTW, I’ve sent a pull request for this, that has never discussed.
This post will assume you have some knowledge of Maven, its structure and usage.

pom.xml

You can read an in depth explanation of the structure of this file here (this is not yet ready)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.locademiaz.vertx</groupId>
  <artifactId>quick-start</artifactId>
  <version>0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <dependencies>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-platform</artifactId>
      <version>2.1M2</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>testtools</artifactId>
      <version>2.0.2-final</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
      <resource>
        <directory>src/main/js</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>src/test/resources</directory>
        <filtering>true</filtering>
      </testResource>
    </testResources>

    <plugins>
      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>2.5.1</version>
         <configuration>
           <source>1.7</source>
           <target>1.7</target>
         </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.4</version>
        <configuration>
          <outputDirectory>${project.build.directory}/mods</outputDirectory>
          <finalName>${module.name}</finalName>
          <appendAssemblyId>false</appendAssemblyId>
          <descriptors>
            <descriptor>src/main/assembly/mod.xml</descriptor>
          </descriptors>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-maven-plugin</artifactId>
        <version>2.0.1-final</version>
      </plugin>
    </plugins>
  </build>
  <properties>
    <module.name>${project.groupId}~${project.artifactId}~${project.version}</module.name>
  </properties>
</project>
mod.xml

Vert.x defines a structure for its modules, so, below is a Maven Assembly definition for building it. In concordance with the pom.xml defined above, this must be placed in the src/main/assembly directory.

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">

  <id>mod</id>

  <formats>
    <format>zip</format>
    <format>dir</format>
  </formats>
  <dependencySets>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <outputDirectory>lib/</outputDirectory>
      <scope>runtime</scope>
      <fileMode>664</fileMode>
    </dependencySet>
  </dependencySets>

  <includeBaseDirectory>false</includeBaseDirectory>

  <fileSets>
    <fileSet>
      <directory>${project.build.outputDirectory}</directory>
      <outputDirectory>/</outputDirectory>
      <includes>
        <include>**</include>
      </includes>
    </fileSet>
  </fileSets>
</assembly>
Your first verticle

Now we have everything setup to start coding. Create a FirstVerticle.java file inside the src/main/java/com/locademiaz/vertx directory with the following content:

package com.locademiaz.vertx;

import org.vertx.java.platform.Verticle;

public class FirstVerticle extends Verticle {

    @Override
    public void start() {
        container.logger().info("Your first verticle has been started!");
    }
}
mod.json

The final part of a Vert.x module is its descriptor. You can find a comprehensive list of its fields here. Place this file in the src/main/resources directory

{
    "main":"com.locademiaz.vertx.FirstVerticle",
    "deploys":"${module.name}",
}

Running your module

Development phase

As you can see in the pom.xml file above the vertx-maven-plugin is configured in lines 72-76. Having this configured, allows you to run, directly from your source code, Vert.x with your module just in place. For doing so just run:

$ mvn clean package vertx:runMod

et voilà, you should see the message logged into the system console

Productive phase

As presented here, the .zip generated in the target/mods by the command

$ mvn clean package

is ready to be deployed. You can drop it into your Nexus repository, or into your local maven structure, or you can also use the handy runzip option:

$ vertx runzip target/mods/com.locademiaz.vertx~quick-start~0.1-SNAPSHOT.zip

In the upcoming entries you can expect more insights about handling deployment, configuration, vert.x packaging, testing, continuous integration and any other shenanigan I encounter in this pleasant trip. Stay tuned.