Finatra : Building Rest APIs Made Simple


Finatra is an open-source project by Twitter that can be used to build REST APIs in Scala programming language. Finatra is a framework for easily building API services on top of  Twitter-server, Finagle, and Twitter-util.

  1. Finagle: It provides the building blocks for most of the code we write on the JVM. It has long-served as our extensible, protocol-agnostic, highly-scalable RPC framework
  2. Twitter Server:It provides elegant integration with twitter flags for parameterizing external server configuration, an HTTP admin interface, tracing functionality, lifecycle management, and stats.
  3. Twitter-Util: A bunch of idiomatic, small, general purpose tools for Scala. 

1---tqJ-9f9eLNZU2kh0zmFg


Finatra allows you to easily define a server and (in the case of an HTTP service) controllers — a service-like abstraction which define and handle endpoints of the server. You can also compose filters either per controller, per route in a controller, or across controllers.

 

Building A Simple Hello Application

 

In This Blog , We Will Begin With a Simple Application Which will return a Simple Message Using Finatra.

Let’s Begin.

Step 1: Create a New SBT project

 

Using Intellij Idea , Create a new Sbt Project in order to Start Building The Application from Scratch.

 

Step 2: Adding required dependencies to build.sbt


Add the Following to Your build.sbt :

lazy val versions = new {
  val finatra = "2.1.2"
  val logback = "1.1.3"
}

resolvers ++= Seq(
  Resolver.sonatypeRepo("releases"),
  "Twitter Maven" at "https://maven.twttr.com"
)

libraryDependencies += "com.twitter.finatra" % "finatra-http_2.11" % versions.finatra
libraryDependencies += "com.twitter.finatra" % "finatra-slf4j_2.11" % versions.finatra
libraryDependencies += "ch.qos.logback" % "logback-classic" % versions.logback

Please Note : Only libraryDependencies += com.twitter.finatra % finatra-http_2.11 % versions.finatra is required. Other libraryDependencies are optional but are prefered to keep track of the logs.

Note : There may be a version error while running the code . This will display a error like
//Error

Exception in thread "main" java.lang.NoSuchMethodError: com.twitter.util.Closable.$init$(Lcom/twitter/util/Closable;)V

at FinatraServer.(Finatra.scala:_)
 at FinatraApp$.(Finatra.scala:_)
at FinatraApp$.(Finatra.scala) 
at FinatraApp.main(Finatra.scala)

In order to Correct that try changing the Scala Version to 2.11.7

Step 3: Importing the Finatra HttpServer

 

Add the Following import to your scala class :

import com.twitter.finatra.http.HttpServer

Step 4: Using the Finatra HttpServer By Extending it

 

class FinatraServer extends HttpServer

object FinatraMain extends FinatraServer

Note : The reason for having a separate object is to allow server to be instantiated multiple times in tests without worrying about static state persisting across test runs in the same JVM. (Documentation)

Step 5: Working On the Main Code Using HelloContainer

 

import com.twitter.finagle.http.Request
import com.twitter.finatra.http.routing.HttpRouter
import com.twitter.finatra.http.{Controller, HttpServer}

object FinatraMain extends FinatraServer

class FinatraServer extends HttpServer {
  override protected def configureHttp(router: HttpRouter): Unit = {
    router.add(new HelloController)
  }
}

class HelloController extends Controller {

  get("/hello") { request: Request =>
    "Hello From Anmol. Let's Learn Finatra"
}

In the code shown above, we created HelloController which extends finatra Controller abstract class. HelloController is defined with one endpoint – /hello.

When an HTTP GET request is made to /hello then the associated callback function will be called. The callback function has callback: RequestType => ResponseType signature. It accepts a com.twitter.finagle.http.Request and returns back a response of any type that can be converted to com.twitter.finagle.http.Response .
The callback function in this case just returns a string.

Step 6:  Making the Http GET Request

 

To make The Http Request , We can basically Use 2 methods :

