Guice and Play2 Singleton from trait - scala

I am using Play with Scala and I am trying to create a singleton, and i want to inject it from its trait and not directly.
for example:
#ImplementedBy(classOf[S3RepositoryImpl])
trait S3Repository {
}
#Singleton
class S3RepositoryImpl extends S3Repository {
}
But this fails with error:
trait Singleton is abstract; cannot be instantiated
I have tried several combinations and they all produce the same.
I come from Spring background and its very natural there? am i missing something about how Guice handles this type of Injection?
Thanks.

As pointed out by #Tavian-Barnes, the solution is to ensure you have the following import:
import javax.inject.Singleton

I have here a "complete" working example, just hope that I'm not stating the obvious...
package controllers
import play.api._
import play.api.mvc._
import com.google.inject._
class Application #Inject() (s3: S3Repository) extends Controller {
def index = Action {
println(s3.get)
Ok
}
}
#ImplementedBy(classOf[S3RepositoryImpl])
trait S3Repository {
def get: String
}
#Singleton
class S3RepositoryImpl extends S3Repository {
def get: String = "bla"
}
Whenever you mark a class' constructor with #Inject the Guice will manage the injection of the instance itself. So, if you marked your class as #Singleton, Guice will create and will always give you just that one instance. Nobody can stop you from manually instantiating a class in your code... You can explore it in detail at Play.

Use below import, instead of import javax.inject.Singleton
import com.google.inject.{Inject, Singleton}

Import both Inject and Singleton.
import javax.inject.{Inject, Singleton}
Refrain from using:
import com.google.inject.{Inject, Singleton}
as play framework requires the javax import

Related

Initialising variables in a mock class scala

I am writing unit tests for an akka actor model implementation. The system contains classes and traits that need to be initialised. My issue lies with the testing of the methods. When I mock required parameters for a class, it removes the intelij compiler error, however all of the variables are set to null.
I have attempted to use
when(mock.answer).thenReturn(42)
and directly assigning the variables
val mock.answer = 42
The above two through compilation errors. "When" is not recognised and directly assigning values cases a runtime error.
Any insight would be much appreciated.
I am not sure if I understood your issue correctly, but try the self contained code snippet below and let me know if it is not clear enough:
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{FunSuite, Matchers}
import org.mockito.Mockito.when
#RunWith(classOf[JUnitRunner])
class MyTest extends FunSuite with Matchers with MockitoSugar {
trait MyMock {
def answer: Int
}
test("my mock") {
val myMock = mock[MyMock]
when(myMock.answer).thenReturn(42)
myMock.answer should be(42)
}
}

Importing object without class

I'm trying to import an object from another .scala file that doesn't exist inside a class. I've found you can import a class like in here Scala, importing class. Is there a way to import an object without having a class around it?
Thanks
Importing a class and importing an object work the same in scala.
If you have a class
package com.package1
class MyClass{}
and an object
package com.package2
object MyObject{}
You import both the exact same way
package com.package3
import com.package1.MyClass
import com.package2.MyObject
import syntax is the same no matter what you are importing, whether it's an object, a class, a trait, a method, or a field
Yes, Scala can do exactly what you ask, and this is used frequently. Here is an example:
object Blah {
val x = 1
val y = "hello"
}
object Main extends App {
import Blah._
println(s"x=$x; y=$y")
}
Output is:
x=1; y=hello
You can also import members of a class instance, which blew my mind the first time I saw it.
If you are talking about companion objects, they are not defined inside a class, but after the class definition:
class AClass {
def sayHello() = {
println(AClass.Hello)
}
}
object AClass {
private val Hello = "hello"
}
You should have no problem importing it.

PowerMock in scala

