A simple Http Service using Java and Finagle

Finagle has always been my top choice to build all my Scala projects, it has an incredible ecosystem and is maintained by awesome people.

Not long ago I had to build a POC using Java, and I chose to give Finagle a try for the first time in one of my Java projects,  boy I struggled 😂, the lack of documentation and the verboseness of using Scala APIs in Java made me struggle a good amount. Later I decided to contribute with an example of HTTP service in java; https://github.com/twitter/finagle/pull/470 and it also gave me the idea to write this blog post.

On this post, I will try to explain some of the basic Finagle concepts while demonstrating how to use them using Java gists.

Cool! But... what is Finagle?

Finagle is a protocol-agnostic, asynchronous RPC system for the JVM and we are able to use it with any JVM-hosted language. By @TwitterEng.

Now that we got rid of the basic definition, let's see how to create a simple service in Java with Finagle.

A minimal HTTP server

Creating a server is pretty straightforward, the serve method takes an address of type SocketAddress and a service. For routing, we are using the HttpMuxer class from com.twitter.finagle.http which is a service that dispatches incoming requests to registered handlers.

Filters

Filters are mainly used to define application-agnostic behaviors, as for adding a timeout to services, rescuing exceptions and transforming into expected HTTP results and etc. Services and filters are the core abstraction that clients and servers are created using Finagle.

Let's go ahead and create a filter that handles Exceptions being thrown from our service, and map then to HTTP status codes, after all, we don't want stack traces leaking out, right? 😉

As you can see we use the Future.handle() function takes a PartialFunction whose responsibility is to transform our exception into our HTTP response with the correct status code. BTW, I chose to use the ExceptionalFunction type from com.twitter.util to allow us throwing checked exceptions.
Now let's go ahead and create our service that will handle the request when we do an HTTP call to /cat.

In general, we should always use Future.exception(), however for the sake of this example we will just throw the exception.

Now we just need to wrap everything together. We will have our service throwing  NumberFormatException when we fail to parse the param id as a number, and our filter transforming that result in a valid HTTP status code as BAD_REQUEST.

Filters and Services

For composing our service with our exception filter we use the andThen method, that produces a new Service composed from our service and our HandleErrorsFilter.

That concludes our post, see you soon!