Google Guice field injection in scala case class - scala

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 **/
}

Related

Create Guice dependency injection binding in Scala function

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]))
}

Call method in constructor

I have a Controller with a constructor where I´m injecting a cache, but also I would like to invoke a method in the constructor when the instance is created. I know we can create some auxiliary constructors with
def this(foo:Foo){}
But in my case because is play framework the one that instance my bootstrap is a little bit more complex.
Here my code
class SteamController #Inject()(cache: CacheApi) extends BaseController {
private val GAME_IDS_LIST_API: String = "api.steampowered.com/ISteamApps/GetAppList/v2"
private val GAME_API: String = "store.steampowered.com/api/appdetails?appids="
private val GAME_KEY: String = "games"
def games = Action { implicit request =>
var fromRequest = request.getQueryString("from")
if (fromRequest.isEmpty) {
fromRequest = Option("0")
}
val from = Integer.parseInt(fromRequest.get) * 10
val to = from + 10
loadGameIds()
Ok(html.games(SteamStore.gamesIds(cache.getVal[JSONArray](GAME_KEY), from, to), cache.jsonArraySize(GAME_KEY)/10))
}
private def loadGameIds(): Unit = {
val games = cache.get(GAME_KEY)
if (games.isEmpty) {
get(s"$GAME_IDS_LIST_API", asJsonGamesId)
cache.set(GAME_KEY, lastResponse.get, 60.minutes)
}
}
What I would like is that loadGameIds would be invoked and cached when the class is instantiated.
Any suggestion?
Regards.
If I understand correctly your question, you simply want to add some statements to the main constructor body? If that's the case, you can simply do so in the body of the class itself. In your case, that would look like this:
class SteamController #Inject()(cache: CacheApi) extends BaseController {
...
private val GAME_KEY: String = "games"
loadGameIds() // <-- Here we are calling from the main constructor body
def games = Action { implicit request =>
...
}
...
}
When doing so, it is usually a good idea to perform additional code after the declaration of all vals and vars in your class, to ensure they are properly initialized at the time your additional constructor code runs.

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.

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.

Scala abstract class method that returns a new corresponding class child object

I have the following class in my mind:
abstract class MyClass (data: MyData) {
def update(): MyClass = {
new MyClass(process())
}
def process(): MyData = {
...
}
}
However, abstract classes cannot be instantiated so the line new MyClass(process()) is an error. My question is - is there any way to tell the compiler that in case of each of the child classes of MyClass I want to create an object of exactly that child class? It seems an overkill to write this method awhole in all child classes. Playing with type parameters of the class or method I could not acheive that myself.
How about something like this? MyClass is parametrized with the concrete type. Of course, all concrete classes have to implement a method that actually returns a new instance of Self.
trait MyClass[+Self <: MyClass[Self]] {
def update(): Self = {
makeNew(process())
}
def process(): MyData = {
// ...
}
protected def makeNew(data: MyData): Self
}
class Concrete0 extends MyClass[Concrete0] {
protected def makeNew(data: MyData) = new Concrete0
}
class RefinedConcrete0 extends Concrete0 with MyClass[RefinedConcrete0] {
override protected def makeNew(data: MyData) = new RefinedConcrete0
}
Credit: IttayD’s second update to his answer to this question.
To completly avoid implementing almost identical method in all subclasses you would need to use reflection. I guess that would be your last resort if you have chosen Scala.
So here is how to minimize the repetitive code:
// additional parameter: a factory function
abstract class MyClass(data: MyData, makeNew: MyData => MyClass) {
def update(): MyClass = {
makeNew(process())
}
def process(): MyData = {
...
}
}
class Concrete(data: MyData) extends MyClass(data, new Concrete(_))
This way you repeat only the shortest fragment required to instantiate the subclass.