I want to mock a scala companion object, so im trying to use PowerMockito. I have the following:
import org.junit.runner.RunWith
import org.mockito.Mockito.when
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.api.mockito.PowerMockito._
#RunWith(classOf[PowerMockRunner])
#PrepareForTest(Array(classOf[ClassToMock]))
class Test {
describe("test") {
it("test") {
mockStatic(classOf[ClassToMock])
when(ClassToMock.apply()).thenReturn(null)
}
}
When running the test i get the following error:
The class path.to.ClassToMock not prepared for test.
To prepare this class, add class to the '#PrepareForTest' annotation.
In case if you don't use this annotation, add the annotation on class or method level.
org.powermock.api.mockito.ClassNotPreparedException:
Any ideas on how can i manage to make the annotation work?
Thx!!

Accessing Singleton values in Play for Scala

I have the following singleton defined in Scala
package main
import javax.inject._
#Singleton
class Properties {
val timeout = 120
}
how do I access it from other programs? I tried main.Properties.timeout but it throws a compilation error saying that a companion object was not found
If you want to access it in the way, that you've mentioned: main.Properties.timeout, then use companion object instead:
class Properties {
// ...
}
object Properties {
val timeout = 120
// ...
}
With #Singleton annotation, you have to inject that service somewhere, to be able to use it. So something like this:
import javax.inject._
import main.Properties
class SomeService #Inject() (props:Properties)() {
println(props.timeout)
}
Here is documentation about DI for PlayFramework: https://www.playframework.com/documentation/2.5.x/ScalaDependencyInjection - for the latest one (not 2.0), but it is a good start point.

PlayFramework Scala dependency Injection Javax

I am new to Scala and the PlayFramework and am trying to figure out how I can do a a dependency Injection. I basically want a file that will be a trait and inject that into a controller. My problem is that my Controller class is not seeing my Trait this is my code
ProfileTrait
package traitss
import play.api.mvc._
trait ProfileTrait extends Controller {
def Addone()
}
Then I try to inject that into my controller
import java.nio.file.{Files, Paths}
import traitss.ProfileTrait_
import play.api.mvc.{Action, Controller}
import javax.inject._
class Profiles #Inject() (profileTrait: ProfileTrait) extends Controller
{
}
However my controller is not seeing it, I am trying to follow the example here https://www.playframework.com/documentation/2.5.x/ScalaDependencyInjection .
I am using the play framework version 2.50
You cannot inject a trait directly. You need to specify the implementation of the trait that needs to be injected.
There are two ways to specify the implementation of a trait that is to be injected:
Using #ImplementedBy annotation. Here's a simple example:
package traitss
import play.api.mvc._
import com.google.inject.ImplementedBy
#ImplementedBy(classOf[ProfileTraitImpl])
trait ProfileTrait extends Controller {
def Addone()
}
class ProfileTraitImpl extends ProfileTrait {
// your implementation goes here
}
Using Programmatic Bindings
package traitss
import play.api.mvc._
import com.google.inject.ImplementedBy
#ImplementedBy(classOf[ProfileTraitImpl])
trait ProfileTrait extends Controller {
def Addone()
}
ProfileTraitImpl:
package traitss.impl
class ProfileTraitImpl extends ProfileTrait {
// your implementation goes here
}
Create a module where you can bind the implementation with trait
import com.google.inject.AbstractModule
class Module extends AbstractModule {
def configure() = {
bind(classOf[ProfileTrait])
.to(classOf[ProfileTraitImpl])
}
}
With using the modules approach you get an additional benefit of enabling or disabling the binding. For example, in your application.conf file you can enable/disable a module using play.modules.enabled += module OR play.modules.disabled += module
You can't inject a trait, you have to inject an object that implements that trait.
For dependency injection to work, you have to tell the framework (play uses Guice under the hood) how to resolve the dependency to be injected.
There are many ways to do it and it depends on your case, for more detail you can look at Guice's documentation, the simplest way in play is to create Module.scala into your app directory , if it's not there already, and put something like this:
import com.google.inject.AbstractModule
class Module extends AbstractModule {
override def configure() = {
bind(classOf[ProfileTrait]).toInstance( ... )
}
}
where in ... you put the logic to create the object you want to inject.