Skip to content

Instantly share code, notes, and snippets.

@ayushmishra2005
Last active December 19, 2017 21:02
Show Gist options
  • Save ayushmishra2005/7f159b57f14a14afe6a34f1ffee20383 to your computer and use it in GitHub Desktop.
Save ayushmishra2005/7f159b57f14a14afe6a34f1ffee20383 to your computer and use it in GitHub Desktop.
Akka Http: High-Level Server-Side API iimplementation of *spray-json*
package com.tutorial.sample
import akka.actor.ActorSystem
import akka.event.Logging
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model.{ContentTypeRange, MediaTypes, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{Route, UnsupportedRequestContentTypeRejection}
import akka.http.scaladsl.server.directives.MethodDirectives.{get, post}
import akka.http.scaladsl.server.directives.RouteDirectives.complete
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.util.Timeout
import org.scalatest.{Matchers, WordSpec}
import spray.json.DefaultJsonProtocol
import scala.concurrent.duration._
case class Employee(id: String, name: String)
case class Employees(employees: Seq[Employee])
trait JsonSupport extends SprayJsonSupport {
import DefaultJsonProtocol._
implicit val employeeJsonFormat = jsonFormat2(Employee)
implicit val employeessJsonFormat = jsonFormat1(Employees)
}
trait EmployeeRoutes extends JsonSupport {
implicit def system: ActorSystem
lazy val log = Logging(system, classOf[EmployeeRoutes])
var list: Employees = Employees(Nil)
implicit lazy val timeout = Timeout(5.seconds)
lazy val employeeRoutes: Route =
pathPrefix("employees") {
pathEnd {
get {
complete(list)
} ~
post {
entity(as[Employee]) { employee =>
list = list.copy(employees = list.employees ++ Seq(employee))
log.info("Created employee :", employee.name)
complete((StatusCodes.Created, employee))
}
}
}
}
}
class EmployeeRoutesSpec extends WordSpec with Matchers with ScalatestRouteTest
with EmployeeRoutes {
import org.scalatest.prop.TableDrivenPropertyChecks._
lazy val routes = employeeRoutes
"EmployeeRoutes" should {
val testData =
Table(
("clue", "path", "expectedStatus", "expectedEntity"),
("return employee list", Get("/employees"), StatusCodes.OK, """{"employees":[]}"""),
("add an employee", Post("/employees", Employee("1", "John")), StatusCodes.Created, """{"id":"1","name":"John"}""")
)
forAll(testData) { case (clue, path, expectedStatus, expectedEntity) =>
s"$clue" in {
path ~> routes ~> check {
status should ===(expectedStatus)
entityAs[String] should ===(expectedEntity)
}
}
}
val rejectData =
Table(
("clue", "path", "expected"),
("reject the request, if respective resource is not found", Get("/emp"), Nil),
("reject the request, if the requests content-type is unsupported", Post("/employees", ""), List(UnsupportedRequestContentTypeRejection(Set(ContentTypeRange(MediaTypes.`application/json`)))))
)
forAll(rejectData) { case (clue, path, expected) =>
s"$clue" in {
path ~> routes ~> check {
rejections shouldBe expected
handled shouldBe false
}
}
}
}
}
package com.tutorial.sample
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
import akka.stream.ActorMaterializer
import scala.concurrent.Future
object ServerStarter extends App with EmployeeRoutes {
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
val (host, port) = ("localhost", 8080)
val bindingFuture: Future[ServerBinding] =
Http().bindAndHandle(employeeRoutes, host, port)
log.info(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
bindingFuture.failed.foreach { ex =>
log.error(ex, "Failed to bind to {}:{}!", host, port)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment