aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlad <vlad@drivergrp.com>2016-07-16 02:43:54 -0400
committervlad <vlad@drivergrp.com>2016-07-16 02:43:54 -0400
commit980deaf70e4e0ba906d0af534aebc839015f0581 (patch)
tree41730ad413bd7581d0ab54429930e83c48f97fe6
parentc0d574dc6134e4f406875ea5a1301ba46602a6ec (diff)
downloaddriver-core-980deaf70e4e0ba906d0af534aebc839015f0581.tar.gz
driver-core-980deaf70e4e0ba906d0af534aebc839015f0581.tar.bz2
driver-core-980deaf70e4e0ba906d0af534aebc839015f0581.zip
Dependency injection through constructor parameters + bug fixes
-rw-r--r--src/main/scala/com/drivergrp/core/DriverApp.scala55
-rw-r--r--src/main/scala/com/drivergrp/core/config.scala36
-rw-r--r--src/main/scala/com/drivergrp/core/database.scala43
-rw-r--r--src/main/scala/com/drivergrp/core/execution.scala28
-rw-r--r--src/main/scala/com/drivergrp/core/logging.scala32
-rw-r--r--src/main/scala/com/drivergrp/core/messages.scala26
-rw-r--r--src/main/scala/com/drivergrp/core/rest.scala16
-rw-r--r--src/main/scala/com/drivergrp/core/stats.scala11
-rw-r--r--src/main/scala/com/drivergrp/core/time.scala5
9 files changed, 70 insertions, 182 deletions
diff --git a/src/main/scala/com/drivergrp/core/DriverApp.scala b/src/main/scala/com/drivergrp/core/DriverApp.scala
index 01fee03..7b991d1 100644
--- a/src/main/scala/com/drivergrp/core/DriverApp.scala
+++ b/src/main/scala/com/drivergrp/core/DriverApp.scala
@@ -5,41 +5,42 @@ import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.RouteResult._
import akka.stream.ActorMaterializer
-import com.drivergrp.core.config.ConfigModule
-import com.drivergrp.core.logging.LoggerModule
+import com.drivergrp.core.logging.{Logger, TypesafeScalaLogger}
+import com.typesafe.config.Config
+import org.slf4j.LoggerFactory
-trait DriverApp {
- this: ConfigModule with LoggerModule =>
+class DriverApp(services: Seq[Service],
+ log: Logger = new TypesafeScalaLogger(
+ com.typesafe.scalalogging.Logger(LoggerFactory.getLogger(classOf[DriverApp]))),
+ config: Config = com.drivergrp.core.config.loadDefaultConfig,
+ interface: String = "localhost", port: Int = 8080) {
- def interface: String = "localhost"
- def port: Int = 8080
-
- def services: Seq[Service]
-
-
- val servicesInstances = services
- activateServices(servicesInstances)
- scheduleServicesDeactivation(servicesInstances)
-
- implicit val actorSystem = ActorSystem("spray-routing", config)
- implicit val executionContext = actorSystem.dispatcher
- implicit val materializer = ActorMaterializer()(actorSystem)
+ def run() = {
+ activateServices(services)
+ scheduleServicesDeactivation(services)
+ bindHttp(services)
+ }
- val serviceTypes = servicesInstances.flatMap(_.serviceTypes)
- val swaggerService = new Swagger(actorSystem, serviceTypes, config)
- val swaggerRoutes = swaggerService.routes ~ swaggerService.swaggerUI
+ protected def bindHttp(services: Seq[Service]) {
+ implicit val actorSystem = ActorSystem("spray-routing", config)
+ implicit val executionContext = actorSystem.dispatcher
+ implicit val materializer = ActorMaterializer()(actorSystem)
- Http()(actorSystem).bindAndHandle(
- route2HandlerFlow(logRequestResult("log")(servicesInstances.map(_.route).foldLeft(swaggerRoutes) { _ ~ _ })),
- interface, port)(materializer)
+ val serviceTypes = services.flatMap(_.serviceTypes)
+ val swaggerService = new Swagger(actorSystem, serviceTypes, config)
+ val swaggerRoutes = swaggerService.routes ~ swaggerService.swaggerUI
+ Http()(actorSystem).bindAndHandle(
+ route2HandlerFlow(logRequestResult("log")(services.map(_.route).foldLeft(swaggerRoutes) { _ ~ _ })),
+ interface, port)(materializer)
+ }
/**
* Initializes services
*/
- protected def activateServices(servicesInstances: Seq[Service]) = {
- servicesInstances.foreach { service =>
+ protected def activateServices(services: Seq[Service]) = {
+ services.foreach { service =>
Console.print(s"Service ${service.name} starts ...")
try {
service.activate()
@@ -55,10 +56,10 @@ trait DriverApp {
/**
* Schedules services to be deactivated on the app shutdown
*/
- protected def scheduleServicesDeactivation(servicesInstances: Seq[Service]) = {
+ protected def scheduleServicesDeactivation(services: Seq[Service]) = {
Runtime.getRuntime.addShutdownHook(new Thread() {
override def run(): Unit = {
- servicesInstances.foreach { service =>
+ services.foreach { service =>
Console.print(s"Service ${service.name} shutting down ...")
try {
service.deactivate()
diff --git a/src/main/scala/com/drivergrp/core/config.scala b/src/main/scala/com/drivergrp/core/config.scala
index 5a89752..bc17d6b 100644
--- a/src/main/scala/com/drivergrp/core/config.scala
+++ b/src/main/scala/com/drivergrp/core/config.scala
@@ -6,38 +6,16 @@ import com.typesafe.config.{Config, ConfigFactory}
object config {
- trait ConfigModule {
- def config: Config
- }
-
- /**
- * Configuration implementation providing config which is specified as the parameter
- * which might be used for testing purposes
- *
- * @param config fixed config to provide
- */
- class DefaultConfigModule(val config: Config) extends ConfigModule
-
- /**
- * Configuration implementation reading default typesafe config
- */
- trait TypesafeConfigModule extends ConfigModule {
+ def loadDefaultConfig: Config = {
+ val configDefaults =
+ ConfigFactory.load(this.getClass.getClassLoader, "application.conf")
- private val internalConfig: Config = {
- val configDefaults =
- ConfigFactory.load(this.getClass.getClassLoader, "application.conf")
+ scala.sys.props.get("application.config") match {
- scala.sys.props.get("application.config") match {
+ case Some(filename) =>
+ ConfigFactory.parseFile(new File(filename)).withFallback(configDefaults)
- case Some(filename) =>
- ConfigFactory.parseFile(new File(filename)).withFallback(configDefaults)
-
- case None => configDefaults
- }
+ case None => configDefaults
}
-
- protected val rootConfig = internalConfig
-
- val config = rootConfig
}
}
diff --git a/src/main/scala/com/drivergrp/core/database.scala b/src/main/scala/com/drivergrp/core/database.scala
index 5eb9d28..f39512c 100644
--- a/src/main/scala/com/drivergrp/core/database.scala
+++ b/src/main/scala/com/drivergrp/core/database.scala
@@ -1,45 +1,40 @@
package com.drivergrp.core
import com.drivergrp.core.id.{Id, Name}
-
import scala.concurrent.Future
+import slick.backend.DatabaseConfig
+import slick.driver.JdbcProfile
object database {
- import slick.backend.DatabaseConfig
- import slick.driver.JdbcProfile
-
-
- trait DatabaseModule {
+ trait Database {
val profile: JdbcProfile
val database: JdbcProfile#Backend#Database
- }
- trait ConfigDatabaseModule extends DatabaseModule {
+ import profile.api._
+
+ implicit def idColumnType[T] =
+ MappedColumnType.base[Id[T], Long]({ id => id: Long }, { id => Id[T](id) })
+
+ implicit def nameColumnType[T] =
+ MappedColumnType.base[Name[T], String]({ name => name: String }, { name => Name[T](name) })
+ }
- protected def databaseConfigKey: String
+ object Database {
- private val dbConfig: DatabaseConfig[JdbcProfile] = DatabaseConfig.forConfig(databaseConfigKey)
+ def fromConfig(databaseName: String): Database = {
+ val dbConfig: DatabaseConfig[JdbcProfile] = DatabaseConfig.forConfig(databaseName)
- val profile: JdbcProfile = dbConfig.driver
- val database: JdbcProfile#Backend#Database = dbConfig.db
+ new Database {
+ val profile: JdbcProfile = dbConfig.driver
+ val database: JdbcProfile#Backend#Database = dbConfig.db
+ }
+ }
}
trait DatabaseObject {
def createTables(): Future[Unit]
def disconnect(): Unit
}
-
- trait IdColumnTypes {
- this: DatabaseModule =>
-
- import profile.api._
-
- implicit def idColumnType[T] =
- MappedColumnType.base[Id[T], Long]({ id => id: Long }, { id => Id[T](id) })
-
- implicit def nameColumnType[T] =
- MappedColumnType.base[Name[T], String]({ name => name: String }, { name => Name[T](name) })
- }
}
diff --git a/src/main/scala/com/drivergrp/core/execution.scala b/src/main/scala/com/drivergrp/core/execution.scala
deleted file mode 100644
index 7274f00..0000000
--- a/src/main/scala/com/drivergrp/core/execution.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.drivergrp.core
-
-
-object execution {
-
- import scala.concurrent.ExecutionContext
- import java.util.concurrent.Executors
- import akka.actor.ActorSystem
-
-
- trait ExecutionContextModule {
-
- def executionContext: ExecutionContext
- }
-
- trait FixedThreadsExecutionContext extends ExecutionContextModule {
-
- def threadsNumber: Int
-
- val executionContext: ExecutionContext =
- ExecutionContext.fromExecutor(Executors.newFixedThreadPool(threadsNumber))
- }
-
- trait ActorSystemModule {
-
- def actorSystem: ActorSystem
- }
-}
diff --git a/src/main/scala/com/drivergrp/core/logging.scala b/src/main/scala/com/drivergrp/core/logging.scala
index 35f3a1b..4729c09 100644
--- a/src/main/scala/com/drivergrp/core/logging.scala
+++ b/src/main/scala/com/drivergrp/core/logging.scala
@@ -1,42 +1,10 @@
package com.drivergrp.core
-import com.typesafe.scalalogging.{LazyLogging, StrictLogging}
import org.slf4j.Marker
object logging {
- trait LoggerModule {
-
- def log: Logger
- }
-
- trait NopLoggerModule extends LoggerModule {
-
- def log: Logger = new NopLogger()
- }
-
- /**
- * Defines `logger` as a lazy value initialized with an underlying `org.slf4j.Logger`
- * named according to the class into which this trait is mixed.
- */
- trait LazyLoggerModule extends LoggerModule {
- this: LazyLogging =>
-
- override val log: Logger = new TypesafeScalaLogger(logger)
- }
-
- /**
- * Defines `logger` as a value initialized with an underlying `org.slf4j.Logger`
- * named according to the class into which this trait is mixed.
- */
- trait StrictLoggerModule extends LoggerModule {
- this: StrictLogging =>
-
- override val log: Logger = new TypesafeScalaLogger(logger)
- }
-
-
trait Logger {
def fatal(message: String): Unit
diff --git a/src/main/scala/com/drivergrp/core/messages.scala b/src/main/scala/com/drivergrp/core/messages.scala
index cf0bb6c..105d1e3 100644
--- a/src/main/scala/com/drivergrp/core/messages.scala
+++ b/src/main/scala/com/drivergrp/core/messages.scala
@@ -3,37 +3,23 @@ package com.drivergrp.core
import java.util.Locale
-import com.drivergrp.core.config.ConfigModule
-import com.drivergrp.core.logging.{Logger, LoggerModule}
+import com.drivergrp.core.logging.Logger
+import com.typesafe.config.Config
import scala.collection.JavaConverters._
-import scala.collection.concurrent.TrieMap
/**
* Scala internationalization (i18n) support
*/
object messages {
- trait MessagesModule {
-
- def messages: Messages
- }
-
- trait ConfigMessagesModule extends MessagesModule {
- this: ConfigModule with LoggerModule =>
-
- private val loadedFromConfig = new TrieMap[Locale, Messages]()
- val locale: Locale = Locale.US
-
- val messages: Messages = {
- loadedFromConfig.getOrElseUpdate(locale, {
- val map = config.getConfig(locale.getISO3Language).root().unwrapped().asScala.mapValues(_.toString).toMap
- Messages(map, locale, log)
- })
+ object Messages {
+ def messages(config: Config, log: Logger, locale: Locale = Locale.US): Messages = {
+ val map = config.getConfig(locale.getLanguage).root().unwrapped().asScala.mapValues(_.toString).toMap
+ Messages(map, locale, log)
}
}
-
case class Messages(map: Map[String, String], locale: Locale, log: Logger) {
/**
diff --git a/src/main/scala/com/drivergrp/core/rest.scala b/src/main/scala/com/drivergrp/core/rest.scala
index e121640..b772a2e 100644
--- a/src/main/scala/com/drivergrp/core/rest.scala
+++ b/src/main/scala/com/drivergrp/core/rest.scala
@@ -1,21 +1,21 @@
package com.drivergrp.core
+import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.http.scaladsl.server.{Directive, _}
import akka.http.scaladsl.util.FastFuture._
import akka.stream.ActorMaterializer
import akka.util.Timeout
-import com.drivergrp.core.execution.{ActorSystemModule, ExecutionContextModule}
import com.drivergrp.core.id.{Id, Name}
-import com.drivergrp.core.logging.LoggerModule
-import com.drivergrp.core.stats.StatsModule
+import com.drivergrp.core.logging.Logger
+import com.drivergrp.core.stats.Stats
import com.drivergrp.core.time.TimeRange
-import com.drivergrp.core.time.provider.TimeModule
+import com.drivergrp.core.time.provider.TimeProvider
import spray.json.{DeserializationException, JsNumber, JsString, JsValue, RootJsonFormat}
-import scala.concurrent.Future
import scala.concurrent.duration._
+import scala.concurrent.{ExecutionContext, Future}
import scala.language.postfixOps
import scala.util.{Failure, Success, Try}
import scalaz.{Failure => _, Success => _, _}
@@ -23,8 +23,8 @@ import scalaz.{Failure => _, Success => _, _}
object rest {
- trait RestService {
- this: ActorSystemModule with LoggerModule with StatsModule with TimeModule with ExecutionContextModule =>
+ class RestService(actorSystem: ActorSystem, log: Logger, stats: Stats,
+ time: TimeProvider, executionContext: ExecutionContext) {
protected implicit val timeout = Timeout(5 seconds)
@@ -68,7 +68,7 @@ object rest {
}
implicit def nameFormat[T] = new RootJsonFormat[Name[T]] {
- def write(name: Name[T]) = JsNumber(name)
+ def write(name: Name[T]) = JsString(name)
def read(value: JsValue): Name[T] = value match {
case JsString(name) => Name[T](name)
diff --git a/src/main/scala/com/drivergrp/core/stats.scala b/src/main/scala/com/drivergrp/core/stats.scala
index 2a173df..152d4c6 100644
--- a/src/main/scala/com/drivergrp/core/stats.scala
+++ b/src/main/scala/com/drivergrp/core/stats.scala
@@ -1,6 +1,6 @@
package com.drivergrp.core
-import com.drivergrp.core.logging.LoggerModule
+import com.drivergrp.core.logging.Logger
import com.drivergrp.core.time.{Time, TimeRange}
object stats {
@@ -9,11 +9,6 @@ object stats {
type StatsKeys = Seq[StatsKey]
- trait StatsModule {
-
- def stats: Stats
- }
-
trait Stats {
def recordStats(keys: StatsKeys, interval: TimeRange, value: BigDecimal): Unit
@@ -40,9 +35,7 @@ object stats {
recordStats(Vector(key), TimeRange(time, time), BigDecimal(value))
}
- trait LogStats extends Stats {
- this: LoggerModule =>
-
+ class LogStats(log: Logger) extends Stats {
def recordStats(keys: StatsKeys, interval: TimeRange, value: BigDecimal): Unit = {
log.audit(s"${keys.mkString(".")}(${interval.start.millis}-${interval.end.millis})=${value.toString}")
}
diff --git a/src/main/scala/com/drivergrp/core/time.scala b/src/main/scala/com/drivergrp/core/time.scala
index 645c991..cce479f 100644
--- a/src/main/scala/com/drivergrp/core/time.scala
+++ b/src/main/scala/com/drivergrp/core/time.scala
@@ -59,11 +59,6 @@ object time {
* All the calls to receive current time must be made using time
* provider injected to the caller.
*/
-
- trait TimeModule {
- def time: TimeProvider
- }
-
trait TimeProvider {
def currentTime(): Time
}