2. Topics CoveredTopics Covered
What is spray
Why we use spray
Spray application architecture
Spray-can HTTP server
Spray-routing
Demo
What is spray
Why we use spray
Spray application architecture
Spray-can HTTP server
Spray-routing
Demo
3. What is SprayWhat is Spray
spray is an open-source toolkit for building REST/HTTP-based integration
layers on top of Scala and Akka.
Principles of spray :-
● Fully asynchronous, non-blocking
● Actor- and Future-based
● High-performance
● Lightweight
● Modular
● Testable
4. Why we use sprayWhy we use spray
● To make RESTful web services
● REST should be used if it is very important for you to minimize the coupling
between client and server components in a distributed application.
● This may be the case if your server is going to be used by many different
clients that you do not have control over.
● Simply make a controller layer of MVC architecture
5.
6. Spray-can Http serverSpray-can Http server
The spray-can HttpServer is scoped with a clear focus on the essential
functionality of an HTTP/1.1 server:
●
Connection management
● Message parsing and header separation
● Timeout management (for requests and connections)
● Response ordering (for transparent pipelining support)
The spray-can HTTP server is implemented by two types of Akka actors,
which sit on top of Akka IO. When you tell spray-can to start a new server
instance on a given port an HttpListener actor is started, which accepts
incoming connections and for each one spawns a new
HttpServerConnection actor, which then manages the connection for the
rest of its lifetime
7. Starting spray-can Http serverStarting spray-can Http server
// we need an ActorSystem to host our application in
implicit val system = ActorSystem("spray-api-service")
// create and start our service actor
val service = system.actorOf(Props[MyServiceActor], "spray-service")
// start a new HTTP server on port 8080 with our service actor as the handler
IO(Http) ! Http.Bind(service, interface = "localhost", port = 8080)
}
A spray-can HTTP server is started by sending an Http.Bind command to the
Http extension:
8. Spray-routing
The spray-routing module provides a high-level, very flexible routing DSL for elegantly defining
RESTful web services. Normally you would use it either on top of a spray-can HTTP Server.
Val routes = path("index") {
get {
respondWithMediaType(`text/html`) {
complete {
HttpResponse(OK, "Hello Sandeep ")
}
}
}
}
9. Directives
Directives are small building blocks of which you can construct arbitrarily
complex route structures. Here is a simple example of a route built from
directives:
A directive does one or more of the following:
● Transform the incoming RequestContext before passing it on to its inner Route
● Filter the RequestContext according to some logic, i.e. only pass on certain
requests and reject all others
● Extract values from the RequestContext and make them available to its inner
Route as “extractions”
● Complete the request
10. Composing directives
val route: Route =
path("order" / IntNumber) { id =>
get {
complete {
"Received GET request for order " + id
}
} ~
put {
complete {
"Received PUT request for order " + id
}
}
}
you can also use the | operator on directives
Get and put directives are chained together with the ~ operator to form a
higher-level route that serves as the inner Route of the path directive
11. Parameters
● .? (optional)
● ? "red" (default value)
● ! "blue" (color should be blue)
● .as[Int] (deserialize as a Int)
Query parameters can be either extracted as a String or can be converted
to another type. The parameter name can be supplied either as a String or
as a Symbol. Parameter extraction can be modified to mark a query
parameter as required or optional or to filter requests where a parameter
has a certain value
12. Get request parameters extract
val route =
parameters('color, 'backgroundColor) { (color, backgroundColor) =>
complete(s"The color is '$color' and the background is '$backgroundColor'")
}
Deserialize the parameters
val route =
parameters('color, 'count.as[Int]) { (color, count) =>
complete(s"The color is '$color' and you have $count of it.")
}
13. Marshalling
“Marshalling” is the process of converting a higher-level (object) structure
into some kind of lower-level representation, often a “wire format”. Other
popular names for it are “Serialization” or “Pickling”.
In spray “Marshalling” means the conversion of an object of type T into an
HttpEntity
spray-httpx comes with pre-defined Marshallers for the following types:
● Array[Byte]
● Array[Char]
● String
● Option[T]
● Either[A, B]
● Try[T]
● Future[T]
14. Unmarshalls
Entity Directive
The entity directive works in conjuction with as and spray.httpx.unmarshalling
to convert some serialized “wire format” value into a higher-level object
structure
val route = post {
entity(as[Person]) { person =>
complete(s"Person: ${person.name} - favorite number: $
{person.favoriteNumber}")
}
}
15. Spray test-kit
For services built with spray-routing spray provides a dedicated test DSL that
makes actor-less testing of route logic easy and convenient. This “route test DSL”
is made available with the spray-testkit module.
"return a 'PONG!' response for GET requests to /ping" in {
Get("/ping") ~> smallRoute ~> check {
responseAs[String] === "PONG!"
}
}