Alexander
Alexander

Reputation: 387

Scala service separating by environment (service locator?)

My Scala application supports 2 environments: TEST and PROD. The difference is in using services. For example, production Emailer actualy sends an email, and test Emailer is rather stub or mock. The environment is configured by parameter. How do you implement such a service separating by environment? Do you prefer some solution with DI like Guice?

Upvotes: 1

Views: 339

Answers (1)

DCKing
DCKing

Reputation: 4283

In addition to Guice, you can keep using the native Scala cake pattern dependency injection if you want.

// MyService.scala
trait MyService {
   this: Emailer =>   // Cake pattern: this must be instatiated with an Emailer trait

   def doSomething() {
      //...
      this.email(...)
      //...
   }
}

// Somewhere else
trait Emailer { def email(args: String): Unit }
trait MockEmailer { override def email(args: String) = println("Email was sent!") }
trait RealEmailer { override def email(args: String) = actuallySendAnEmail(args) }

// Application.scala    
sealed trait Environment
case object Test extends Environment
case object Prod extends Environment

object Application {
   private var _environment: Environment = Test // Choose default
   def environment = _environment

   def main(args: Array[String) {
       // Determine environment at startup
       if(args.contains("PROD") {
         _environment = Prod
       } else {
         _environment = Test
       }
       // ...
   }
}

// Configuration.scala
val myService = Application.environment match {
   case Test => new MyService with MockEmailer
   case Prod => new MyService with RealEmailer
}

It takes a handful of lines to write this yourself, but it doesn't require any seperate dependency injection framework with its own annotation verbosities. In addition, you won't encounter runtime dependency injection errors - the Scala compiler guarantees this will work.

Upvotes: 2

Related Questions