Part 1 Creating a RestFull Interface in Vert.x

In this series of blog posts I will be explaining how you can create a reactive microservice using Vert.x and ReactiveX. With these types of posts, it is common to use a API that has some fictitious purpose. Because I worked on the Flight APIs of Schiphol (Dutch airport) and the required APIs are free. I will be creating a simple API that determines at what time and how you need to go to Schiphil to not miss your flight.

These days creating a rest interface in Java is easy, a lot of frameworks exist that do a lot of boiler plaiting for you. Vert.x is just like that, creating a rest interface in Vert.x is easy. It can be done with just a couple lines of code.

As mentioned in the article (link) a Vert.x application exists out of one or more verticles. These verticles are deployed on the event loop of vert.x. So without further ado let’s get cracking.

First, we need to create a Verticle that implements a rest interface. Vert.x has a need library for that so besides the normal Vert.x dependencies we must add the vert.x web dependency as well.

 
<properties> 
    <vertx.version><Latest and greatest></vertx.version> 
</properties> 
 

<dependencies> 
  <dependency> 
    <groupId>io.vertx</groupId> 
    <artifactId>vertx-core</artifactId> 
    <version>${vertx.version}</version> 
  </dependency> 

  <dependency> 
    <groupId>io.vertx</groupId> 
    <artifactId>vertx-web</artifactId> 
    <version>${vertx.version}</version> 
  </dependency> 
</dependencies> 

So, we have to dependencies, the vertx-core and vertx-web. These are all the dependencies we need for now.

You can create a verticle by implementing the Verticle interface. The easiest way to do this is by extending the AbstractVerticle class. There are several other verticle types, but the AbstractVerticle will do for our rest service.

The AbstractVerticle contains the start method which you need to implement. In this method you dictate what the verticle needs to do on startup. For our rest verticle this means that we need to define that the verticle is going to start a HTTP server with some routing options.

public class VertxRestService extends AbstractVerticle { 

  @Override 
  public void start(Future future) { 

      vertx.createHttpServer() 
          .requestHandler(createRouter()::accept) 
          .listen(8080, httpServerAsyncResult -> { 
              if (httpServerAsyncResult.succeeded()) { 
                  future.complete(); 
              } else { 
                  future.fail(httpServerAsyncResult.cause()); 
          } 		

      }); 

  } 

    .... 

}   

In the example above, I created a http server that listens to the port 8080. When this verticle is deployed it will start listening on that port. You will also notice that Vert.x uses a Future class in the signature.

Because everything is loosly coupled in Vert.x, even the deployment of the verticles itself you do not know when something is completed / deployed. However, in some scenarios you want to control what is being started when. Sometimes you want to wait for the deployment to be finished. For this the Future.class exists. You can start a verticle with the Future class in the signature (as seen in the example). When deploying the verticle the deployment is only done when the future.complete() method is called. In this case, when the httpserver has been started.

The second part of creating a Rest interface is the routing part. When creating a rest service, you must define the methods that the service offers, the GET, POST, PUT, etc methods. For this you need to implement the vert.x Router class.

private Router createRouter() { 

        Router router = Router.router(vertx); 
        router.get("/flight/:id/car").handler(routingContext -> { 
            routingContext.response().end("Here be dragons!"); 
        }); 
        router.get("/flight/:id/train").handler(routingContext -> { 
            routingContext.response().end("Here be dragons!"); 
        }); 
        return router; 
} 

This service supports 2 methods, it can calculate the time you need to leave when traveling by car or by train.

Now we are almost done, we have all that is required to run a rest service in Vert.x. The only thing that leaves us is the deployment.

Deploying and starting a Vert.x application is easy. The way I find the easiest is by using a main method that deploys the verticles.

public class VertxMain  { 
 

    private static final Logger logger = LogManager.getLogger(VertxMain.class); 
 

    public static void main(String... args){ 
        VertxOptions options = new VertxOptions(); 
        Vertx vertx = Vertx.vertx(options); 
 
        Consumer runner = clazz -> { 
            vertx.deployVerticle(clazz.getName(), stringAsyncResult -> { 
                if (stringAsyncResult.succeeded()){ 
                    logger.log(Level.INFO, "Succesfully deployed " + clazz.getSimpleName()); 
                } else { 
                    logger.log(Level.ERROR, "Failed to deploy" + stringAsyncResult.cause()); 
                } 
            }); 
        }; 

        Class[] clazzes = {VertxRestService.class}; 
 
        Stream.of(clazzes).forEach(runner); 

    } 

} 

The main method first instantiates an instance of Vertx. This is the core component and the start of every vertx application. You can instantiate the Vertx object in two ways. The regular and clustered. This means that you can create a clustered vertx application for extra flexibility and scalability. With the VertxOptions object you can configure your application.

A verticle can be deployed by calling the vertx.deployVerticle method. In the example I pass the class and a async result handler. With the result handler you can verify if the verticle has been deployed sucesfully. This is done with the above mentioned Future object. Each verticle that you create needs to be deployed in the Vertx instance.

That is it, we have our verticle with the rest interface and the httpserver. We have a main method that can deploy the verticle. The only thing we need to do is run the main method. This can ofcourse be done by creating the jar and running it in your JVM. But you can also run it from your IDE. once it is started you can test your rest interface by calling the get method.

The sources of this post can be found in my git repository here