REST API without Java Servlets

Using Vert.x, RxJava and Postgresql

This article is a step by step tutorial which explains how to develop a simple REST API using Vert.x as the HTTP request handler and Postgresql as the database backend. Full source code for this tutorial can be found here if someone wants to directly jump in to the source code.

Following is the simple business user story considered in this API implementation.

As an API consumer, I should be able to create a new vehicle owner in the system by providing following information. 
- First name
- Last name
- NIC
- Contact Numbers [Mobile, Office, Home]
To create successful vehicle owner resource, First name, Last name, NIC and at-least a single contact number should be sent.

Make sure business logic and domain model is tested

First, we will create a simple domain model to implement the above business rules.

Domain Model — Vehicle Owner

After few TDD iterations VehicleOwner, ContactNumbers and Address domain classes were implemented with the support of VehicleOwnerTest and ContactNumbersTest unit test classes. I used JUnit 5 as the unit test framework. Refer my previous article — What I like most in JUnit 5- to get to know more about the reason.

Expose REST API

Now we will focus on the externally exposing part of this application — the REST API. This API is implemented using Vert.x. Vert.x is not a Servlet based HTTP listening framework. Actually, it is an event-driven application framework which runs on JVM. Architecture of Vert.x is similar to Node. I hope following simple digram will give you a head start to understand how Vert.x do the same which Servlet does with HTTP requests.

How Vert.x handles HTTP Requests

Let’s start from AdminToolsVerticle which acts as the triggering point of the application. It extends AbstractVerticle from core Vert.x library. AdminToolsVerticle's start() method does few important things:

  1. Starts a HTTP server to listen to all the HTTP requests.
  2. Register all the Routes need to be exposed from this Verticle.
  3. Creates a JDBC Client.

Above I mentioned AdminToolsVerticle class is the starting point of the application. But, Java runtime does not know about that. We have to instruct Java runtime to run the application from start() method. Instructions need to be given in the build.gradle as shown below.

Next we will see how Vehicle Owner resource APIs are defined in VehicleOwnerRoute class. There is nothing complex when it comes to register routes in Vert.x, but if you miss following line in your route, you will waste few minutes debugging the error for requests which contains a body payload.

router.route("/api/resource*").handler(BodyHandler.create());

Integrate with Database

In AdminToolsVerticle, we initiated Jdbc client. Since we are hoping to use RxJava in service layer classes, Jdbc client should be initialized with RxJava Vert.x instance.

At last, VehicleOwnerService does the last bits. It saves newly created VehicleOwner object to the database.

For this simple application, we need to create a single table to persist Vehicle Owners. Following is the DDL for creating vehicle_owner table in Postgres.

Run the Verticle

Finally, we are ready to expose our Vehicle Owner REST API to the consumers. We are few steps behind.

  1. Build the fat jar file using Shadow Jar Gradle plugin.
     ./gradlew shadowJar
  2. Then run the fat jar file. 
    java -jar build/libs/majan-admintools-api-1.0-SNAPSHOT-fat.jar
  3. Then use your favourite REST client to send following request to create new Vehicle Owner resource.
POST /api/vehicleowners HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 3eb1e239-769f-a9d8-8c13-297480fa7c5c
{
"firstName": "Kasun",
"lastName":"Dilunika",
"nic":"84544454445",
"contactNumbers" : {
"mobileNumber": "07772323232"
}
}

You will receive 201 HTTP response with no content.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.