jakstack
jakstack

Reputation: 2205

Akka Http DSL Directives, how it works

In typical Akka Http DSL style we have:

import akka.http.scaladsl.server.Directives._

then further in the code you may see something like

val routes = {
logRequestResult("akka-http-microservice") {
  pathPrefix("ip") {
    (get & path(Segment)) { ip =>
      complete {
        fetchIpInfo(ip).map[ToResponseMarshallable] {
          case Right(ipInfo) => ipInfo
          case Left(errorMessage) => BadRequest -> errorMessage
        }
      }
    } ~
    (post & entity(as[IpPairSummaryRequest])) { ipPairSummaryRequest =>
      complete {
        val ip1InfoFuture = fetchIpInfo(ipPairSummaryRequest.ip1)
        val ip2InfoFuture = fetchIpInfo(ipPairSummaryRequest.ip2)
        ip1InfoFuture.zip(ip2InfoFuture).map[ToResponseMarshallable] {
          case (Right(info1), Right(info2)) => IpPairSummary(info1, info2)
          case (Left(errorMessage), _) => BadRequest -> errorMessage
          case (_, Left(errorMessage)) => BadRequest -> errorMessage
        }
      }
    }
  }
}

What I don't get fully is how does for example the 'get' in (get & path(Segment)) { ip => be recognised as a method def from MethodDirectives trait. So we type '(get ...' and Scala knows that it's from MethodDirectives, but how?

To me it seems that what makes this work is a core feature of the Scala compiler that's not obvious to me.

I always say to people moving from Java to Scala is like converting to a new religion, sometimes you just have to believe ;)

I know I'm gonna kick myself when I find out though :(

Upvotes: 1

Views: 402

Answers (1)

jakstack
jakstack

Reputation: 2205

Okay made some progress, turns out that in Scala you can import things like packages, classes, objects, instances, fields and methods. Importing methods is no big deal since functions are first class citizens. So importing

import akka.http.scaladsl.server.Directives._

Will in fact import all the methods in the Directives trait (as the documentation suggests):

In the above question the code uses:

logRequestResult
pathPrefix
get
path
etc ...

These are all methods that are auto imported from this single import statement, so

logRequestResult from DebuggingDirectives
pathPrefix from PathDirectives
get from MethodDirectives
path from PathDirectives
etc ...

If you clone this project sample app and click through these methods it will take you to the traits where these are defined, what you'll also notice is that each trait has also a companion object which is what makes importing methods in Scala possible.

The Scala feature that wasn't obvious to me was importing methods!

Now I'll go and kick myself :)

Upvotes: 2

Related Questions