Create Guice dependency injection binding in Scala function - scala

I want to bind a certain class, lets call it injected either to its real implementation real or to its mock.
Also side effects should happen and therefor a function would be preferable to encapsulate this work.
Doing that outside of a function is known. But that also requires the side effects to be coded multiple times
The functionality iam looking for could be outlined as this (none working approach!)
private def bindMocksOptional(configSettingKey: String, injected: Class[_], real: Class[_] , mock: Class[_]) {
configuration.getOptional[Boolean](configSettingKey) match {
case Some(true) => {
bind(injected).to(mock)
val message = s"Using a mock (${mock.getCanonicalName})for ${injected.getCanonicalName}"
Logger.warn(message)
println(Console.MAGENTA + message)
}
case _ => bind(injected).to(real)
}
}
The function should take the outlined types as parameters, look up some config settings and based on those bind either to mock or real implementation.

You can use Provider:
import com.google.inject.{AbstractModule, Guice, Inject, Provider}
class Configuration {
def getOptional[T](key: String): Option[T] = None
}
trait DatabaseClient
class DatabaseClientMock extends DatabaseClient
class DatabaseClientReal extends DatabaseClient
// ---
// 1. Define Guice Provider:
class DatabaseClientGuiceProvide #Inject()(configuration: Configuration)
extends Provider[DatabaseClient] {
override def get(): DatabaseClient = {
configuration.getOptional[Boolean]("mock") match {
case Some(true) =>
println("used mock")
new DatabaseClientMock
case _ =>
println("used real")
new DatabaseClientReal
}
}
}
class MainModule extends AbstractModule {
override def configure(): Unit = {
// 2. Bind dependencies of provider
bind(classOf[Configuration]).toInstance(new Configuration)
// 3. Bind provider
bind(classOf[DatabaseClient])
.toProvider(classOf[DatabaseClientGuiceProvide])
}
}
// 4. Test it:
object GuiceMain extends App {
val module = Guice.createInjector(new MainModule)
println(module.getInstance(classOf[DatabaseClient]))
}

Related

Google Guice field injection in scala case class

I am writing Play 2.5 application using Scala. I have following piece of code:
#ImplementedBy(classOf[BarRepositoryImpl])
trait BarRepository {
def bar = //some actions
}
class BarRepositoryImpl extends BarRepository
case class Foo( /*some fields*/) {
#Inject private var barRepository: BarRepository = null
def foo1 = {
val a = barRepository.bar //here barRepository is always null
// some actions with 'a' and returning some result which depends on 'a'
}
}
I also have a controller where I inject BarRepository as well, but through constructor and there everything works well while in the class Foo on the line val a = barRepository.bar I get a NullPointerException. Could someone help to figure out what's the problem? Is it forbidden to use injection in case class?
If you don't want to pollute your case class signature with Guice injected annotation and fields then simply add an implicit dependency on the method that needs it instead:
case class Foo( /*some fields*/) {
def bar1(someField: Int)(implicit barRepository: BarRepository) = {
// some code that interacts with barRepository
}
}
The calling class will have to have the BarRepository as an implicitly injected parameter. E.g. a Play controller like:
#Singleton
class HomeController #Inject()(cc: ControllerComponents)
(implicit barRepository: BarRepository)
extends AbstractController(cc) {
def index() = Action { implicit request =>
val foo = Foo("field")
val bar = foo.bar1
// ...
}
}
I would have assumed that you inject the object in your class signature?
case class Foo #Inject()(barRepository:BarRepository, /* your fields */){
/** some stuff **/
}

Unit testing trait with object

I have the following construct, where I have a
trait DataServiceLocalImpl extends DataService {
override lazy val dataService = DataComponentLocalImpl
}
object DataComponentLocalImpl extends DataComponent {
def getData(element:String):String = GetStuffFromFile(element)
}
trait DataService {
val dataService: DataComponent
}
trait DataComponent {
def getData(element:String):String
}
The GetStuffFromFile reads a file from disk once (I only want this once, hence the object), creates a map and then returns the value for element.
This is all done in an Play Framework 2.3 surrounding and the app works as well, but when I use it in a test as an implicit I get the following error:
java.lang.NoClassDefFoundError: Could not initialize class DataComponentLocalImpl
Test suite:
class AutoCompleteSpec extends PlaySpec with Mockito with OneAppPerSuite {
val resource = new DataServiceLocalImpl {}
implicit val dataService = resource.dataService
}
If I remove the implicit it works...
You should create an object with the service overriden.
object FakeImpl extends DataServiceLocalImpl {
override dataService = //Fake or test data service here
}
You then create an anonymous class definition that allows you to test the trait.

Abstracting the Database client in the cake pattern

