It seems like i am able to inject Services or Akka Actors without the use of Module. May i know what is the purpose of Module then?
class Hello(implicit inj:Injector) extends Controller with AkkaInjectable {
val greetingService = inject[GreetingService]
implicit val system = inject [ActorSystem]
val greetingActor = injectActorRef[greetingActor]
def greet(person:Person) = Action {
Ok(greetingService.greet(person.name))
}
}
Even without the below it works just fine
class MainModule extends Module {
binding to new GreetingService
bind [ActorSystem] to ActorSystem("ScaldiAkkaExample") destroyWith (_.terminate())
binding toProvider new StatisticsProvider
}
Module basically instantiates the services and when you inject them to your controllers, all controllers share the same instance (which is what we want).
Without declaring the bindings in module you will have a new instance of service in every controller (which is not what we want).
However in Akka its the opposite
Quote from scaldi
I would like to point out how Actor are bound. It is important, that you bind them with toProvider function. It will make sure that Scaldi always creates new instances of the Actor classes when you inject them with injectActorRef or injectActorProps
Related
I'm not sure if there's something really basic that I'm missing, but I can't figure out how to use WSClient. I've seen all of the examples saying you need to pass the WSClient to a class as a dependency, which I've done, but when I run the program what do I actually pass to my class?
For example, my class signature is:
class myClassName(ws: WSClient)
But when I instantiate the class what do I actually pass to it? I'm also happy to ignore the Play! framework stuff if that makes it easier and just use SBT to run it (which I'm more familiar with).
It's unclear where you might be using a WSClient, but it is recommended that you let the Play framework 'manage' the instance of the client. When you instantiate your application, it gets injected:
class Application #Inject() (ws: WSClient) extends Controller {
...
}
What that means is that inside the ... you have access to ws as a value. You can instantiate myClassName using it:
class Application #Inject() (ws: WSClient) extends Controller {
val myclass = myClassName(ws) // passes the injected WSClient to myClassName
}
Or you can write a function that returns the WSClient, so some other area of your code can call into your Application object to get a object handler for it.
But the key is that the Application object gets that handle because of injection, which is the #Inject annotation.
If you need to generate a WSClient and manage it manually, there are good instructions here. The recommended implementation is reliant on Play! framework libraries, but doesn't depend on the Application.
I used to get the application.conf variable in Play 2.4.x with Play.current.configuration.getString('NAME_HERE'), and it was working good in class, object and companion object too.
Now, I'm using Play 2.5.4 with Scala in a new project, and I won't use this Play.current, because it's deprecated, but there is an alternative using DI, like this :
class HomeController #Inject() (configuration: play.api.Configuration) extends Controller {
def config = Action {
Ok(configuration.underlying.getString("db.driver"))
}
}
This DI Injection works like a charm in class, but in this project, I need to get the variable db.driver in a object? And as far I know, with an object I can't use DI.
Maybe using Guice would help?
You can use #Singleton annotated class instead of object
trait Foo {}
#Singleton
class FooImpl #Inject()(configuration: play.api.Configuration)) extends Foo {
//do whatever you want
}
#Singleton makes the class singleton.It feels bit awkward because Scala itself natively have syntax object to create a singleton, But this is the easiest and probably best solution to DI into a singleton.
You also may create the singleton eagerly like the code below.
bind(classOf[Foo]).to(classOf[FooImpl])asEagerSingleton()
for more detail Info, You can look up Google Guice Wiki and Playframework site
EDIT
How you call it is exactly the same as how you DI in Playframework2.5.
class BarController #Inject()(foo: Foo) extends Controller {
//Do whatever you want with Foo
}
Guice basically generates new instance every time you DI, Once you put #Singleton, Guice use only one instance instead.
DI is for anti-high coupling.So when you want to use a class you defined from another class,You need to DI otherwise the classes are highly coupled which end up making it harder to code your unit test.
FYI, You can use them outside of Play with this technique.
Create an Instance of class which does DI via Playframework Guice Independently in Scala
Have you tried
import com.typesafe.config.ConfigFactory
val myConfig = ConfigFactory.load().getString("myConfig.key")
Above approach doesn't require you to convert your object to singleton class.
You can do
Play.current.configuration
however that will (probably) no longer be possible with Play 2.6.
Ideally, however, you would pass the configuration in as a parameter to that method of the object or, use a class instead of an object.
What I somtimes do to migrate 'from object to class':
class MyComponent #Inject() (config: Configuration) {
// here goes everything nice
def doStuff = ???
}
object MyComponent {
#deprecated("Inject MyComponent")
def doStuff = {
val instance = Play.current.injector.instanceOf[MyComponent]
instance.doStuff
}
}
This way, you're not breaking existing code while all users of your methods can slowly migrate to using classes.
Any way to resolve class in object in Scala. I want to use an instance of Configuration class in Configuration object.
package application
import com.google.inject.Singleton
import play.api.Environment
#Singleton
class Configuration(env: Environment) {
private lazy val config = play.api.Configuration.load(env)
val venturesTime = config.getBoolean("ventures.time")
}
object Configuration {
}
You cannot - in this scenario.
If you get an instance of your configuration via dependency injection, then that's only available inside the class. While the class can access the companion object's methods, the other way around doesn't work, because which instance should it take?
If you need the configuration inside the companion object, you should pass it to the respective method as a parameter.
On a different note, rather than injecting the environment, you could as well inject the configuration directly.
I'm trying to test an Actor A inside my Play 2.4 application with Scaldi. This actor is calling injectActorRef[B] that I want to mock with a TestKit.TestProbe.
Inside my specs2, I would like to be able to retrieve the probe for mocked B while providing the corresponding TestKit.TestProbe.ref to actor A.
I would like to do something like this :
implicit val inj = (new TestModule(){
bind[TestProbe] identifiedBy 'probeForB to TestProbe()
bind[B] to inject[TestProbe]('probeForB).ref
}).injector
inject[TestProbe]('probeForB).expectMsgType[] must ...
The issue is that the ref is an ActorRef and therefore does not match the expected Btype.
Is there a clean way to do that ?
Can we specify an ActorRef to be returned by injectActorRef[B]?
I ended up overriding the bind for Actor A.
val probeForB = TestProbe()
implicit val inj = (new Module() {
bind[A] to new A() {
override def injectB(): ActorRef = probeForB.ref
}
}).injector
As you mentioned, the issue is that inject[TestProbe]('probeForB).ref gives you an ActorRef back instead of an instance of actual actor.
If you would like to test it in a way you described, then you need define a binding of ActorRef for actor B as well. For example:
bind [BActor] toProvider new BActor
bind [ActorRef] identifiedBy 'bRef to {
implicit val system = inject [ActorSystem]
injectActorRef[BActor]
}
When you have this setup, then you can override the second binding with test probe:
bind [ActorRef] identifiedBy 'bRef to inject[TestProbe]('probeForB).ref
Please note, that this example is not direct equivalent since BActor now has a different supervisor (guardian actor, that's why we need to inject an ActorSystem here).
injectActorRef delegates an actor creation to a "context" (a parent actor or actor system) with context.actorOf. What makes it helpful is that it creates a special Props that injects new instances of BActor class when akka wants to create one. This means that scaldi does not have control over the actor lifecycle (it's pretty important, since akka itself has very sophisticated mechanisms for this), it just gives akka the knowledge how to create new instances of particular actor class.
If you are creating an actor within another actor (like you described), then the lifecycle of them both is strongly connected and managed by akka. That's the reason why in this case you can't simply override and Actor binding with an ActorRef binding for the tests.
I have a Logger class that logs events in my application. While I only need one instance of the logger in this application, I want this class to be reusable, so I don't want to make it a singleton and couple it with my specific needs for this application.
I want to be able to access this Logger instance from anywhere in the application without having to create a new one every time or pass it around to every class that might need to log something. What I currently do is have an ApplicationUtils singleton that I use as the point of access for the application's Logger:
object ApplicationUtils {
lazy val log : Logger = new Logger()
}
Then I have a Loggable trait that I add to classes that need the Logger:
trait Loggable {
protected[this] lazy val log = ApplicationUtils.log
}
Is this a valid approach for what I am trying to accomplish? It feels a little hack-y. Is there a better approach I could be using? I'm pretty new to Scala.
Be careful when putting functionality in objects. That functionality is easily testable, but if you need to test clients of that code to make sure they interact with it correctly (via mocks and spies), you're stuck 'cause objects compile to final classes and thus cannot be mocked.
Instead, use this pattern:
trait T { /* code goes here */ }
object T extends T /* pass this to client code from main sources */
Now you can create Mockito mocks / spies for trait T in your test code, pass that in and confirm that the interactions of the code under test with the trait T code are what they should be.
If you have code that's a client of T and whose interactions with it don't require testing, you can directly reference object T.
To address what you're trying to do (rather than what you're asking), take a look at TypeSafe's scalalogging package. It provides a Logging trait that you can use like so:
class MyClass extends Logging {
logger.debug("This is very convenient ;-)")
}
It's a macro-based wrapper for SLF4J, so something like logger.debug(...) gets compiled as if (logger.isDebugEnabled) logger.debug(...).