14

Quick Background

I am running through some examples learning the Akka HTTP stack for creating a new REST project (completely non-UI). I have been using and augmenting the Akka HTTP Microservice Example to work through a bunch of use cases and configurations and have been pleasantly surprised by how well Scala & Akka HTTP work.

Current Setup

Currently I have a configuration like this:

object AkkaHttpMicroservice extends App with Service {
  override implicit val system = ActorSystem()
  override implicit val executor = system.dispatcher
  override implicit val materializer = ActorMaterializer()

  override val config = ConfigFactory.load()
  override val logger = Logging(system, getClass)

  Http().bindAndHandle(routes, config.getString("http.interface"), config.getInt("http.port"))
}

The routes parameter is just a simple value that has the typical data within it using path, pathPrefix, etc.

The Problem

Is there any way to set up routing in multiple Scala files or an example somewhere out there?

I would really like to be able to define a set of classes that separate the concerns and deal with Actor setup and processing to deal with different areas of the application and just leave the marshaling to the root App extension.

This might be me thinking too much in terms of how I did things in Java using annotations like @javax.ws.rs.Path("/whatever") on my classes. If that is the case, please feel free to point out the change in mindset.

I tried searching for a few different set of keywords but believe I am asking the wrong question (eg, 1, 2).

el n00b
  • 1,957
  • 7
  • 37
  • 64

1 Answers1

29

Problem 1 - combine routes in multiple files

You can combine routes from multiple files quite easy.

FooRouter.scala

object FooRouter {
   val route = path("foo") {
       complete {
          Ok -> "foo"
       } 
   }       
}

BarRouter.scala

object BarRouter {
   val route = path("bar") {
       complete {
          Ok -> "bar"
       } 
   }       
}

MainRouter.scala

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

object MainRouter {
   val routes = FooRouter.route ~ BarRouter.route
}

object AkkaHttpMicroservice extends App with Service {
  ...    
  Http().bindAndHandle(MainRouter.routes, config.getString("http.interface"), config.getInt("http.port"))
}

Here you have have some docs :

Problem 2 - seprate routing, marshalling, etc

Yes, you can separate routing, marshalling and application logic. Here you have activator example: https://github.com/theiterators/reactive-microservices

Problem 3 - handle routes using annotations

I don't know any lib that allow you to use annotion to define routing in akka-http. Try to learn more about DSL routing. This represents a different approach to http routing but it is convenient tool too.

CommonSenseCode
  • 23,522
  • 33
  • 131
  • 186
mgosk
  • 1,874
  • 14
  • 23
  • Thanks. Looking up the DSL routing set me down a good path and shifted my approach a bit. It seems to be the more appropriate mindset for approaching my particular problem at hand. The thing with Problem 1 is that I was trying to avoid having to edit multiple files (i.e., the separate file and then adding the route concatenation in the app). – el n00b Dec 30 '15 at 14:15
  • This was driving me nuts. I used http://doc.akka.io/docs/akka-http/current/scala/http/routing-dsl/routes.html#the-routing-tree and it worked fine. Previously used `FooRouter.route ~ BarRouter.route` but it was throwing some unmarshalling exception. Thanks for saving my hair. – Greedy Coder Feb 14 '17 at 14:46
  • 2
    Worth saying that you need to write `import akka.http.scaladsl.server.Directives._` for this to work. Doc: http://doc.akka.io/docs/akka-http/current/scala/http/routing-dsl/routes.html#composing-routes – Rick Jul 23 '17 at 13:46
  • Using this approach causes an error for me: `Http().bindAndHandle(MainRouter.routes` for me is throwing an error, it's saying `Type mismatch, expected: Flow[HttpRequest, HttpResponse, Any], actual: server.Route` – NateH06 Apr 11 '18 at 16:20