Vert-x

Building a Vert-x application with JBoss Forge

Vert.x is a framework which is made up of several different components designed to make it easier for you to write compelling reactive applications, using a range of different languages. In this tutorial we will make use of JBoss Forge to quickly set up a Vert.x basic example.

So first of all you need to know that Vert.x is not an all-or-nothing framework but an highly modular library and you just use the bits that you need and nothing more, nothing less. As a matter of fact, Vert.x is a library and not a restrictive container so you aren't forced to use only the components provided by Vert.x. You can also use Vert.x with all the usual libraries that you like.

The Vert.x core contains fairly low level functionality including support for HTTP, TCP, file system access, and various other features. You can use this directly in your own applications, and it's used by many of the other components of Vert.x. In this example we will show how to create a simple HTTP Server with a Java Verticle class and then we will augment if a bit by turning our Web server into a REST Server.

Not using JBoss Forge ? then you can manually create a quickstart Maven project and add the pom.xml file (described later in this article ) to the root of your project along with Java classes.

So first of all start JBoss Forge and install the forge add-on:

addon-install --coordinate me.escoffier.forge:vertx-forge-addon

Next, the vert.x project type will be enabled so you will be able to create your first vert-x project:

project-new --named demo-vertx --type vert.x --vertx-version 3.3.3

In a couple of seconds, Forge will configure the vertx-maven-plugin:

Configuring the vertx-maven-plugin...
maven-compiler-plugin already configured in the `pom.xml`, updating configuration...
vertx-maven-plugin is already configured in the `pom.xml` file - skipping its configuration
***SUCCESS*** Project named 'demo-vertx' has been created.
***SUCCESS*** Vert.x project created successfully

A maven project with the required dependencies will be created. A demo verticle will be created as well.

A Verticle is the main component that you can deploy to Vert.x. In a way it's similar to other JEE components like EJBs or Servlet, however Verticles they communicate with each other by sending messages over the EventBus.

Forge lets you create new verticles with the vertx-add-verticle command as follows:

vertx-add-verticle --name DemoVerticle.java --type java        

Let's see the Java verticle which has been just created:

package org.demo.vertx;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.*;

public class DemoV extends AbstractVerticle {

	@Override
	public void start() {
		vertx.createHttpServer()
				.requestHandler(req -> req.response().end("Hello World!"))
				.listen(8080);
	}
}

So this class extends the io.vertx.core.AbstractVerticle class to define your Verticle class.

In the simplest case, just override the start() method that will be invoked to boostrap your Verticle. If you have verticle clean-up to do you can optionally override the stop() method too.

In our example, we are simply using the built-in createHttpServer function from the core vert-x.

Additionally, Forge will create a sample Unit test for your Verticle:

package org.demo.vertx;

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;
import org.demo.vertx.DemoV;
import static junit.framework.TestCase.fail;

@RunWith(VertxUnitRunner.class)
public class DemoVTest {

	private Vertx vertx;

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

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

	@Test
	public void myAppTest(TestContext context) {
	}
}

In order to build your project, Forge will automatically include in your pom.xml the io.vertx dependencies and the vertx.maven-plugin:

<?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>org.demo.vertx</groupId>
   <artifactId>demo-vertx</artifactId>
   <version>1.0.0-SNAPSHOT</version>
   <build>
      <finalName>demo-vertx</finalName>
      <plugins>
         <plugin>
            <artifactId>vertx-maven-plugin</artifactId>
            <groupId>io.fabric8</groupId>
            <configuration>
               <redeploy>true</redeploy>
            </configuration>
            <version>1.0.1</version>
            <executions>
               <execution>
                  <id>vertx</id>
                  <goals>
                     <goal>initialize</goal>
                     <goal>package</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
               <source>1.8</source>
               <target>1.8</target>
            </configuration>
         </plugin>
      </plugins>
   </build>
   <properties>
      <vertx.version>3.3.3</vertx.version>
      <vertx.verticle>org.demo.vertx.MainVerticle</vertx.verticle>
   </properties>
   <dependencies>
      <dependency>
         <groupId>io.vertx</groupId>
         <artifactId>vertx-core</artifactId>
      </dependency>
      <dependency>
         <groupId>io.vertx</groupId>
         <artifactId>vertx-unit</artifactId>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>
         <scope>test</scope>
      </dependency>
   </dependencies>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-dependencies</artifactId>
            <version>${vertx.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>
</project>

Now build your project with:

$ mvn clean install

In order to run it, you can either execute a:

$ java -jar demo-vertx.jar 

Or, if you have configured in your vert-x maven plugin the main verticle class:

mvn vertx:run

Let's test it!

$ curl http://localhost:8080
Hello World!

Nothing fancy, however it works!

Coding a simple REST Service with Vert-x

We will now run a bit more advanced example which will leverage a REST Service. This service, exposes a @GET Resource which will print out the parameter passed on the PATH URL of your Web application:

package org.demo.vertx;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;

@Path("/")
public class HelloWorldService {

  @GET
  @Path("/{name:.*}")
  public Response doGet(@PathParam("name") String name) {
    if (name == null || name.isEmpty()) {
      name = "World";
    }
    return Response.status(200).entity("Hello " + name).build();
  }
}

Some changes will be required in your Verticle as well to build the JAX-RS controller deployment, adding to the JAX-RS registry the HelloWorldService:

package org.demo.vertx;

import io.vertx.core.AbstractVerticle;
import org.jboss.resteasy.plugins.server.vertx.VertxRequestHandler;
import org.jboss.resteasy.plugins.server.vertx.VertxResteasyDeployment;

public class DemoV extends AbstractVerticle {

  @Override
  public void start() throws Exception {

    VertxResteasyDeployment deployment = new VertxResteasyDeployment();
    deployment.start();
    deployment.getRegistry().addPerInstanceResource(HelloWorldService.class);

    // Start the front end server using the Jax-RS controller
    vertx.createHttpServer()
        .requestHandler(new VertxRequestHandler(vertx, deployment))
        .listen(8080, ar -> {
          System.out.println("Server started on port "+ ar.result().actualPort());
        });

  }
}

In order to be able to build it, you need to include resteasy vert-x dependency:

<dependency>
   <groupId>org.jboss.resteasy</groupId>
   <artifactId>resteasy-vertx</artifactId>
   <version>3.1.0.Final</version>
</dependency>

Let's test it!

$ curl http://localhost:8080/Frank
Hello Frank

Follow us on Twitter