I am trying to create an abstraction for a SearchService using the Cake pattern. This is what I have currently:
trait SearchServiceComponent{
val searchService:SearchService
trait SearchService{
def searchForSomething(..):List[String]
def updateIndex(..):Boolean
}
}
Lets say I have a DbSearchServiceComponent and LuceneSearchServiceComponent as follows:
trait DbSearchServiceComponent extends SearchServiceComponent{
class DbSearchService extends SearchService{
//Initialize the db client
//Implement all the trait methods
}
}
Similarly...
trait LuceneSearchServiceComponent extends SearchServiceComponent{
class LuceneSearchService extends SearchService{
//Initialize the lucene client
//Implement all the trait methods
}
}
The issue I have with the above snippet is that
I have initialized instances of lucene client and the db client in the Service implementations.
Ideally I would want to "mix-in" a "Client" base type that can be either a Db client or a Lucene client but I am pretty confused as to how to inject a polymorphic client type here.
Can somebody point out how I may be able to refactor the code so that I can inject different versions of the client to my implementations of the SearchService trait?
Not sure if I interpret your question correctly, but that's how you could use the cake pattern for this:
trait SearchServiceComponent {
val searchService: SearchService
trait SearchService {
def searchForSomething(...): List[String]
def updateIndex(...): Boolean
}
}
trait DbSearchServiceComponent extends SearchServiceComponent {
override val searchService = new SearchService {
// Initialize client, implement methods
}
}
trait trait LuceneSearchServiceComponent extends SearchServiceComponent {
override val searchService = new SearchService {
// Initialize client, implement methods
}
}
and upon instantiation:
val myLucenceApp = new Whatever with LuceneSearchServiceComponent
val myDbApp = new Whatever with DbSearchServiceComponent
where Whatever would typically be something along the lines of
class Whatever { this: SearchServiceComponent =>
// ... use `searchService` and do lots of other things
}

Delaying trait initialization

I need a smart mechanism for component composition which allows mixed in traits to initialize after the composed component. The following throws a NullPointerException:
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {}
}
trait DynamicComponent {
protected def component: Component
component.addListener {
case x =>
}
}
class Foo extends DynamicComponent {
protected val component = new Component
}
new Foo // -> NullPointerException
The following things are not options for me:
Using protected lazy val component; that would produce an avalange of dozens of vals needing to become lazy, something I do not want.
Putting addListener in a method, e.g. initDynamic(); because I will be mixing in many traits, and I don't want to remember to call half a dozen initFoo() methods.
Using DelayedInit. This doesn't work with traits, at least according to the scaladocs.
I could live with a single init() call, but only under the following conditions:
all mixed in traits can easily declare to be invoked in this one single call
it is a compile error to forget the init() statement.
You can delay the initialization of a trait by by using early definitions. (See section 5.1.6 of the scala language specification)
class Foo extends {
protected val component = new Component
} with DynamicComponent
It's even clunkier than your solution, but you can always require the creation of a val that must be set with the init() method. You could choose to not do it last and get an error at runtime, but at least you won't forget it entirely:
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {
println("Added")
}
}
trait Dyn {
protected def component: Component
protected val initialized: Init
class Init private () {}
private object Init { def apply() = new Init() }
def init() = { component.addListener{ case x => }; Init() }
}
class Foo extends Dyn {
protected val component = new Component
protected val initialized = init()
}
No cheating!:
> class Bar extends Dyn { protected val component = new Component }
<console>:12: error: class Bar needs to be abstract, since value
initialized in trait Dyn of type Bar.this.Init is not defined
class Bar extends Dyn { protected val component = new Component }
The advantage this has is if you need multiple things to be in place before you initialize all of them cooperatively, or if your Component class is final so you can't mix in anything else.
AN idea could be to use the trick described here:
Cake pattern: how to get all objects of type UserService provided by components
All your components that should be initialized could be registered in some Seq[InitializableComponent]. And then you could initialize all registered components with a foreach.
No component will be forgotten in that Seq because they are registered automatically, but you can still forget to call the foreach anyway...
Here is one idea (I am happy to read about other suggestions):
class Component {
def addListener(pf: PartialFunction[Any, Unit]) {
println("Added")
}
}
trait DynamicComponentHost {
protected def component: Component with DynamicPeer
protected trait DynamicPeer {
_: Component =>
addListener {
case x =>
}
}
}
class Foo extends DynamicComponentHost {
protected val component = new Component with DynamicPeer
}
new Foo
So basically I am forcing the component to mix in a type that can only be provided by the mixed in trait. Reasonable? Looks a bit too complicated in my eyes.

Inject a dependency inside an object

I'm new to the Play framework and scala and I'm trying to inject a dependency inside a companion object.
I have a simple case class, like:
case class Bar(foo: Int) {}
With a companion object like:
object Bar {
val myDependency =
if (isTest) {
// Mock
}
else
{
// Actual implementation
}
val form = Form(mapping(
"foo" -> number(0, 100).verifying(foo => myDependency.validate(foo)),
)(Bar.apply)(Bar.unapply))
}
This works fine, but it's not really a clean way to do it. I'd like to be able to inject the dependency at build time so that I can inject different mock objects when testing and different real implementations in development and production.
What's the best way to achieve this?
Any help really appreciated. Thanks!
Along the lines of the Cake, we can try to change your example to
trait Validator {
def validate(foo: Int): Boolean
}
trait TestValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait ImplValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait BarBehavior {
def validator: Validator
val form = Form(mapping(...))(Bar.apply)(Bar.unapply)
}
//use this in your tests
object TestBar extends BarBehavior with TestValidation
//use this in production
object ImplBar extends BarBehavior with ImplValidation
You should additionally try and test if this example fits well within the Play Framework, too