I have a simple Main
object, which create routes
for my two services this way:
object GameApp extends App {
val config = ConfigFactory.load()
val host = config.getString("http.host")
val port = config.getInt("http.port")
implicit val system = ActorSystem("game-service")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
val game = new GameRouting
val rate = new RateRouting
val routes: Route = game.route ~ rate.route
Http().bindAndHandle(routes, host, port) map {
binding => println(s"Server start on ${binding.localAddress}")
} recover {
case ex => println(s"Server could not start on ${host}:${port}", ex.getMessage)
}
}
Now, I would like to refactor this code and move this piece into separate method/class/object etc.:
val game = new GameRouting
val rate = new RateRouting
val routes: Route = game.route ~ rate.route
But this classes (GameRouting
and RateRouting
) uses implicit
in constructors and I cannot simply move this code to separate place.
How should I refactor this code to get what I want?
My another question is - routes classes (GameRouting
and RateRouting
) should be class
or case class
? This is GameRouting
class:
trait Protocols extends SprayJsonSupport with DefaultJsonProtocol {
implicit val gameFormat = jsonFormat4(Game)
}
class GameRouting(implicit executionContext: ExecutionContext) extends Protocols {
val gameService = new GameService
val route: Route = {
pathPrefix("games") {
pathEndOrSingleSlash {
get {
complete {
gameService.getGames()
}
} ~
post {
entity(as[Game]) { gameForCreate =>
createGame(gameForCreate)
}
}
} ~
pathPrefix(LongNumber) { id =>
get {
complete {
gameService.getGame(id)
}
} ~ put {
entity(as[Game]) { gameForUpdate =>
complete {
gameService.update(gameForUpdate)
}
}
}
}
}
}
private def createGame(gameForCreate: Game) = {
onComplete(gameService.createGame(gameForCreate)) {
case Success(created) => complete(StatusCodes.Created, created)
case Failure(exception) => complete(StatusCodes.BadRequest, s"An error: $exception")
}
}
}
And if I make it case
I cannot access field routes
from Main
object. How to fix this or write it in better way? Maybe there are basic questions, but I've been still learning Scala and Akka since few weeks.
You can just move your implicits to separate object:
object GameAppImplicits {
implicit val system = ActorSystem("game-service")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
}
and then import when needed:
import yourpackage.GameAppImplicits._
For your second question, case classes are usually used for modeling immutable data. In this case you don't really need any feature, that case classes give you (like automatic toString
, equals
, copy
etc.), so I would say it would be best to just use plain class
.