Contract Driven REST Services with Vert.x3
We see a new trend in development where we are shifting from developing applications to develop APIs. More and more we see services being offered as REST APIs that we are allowed to consume and we already see this trend from the big names in the industry, e.g.: Facebook, Wikipedia, Amazon, Twitter, Google and Reddit they all offer APIs.
Of course making an REST API using Vert.x is quite simple, just use Vert.x Web and you can start writing your API in seconds, however an API without documentation is not an API since no developer will know how to use it. However this is one of the most sensitive issues to tackle in software development, nobody likes to write documentation. However, in the REST age where REST-based web-services are ubiquitous, documentation for public web-services is a necessity. There are a lot of tools out there, two of the most popular are without a doubt:
Both frameworks have a large ecosystem of tools and tooling around but they tackle the documentation from two different perspectives. While Swagger is purely a documentation tool it tackles the problem from bottom up and RAML does document top down. They both rely on a document (JSON
for Swagger, YAML
for RAML).
I’ll now go over building a simple Hello World API, document it and test it. For this example I’ll choose RAML since it feels more natural to the way we code with Vert.x Web.
Define the Hello World API
We need a contract and as with any other development we need some specification, You can learn about RAML in its website and quickly see how easy it is to get started. So we start with the following specification:
So if you didn’t understood why I named RAML as a top down documentation tool, I think it becomes clear now. So there are some basic definition on the top of the file like, title
, baseUri
and version
which should be self explanatory.
And then we start with the API documentation, so we specify that at the URL
/hello
using the HTTP verb GET
you are expected to get a response with status code 200
and the body of the response should have content type application/json
. This is a very minimal document, one could go over and specify the json schema
for the response, input values, etc…, however lets just keep it simple for this example.
If you do not like to write yaml in your editor you can always use the API Designer which gives you instant feedback on your API document and provides a testing platform.
Implement the API
So you got your contract, time to implement it, this is a very simple API so I’ll jump to the code immediately:
As you can see the code resembles the contract document, when there is a GET
request to /hello
we send to the client a empty JSON
document {}
.
Are we done?
The answer is NO!!! how can we be sure that our implementation does comply to the contract? We need to test. As I wrote before there is no specific support for Vert.x from RAML or other tools however in this case it is not a problem we can still test our code without having the need to implement a test framework from the ground up.
Testing our contract
The initial step is to setup a test, this should be trivial we are using Java (although we could test any of Vert.x supported languages using the same technique). We create a JUnit unit test.
For this example, I will be using JUnit instead of Vert.x Test mostly to let you know that Vert.x isn’t an opinionated framework, so you are free to choose the tool that best fits you.
So at this moment you have a simple test, I’ll share the code of the runner class (basically it just instantiates a
Vertx
instance and load the verticle
we just implemented above) and has a empty test testHelloEndpoint
.
Load the API definition into the test
So the first step is to load the API
definition into our test and have a reference to a CheckingWebTarget
object. The checking object is where you can perform assertions, but to do this we need some client make REST calls in order to test.
Create a REST client
There are many options for this, you could use JAX-RS
, RestAssured
, RestEasy
, etc… so I’ll pick RestEasy
for now:
Implement the test
All of the boilerplate code is in place and if you look at the previous section you will see that it wasn’t that bad, just a few lines and you loaded the RAML contract, created a REST client and started up your application and all this under ~10 lines of code.
So lets finish and implement the verification of the contract:
Once you run your tests, you will see:
And we are done, we now have a API that follow the contract, you can now keep developing your API and implementation and have a test driven approach to be sure that the contract is not broken.
Next steps
Until now you have learn how to integrate RAML into Vert.x and CI, however the users of your API will not be able to know much about the API yet since its documentation is not publicly available. So lets publish online the documentation of your API, of course if your API is private you do not need to follow these steps.
In order to do this all we need it to include in our application the RAML console, the fastest way to do this is just download a release to src/main/resouces/webroot
and in the original application Vert.x Router we add a Static Content Handler to serve the console files. Your application source code should look like this:
Once you start you application open a browser pointing at the console. Once you do that you should be presented with something similar to this:
Article source code
You can get the full source code for this article here.