  1. Request From Terminal :
    curl -i http://localhost:8888/hello
    Response :
    HTTP/1.1 200 OK
    Content-Length: 37
    Hello From Anmol. Let’s Learn Finatra 
  2. Request Through Browser : 
    http://localhost:8888/hello
    Response On Browser Window:
    Hello From Anmol. Let’s Learn Finatra 

Similarly you can Add multiple End Points in the application to make Multiple Requests .

 

Testing Of the Hello Application

Step 1 :

In order to test the Application Controller we need to add Certain Things to built.sbt such that your build.sbt looks something like this :

lazy val versions = new {
  val finatra = "2.1.2"
    val logback = "1.1.3"
  val guice = "4.0"

}

resolvers ++= Seq(
  Resolver.sonatypeRepo("releases"),
  "Twitter Maven" at "https://maven.twttr.com"
)

libraryDependencies += "com.twitter.finatra" % "finatra-http_2.11" % versions.finatra
libraryDependencies += "com.twitter.finatra" % "finatra-slf4j_2.11" % versions.finatra
libraryDependencies += "ch.qos.logback" % "logback-classic" % versions.logback
libraryDependencies += "com.twitter.finatra" % "finatra-http_2.11" % versions.finatra % "test"
libraryDependencies += "com.twitter.inject" % "inject-server_2.11" % versions.finatra % "test"
libraryDependencies += "com.twitter.inject" % "inject-app_2.11" % versions.finatra % "test"
libraryDependencies += "com.twitter.inject" % "inject-core_2.11" % versions.finatra % "test"
libraryDependencies += "com.twitter.inject" %% "inject-modules" % versions.finatra % "test"
libraryDependencies += "com.google.inject.extensions" % "guice-testlib" % versions.guice % "test"
libraryDependencies +=  "com.twitter.finatra" % "finatra-jackson_2.11" % versions.finatra % "test"

libraryDependencies += "com.twitter.finatra" % "finatra-http_2.11" % versions.finatra % "test" classifier "tests"
libraryDependencies += "com.twitter.inject" % "inject-server_2.11" % versions.finatra % "test" classifier "tests"
libraryDependencies += "com.twitter.inject" % "inject-app_2.11" % versions.finatra % "test" classifier "tests"
libraryDependencies += "com.twitter.inject" % "inject-core_2.11" % versions.finatra % "test" classifier "tests"
libraryDependencies += "com.twitter.inject" % "inject-modules_2.11" % versions.finatra % "test" classifier "tests"
libraryDependencies += "com.google.inject.extensions" % "guice-testlib" % versions.guice % "test" classifier "tests"
libraryDependencies +=  "com.twitter.finatra" % "finatra-jackson_2.11" % versions.finatra % "test"  classifier "tests"

libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.4" % "test"
libraryDependencies += "org.specs2" %% "specs2" % "2.3.12" % "test"

 

Step 2 :

Add the Following Code to Your Test class in order to test your controller :

import com.twitter.finagle.http.Status
import com.twitter.finatra.http.test.EmbeddedHttpServer
import com.twitter.inject.server.FeatureTest

class HelloControllerSpec extends FeatureTest {
  override val server: EmbeddedHttpServer = new EmbeddedHttpServer(
    twitterServer = new FinatraServer)

  "Saying Hello" in {
    server.httpGet(
      path = "/hello",
      andExpect = Status.Ok,
      withBody = "Hello From Anmol. Let's Learn Finatra"
    )
  }
}

 

Step 3 :

Finally sbt test from the terminal to ensure that the application passes the test.

 

 

For Further Reference, Check out the Official Link : https://github.com/twitter/finatra

For the Demo Hello Application, Check out Our Github Link  : https://github.com/anmol2709/Finatra_Application_For_Beginners.git

 


KNOLDUS-advt-sticker

This entry was posted in Scala and tagged , . Bookmark the permalink.

One Response to Finatra : Building Rest APIs Made Simple

  1. anmolsarna09 says:

    Reblogged this on Anmol Sarna and commented:
    Finatra : Building Rest APIs Made Simple

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s