I recently started playing with Ratpack.  

It's a set of Java libraries for buiding modern HTTP applications.

To go beyond that simple definition, Ratpack is non-blocking, asynchronous and netty-based. A bit like our Java SDK. So it comes as a natural candidate for a lightweight application framework.

One of the first thing you can do when testing a new web framework is create a basic API. And building a simple CRUD comes naturally when you work with a document database like Couchbase. So this post is a basic intro to Ratpack showcasing the Couchbase entity repository abstraction available with our Java SDK. I will not focus on the API itself here, but more on the mechanism used in Ratpack and the Couchbase repository.

Creating a Ratpack Java Project

Most of the Ratpack users I know tend to code with Groovy. I am usually coding in Java so this is what I am going to use today. The quickstart guides you'll find for Ratpack will feature Groovy though. The lazybones template is a Groovy one for instance. So I started by generating a simple Java Gradle project in my favorite IDE. Then I opened the build.gradle file and completed it with the right dependencies. I added the jcenter repository, a dependency to ratpack-gradle 1.3.3 and made sure I was using the io.ratpack.ratpack-java plugin. And let's not forget the Couchbase dependency.

The next step is to start the app with a simple Hello World. I have an Application class as you can see on the build file above with the mainClassName option. All I am going to do here for starter is spin up the Ratpack server and register the '/hello' URL path to return a Hello World message.

Ratpack has Handlers objects. A Handler is a function with a Context as parameter. You can associate a handler with a path. So here I am going to associate a Handler function to the '/hello' path. To understand Ratpack you have to understand handlers as you will use them in all your applications.

The entrypoint in a Ratpack application is the RatpackServer class. From this class you can use the static method start. It takes a function with a RatpackServerSpec object as parameter. This object gives you a fluent API to configure the server. The only thing I need to do here is add my handler. The handlers method takes a function with a Handler Chain as parameter. From that chain I can create my handler:

When I start the application and go to localhost:5050/hello, I get my hello message. Moving on to the Couchbase part.

The Couchbase Entity Model

The entity model appeared with version 2.2.x. You can declare entity easily using the Couchbase annotation @Id. You also need to make sure that your entity class has a public, zero arg constructor and that setter and getter are available for the fields you want in the resulting JSON document. To model a user with a username, age, first name and last name, I use the following User class:

The @Id annotation is mandatory and defines the field that will be used as key of your document. You can use the @Field annotation to change the name of the properties in your resulting JSON document. Note also that the @Id field won't be in the JSON.

This Entity class has to be used with the EntityDocument. It's very similar in use with the other document implementations available with the SDK. The following code will create a JSON document in Couchbase:

Which create the following document:

Key: ldoguin

Value: { “lName”: “Doguin”, “age”: 31, “fName”: “Laurent” }

This code is currently blocking and synchronous. Is this a bad thing? It depends :) If you are running blocking code in a non-blocking thread, like you would do if it was running in place of the hello world above, than you are blocking everything else. And yes that would be a bad thing. Because this thread manages the event loop that handles all the requests. I found this blog post quite useful to understand this.

One of Ratpack's goal is to help you use blocking code in an async, non-blocking handler. Ratpack uses Promise as a way to manage asynchronous code. And it also gives you a Blocking primitive that takes a function as argument and return a promise. The function will execute the blocking code. Here I have an example that creates a user when hitting the localhost:5050/create URL and returns it when hitting the localhost:5050/get URL:

Taking aside the fact that this is probably the worst designed API ever, this should give you an idea on how you can run blocking, synchronous code in an async handler with Ratpack. Which is the first step to migrate an existing application to Ratpack.

But then this example does not really showcase all the goodness that is our RxJava based SDK. So in the next post I will show you how to use RxJava and Ratpack together with the Async version of the Repository.

Author

Posted by Laurent Doguin, Developer Advocate, Couchbase

Laurent is a Paris based Developer Advocate where he focuses on helping Java developers and the French community. He writes code in Java and blog posts in Markdown. Prior to joining Couchbase he was Nuxeo’s community liaison where he devoted his time and expertise to helping the entire Nuxeo Community become more active and efficient.

Leave a reply