My first Vert.x 3 Application

Let’s say, you heard some­one say­ing that Vert.x is awe­some. Ok great, but you may want to try it by your­self. Well, the next nat­ural ques­tion is “where do I start?”. This post is a good start­ing point. It shows how is built a very sim­ple vert.x ap­pli­ca­tion (noth­ing fancy), how it is tested and how it is pack­aged and ex­e­cuted. So, every­thing you need to know be­fore build­ing your own ground­break­ing ap­pli­ca­tion.

The code de­vel­oped in this post is avail­able on github. This post is part of the In­tro­duc­tion to Vert.x se­ries. The code of this post in in the post-1 branch.

Let’s start!

First, let’s cre­ate a project. In this post, we use Apache Maven, but you can use Gra­dle or the build process tool you pre­fer. You could use the Maven jar ar­che­type to cre­ate the struc­ture, but ba­si­cally, you just need a di­rec­tory with:

  1. a src/main/java di­rec­tory
  2. a src/test/java di­rec­tory
  3. a pom.xml file

So, you would get some­thing like:

.
├── pom.xml
├── src
│   ├── main
│   │   └── java
│   └── test
│       └── java

Let’s cre­ate the pom.xml file with the fol­low­ing con­tent:

<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>io.vertx.blog</groupId>
  <artifactId>my-first-app</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-core</artifactId>
      <version>3.0.0</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

This pom.xml file is pretty straight­for­ward:

  • it de­clares a de­pen­dency on vertx-core
  • it con­fig­ures the maven-​compiler-plugin to use Java 8.

This sec­ond point is im­por­tant, Vert.x ap­pli­ca­tions re­quire Java 8.

Let’s code!

Ok, now we have made the pom.xml file. Let’s do some real cod­ing… Cre­ate the src/main/java/io/vertx/blog/first/MyFirstVerticle.java file with the fol­low­ing con­tent:

package io.vertx.blog.first;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;

public class MyFirstVerticle extends AbstractVerticle {

  @Override
  public void start(Future<Void> fut) {
    vertx
        .createHttpServer()
        .requestHandler(r -> {
          r.response().end("<h1>Hello from my first " +
              "Vert.x 3 application</h1>");
        })
        .listen(8080, result -> {
          if (result.succeeded()) {
            fut.complete();
          } else {
            fut.fail(result.cause());
          }
        });
  }
}

This is ac­tu­ally our not fancy ap­pli­ca­tion. The class ex­tends AbstractVerticle. In the Vert.x world, a ver­ti­cle is a com­po­nent. By ex­tend­ing AbstractVerticle, our class gets ac­cess to the vertx field.

The start method is called when the ver­ti­cle is de­ployed. We could also im­ple­ment a stop method, but in this case Vert.x takes care of the garbage for us. The start method re­ceives a Future ob­ject that will let us in­form Vert.x when our start se­quence is com­pleted or re­port an error. One of the par­tic­u­lar­ity of Vert.x is its asyn­chro­nous / non-​blocking as­pect. When our ver­ti­cle is going to be de­ployed it won’t wait until the start method has been com­pleted. So, the Future pa­ra­me­ter is im­por­tant to no­tify of the com­ple­tion.

The start method cre­ates a HTTP server and at­taches a re­quest han­dler to it. The re­quest han­dler is a lambda, passed in the requestHandler method, called every time the server re­ceives a re­quest. Here, we just reply Hello ... (noth­ing fancy I told you). Fi­nally, the server is bound to the 8080 port. As this may fails (be­cause the port may al­ready be used), we pass an­other lambda ex­pres­sion check­ing whether or not the con­nec­tion has suc­ceeded. As men­tioned above it calls ei­ther fut.complete in case of suc­cess or fut.fail to re­port an error.

Let’s try to com­pile the ap­pli­ca­tion using:

mvn clean compile

For­tu­nately, it should suc­ceed.

That’s all for the ap­pli­ca­tion.

Let’s test

Well, that’s good to have de­vel­oped an ap­pli­ca­tion, but we can never be too care­ful, so let’s test it. The test uses JUnit and vertx-​unit - a frame­work de­liv­ered with vert.x to make the test­ing of vert.x ap­pli­ca­tion more nat­ural.

Open the pom.xml file to add the two fol­low­ing de­pen­den­cies:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-unit</artifactId>
  <version>3.0.0</version>
  <scope>test</scope>
</dependency>

Now cre­ate the src/test/java/io/vertx/blog/first/MyFirstVerticleTest.java with the fol­low­ing con­tent:

package io.vertx.blog.first;

import io.vertx.core.Vertx;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(VertxUnitRunner.class)
public class MyFirstVerticleTest {

  private Vertx vertx;

  @Before
  public void setUp(TestContext context) {
    vertx = Vertx.vertx();
    vertx.deployVerticle(MyFirstVerticle.class.getName(),
        context.asyncAssertSuccess());
  }

  @After
  public void tearDown(TestContext context) {
    vertx.close(context.asyncAssertSuccess());
  }

  @Test
  public void testMyApplication(TestContext context) {
    final Async async = context.async();

    vertx.createHttpClient().getNow(8080, "localhost", "/",
     response -> {
      response.handler(body -> {
        context.assertTrue(body.toString().contains("Hello"));
        async.complete();
      });
    });
  }
}

This is a JUnit test for our ver­ti­cle. The test uses vertx-​unit, so we use a cus­tom run­ner. vert.x-​unit makes easy to test asyn­chro­nous in­ter­ac­tions, which are the basis of vert.x ap­pli­ca­tions.

In the setUp method, we cre­ates an in­stance of Vertx and de­ploy our ver­ti­cle. You may have no­ticed that un­like the tra­di­tional JUnit @Before method, it re­ceives a TestContext. This ob­ject lets us con­trol the asyn­chro­nous as­pect of our test. For in­stance, when we de­ploy our ver­ti­cle, it starts asyn­chro­nously, as most Vert.x in­ter­ac­tions. We can­not check any­thing until it gets started cor­rectly. So, as sec­ond ar­gu­ment of the deployVerticle method, we pass a re­sult han­dler: context.asyncAssertSuccess(). It fails the test if the ver­ti­cle does not start cor­rectly. In ad­di­tion it waits until the ver­ti­cle has com­pleted its start se­quence. Re­mem­ber, in our ver­ti­cle, we call fut.complete(). So it waits until this method is called, and in the case of a fail­ures, fails the test.

Well, the tearDown method is straight­for­ward, and just ter­mi­nates the vertx in­stance we cre­ated.

Let’s now have a look to the test of our ap­pli­ca­tion: the testMyApplication method. The test emits a re­quest to our ap­pli­ca­tion and checks the re­sult. Emit­ting the re­quest and re­ceiv­ing the re­sponse is asyn­chro­nous. So we need a way to con­trol this. As the setUp and tearDown meth­ods, the test method re­ceives a TestContext. From this ob­ject we cre­ates an async han­dle (async) that lets us no­tify the test frame­work when the test has com­pleted (using async.complete()).

So, once the async han­dle is cre­ated, we cre­ate a HTTP client and emits a HTTP re­quest han­dled by our ap­pli­ca­tion with the getNow() method (getNow is just a short­cut for get(...).end()). The re­sponse is han­dled by a lambda. In this lambda we re­trieves the re­sponse body by pass­ing an­other lambda to the handler method. The body ar­gu­ment is the re­sponse body (as a buffer ob­ject). We check that the body con­tains the "Hello" String and de­clare the test com­plete.

Let’s take a minute to men­tion the as­ser­tions. Un­like in tra­di­tional JUnit tests, it uses context.assert.... In­deed, if the as­ser­tion fails, it will in­ter­rupt the test im­me­di­ately. So it’s pretty im­por­tant to al­ways uses these as­ser­tion meth­ods be­cause of the asyn­chro­nous as­pect of the Vert.x ap­pli­ca­tion and so tests.

Our test can be run from an IDE, or using Maven:

mvn clean test

Packaging

So, let’s sum up. We have an ap­pli­ca­tion and a test. Well, let’s now pack­age the ap­pli­ca­tion. In this post we pack­age the ap­pli­ca­tion in a fat jar. A fat jar is a stand­alone ex­e­cutable Jar file con­tain­ing all the de­pen­den­cies re­quired to run the ap­pli­ca­tion. This is a very con­ve­nient way to pack­age Vert.x ap­pli­ca­tions as it’s only one file. It also make them easy to ex­e­cute.

To cre­ate a fat jar, edit the pom.xml file and add the fol­low­ing code just be­fore </plugins>:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>2.3</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <transformers>
          <transformer
            implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <manifestEntries>
              <Main-Class>io.vertx.core.Starter</Main-Class>
              <Main-Verticle>io.vertx.blog.first.MyFirstVerticle</Main-Verticle>
            </manifestEntries>
          </transformer>
        </transformers>
        <artifactSet/>
        <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar</outputFile>
      </configuration>
    </execution>
  </executions>
</plugin>

It uses the maven-​shade-plugin to cre­ate the fat jar. In the manifestEntries it in­di­cates the name of our ver­ti­cle. You may won­der from where comes the Starter class. It’s ac­tu­ally a class from vert.x, that is going to cre­ate the vertx in­stance and de­ploy our ver­ti­cle.

So, with this plug­in con­fig­ured, let’s launch:

mvn clean package

This is going to cre­ate target/my-first-app-1.0-SNAPSHOT-fat.jar em­bed­ding our ap­pli­ca­tion along with all the de­pen­den­cies (in­clud­ing vert.x it­self).

Executing our application

Well, it’s nice to have a fat jar, but we want to see our ap­pli­ca­tion run­ning! As said above, thanks to the fat jar pack­ag­ing, run­ning Vert.x ap­pli­ca­tion is easy as:

java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar

Then, open a browser to http://lo­cal­host:8080.

To stop the ap­pli­ca­tion, hit CTRL+C.

Conclusion

This Vert.x 3 crash class has pre­sented how you can de­velop a sim­ple ap­pli­ca­tion using Vert.x 3, how to test it, pack­age it and run it. So, you now know every­thing you need to build amaz­ing sys­tem on top of Vert.x 3. Next time we will see how to con­fig­ure our ap­pli­ca­tion.

Happy cod­ing & Stay tuned !

Next post

Vert.x Application Configuration

In our previous post, we developed a very simple Vert.x 3 application, and saw how this application can be tested, packaged and executed. That was nice, wasn’t it?

Read more
Previous post

Vert.x 3 says “hello” to NPM users

In programming literature it has become the standard to create a hello world program as the first example. In this article, I'll demonstrate how NPM users can quickly get started with Vert.x.

Read more
Related posts

Unit and Integration Tests

Let’s refresh our mind about what we developed so far in the introduction to vert.x series. We forgot an important task. We didn’t test the API.

Read more

Some Rest with Vert.x

This post is part of the Introduction to Vert.x series. Let’s go a bit further this time and develop a CRUD-ish application

Read more

Using the asynchronous SQL client

Finally, back... This post is the fifth post of the introduction to vert.x blog series, after a not-that-small break. In this post we are going to see how we can use JDBC in a vert.x application.

Read more