Alternative to using Akka.system inside an object - scala

I am learning the Play Framework together with Scala, and I looked at the reactive-stocks tutorial that comes with activator for learning more about the framework.
In the learning project that I am creating (a simple chat) I want to have something similar to this snippet taken out from the tutorial:
object StocksActor {
lazy val stocksActor: ActorRef = Akka.system.actorOf(Props(classOf[StocksActor]))
}
That is, an actor that will only be instanciated one time on the application. But I found out that Akka.system is deprecated, so I should use dependency injection to get the ActorSystem. How would I do dependency injection in an Object?
object ChatRoomsActor #Inject() (actorSystem: ActorSystem) {
lazy val ref: ActorRef = actorSystem.actorOf(Props(classOf[ChatRoomsActor]))
}
I tried this code, but it doesn't work.

Related

How do I create thread pools in Play 2.5.x?

I am currently on Play 2.4.2 and have successfully created thread pools using the following below:
package threads
import scala.concurrent.ExecutionContext
import play.api.libs.concurrent.Akka
import play.api.Play.current
object Contexts {
implicit val db: ExecutionContext = Akka.system.dispatchers.lookup("contexts.db-context")
implicit val pdf: ExecutionContext = Akka.system.dispatchers.lookup("contexts.pdf-context")
implicit val email: ExecutionContext = Akka.system.dispatchers.lookup("contexts.email-context")
}
and then in the code with...
Future{....}(threads.Contexts.db)
We are ready to upgrade to Play 2.5 and having trouble understanding the documentation. The documentation for 2.4.2 uses Akka.system.dispatchers.lookup, which we use without issue. The documentation for 2.5.x uses app.actorSystem.dispatchers.lookup. As far as I know, I have to inject the app into a Class, not an Object. Yet the documentation clearly uses an Object for the example!
Has anyone successfully created thread pools in Play 2.5.x that can help out? Is it as simple as changing Contexts to a class, then injecting it wherever I would like to use this threading? Seems odd since to use the default ExecutionContext I just have to make an implicit import.
Also, we are using Play scala.
If you simply change your Contexts to a class, then you will have to deal with how to get an instance of that class.
In my opinion, if you have a number of thread pools that you want to make use of, named bindings are the way to go. In the below example, I will show you how you could accomplish this with guice.
Note that guice injects depedencies at runtime, but it is also possible to inject dependencies at compile time.
I'm going to show it with the db context as an example. First, this is how you will be using it:
class MyService #Inject() (#Named("db") dbCtx: ExecutionContext) {
// make db access here
}
And here's how you could define the binding:
bind[ExecutionContext].qualifiedWith("db").toProvider[DbExecutionContextProvider]
And somewhere define the provider:
class DbExecutionContextProvider #Inject() (actorSystem: ActorSystem) extends Provider[ExecutionContext] {
override def get(): ExecutionContext = actorSystem.dispatchers.lookup("contexts.db-context")
}
You will have to do this for each of your contexts. I understand this may be a little cumbersome and there may actually be more elegant ways to define the bindings in guice.
Note that I have not tried this out. One issue you might stumble upon could be that you'll end up with conflicts, because play already defines a binding for the ExecutionContext in their BuiltinModule. You may need to override the binding to work around that.

Scala and Slick: DatabaseConfigProvider in standalone application

I have an Play 2.5.3 application which uses Slick for reading an object from DB.
The service classes are built in the following way:
class SomeModelRepo #Inject()(protected val dbConfigProvider: DatabaseConfigProvider) {
val dbConfig = dbConfigProvider.get[JdbcProfile]
import dbConfig.driver.api._
val db = dbConfig.db
...
Now I need some standalone Scala scripts to perform some operations in the background. I need to connect to the DB within them and I would like to reuse my existing service classes to read objects from DB.
To instantiate a SomeModelRepo class' object I need to pass some DatabaseConfigProvider as a parameter. I tried to run:
object SomeParser extends App {
object testDbProvider extends DatabaseConfigProvider {
def get[P <: BasicProfile]: DatabaseConfig[P] = {
DatabaseConfigProvider.get("default")(Play.current)
}
}
...
val someRepo = new SomeModelRepo(testDbProvider)
however I have an error: "There is no started application" in the line with "(Play.current)". Moreover the method current in object Play is deprecated and should be replaced with DI.
Is there any way to initialize my SomeModelRepo class' object within the standalone object SomeParser?
Best regards
When you start your Play application, the PlaySlick module handles the Slick configurations for you. With it you have two choices:
inject DatabaseConfigProvider and get the driver from there, or
do a global lookup via DatabaseConfigProvider.get[JdbcProfile](Play.current), which is not preferred.
Either way, you must have your Play app running! Since this is not the case with your standalone scripts you get the error: "There is no started application".
So, you will have to use Slick's default approach, by instantiating db directly from config:
val db = Database.forConfig("default")
You have lot's of examples at Lightbend's templates.
EDIT: Sorry, I didn't read the whole question. Do you really need to have it as another application? You can run your background operations when your app starts, like here. In this example, InitialData class is instantiated as eager singleton, so it's insert() method is run immediately when app starts.

ScalaWS in play framework 2.5 and dependency injection of WSClient in custom class

I'm using Scala Play framework 2.5 and I would like to use dependency injection to inject an instance of WSClient into my custom class but I keep getting the following error.
not enough arguments for constructor TestClass: (ws: play.api.libs.ws.WSClient)service.TestClass. Unspecified value parameter ws.
I get the error when running the following code
class TestClass #Inject() (ws: WSClient) {
def doSomething() : Future[WSResponse] = {
ws.url("http://www.google.com").get()
}
}
val test = new TestClass()
val f = test.doSomething()
val result = Await.result(f, Duration.Inf)
println("doSomething: " + result)
Can someone help me resolve this problem of trying to inject a wsclient dependency into a custom class?
Thanking you in advance
Francis
This line:
val test = new TestClass()
It is not using the dependency injection support provided by Play. You are manually creating the instance of TestClass. I truly recommend that you read the following doc page:
PlayFramework: Scala Dependency Injection
Basically, when using runtime Dependency Injection, you don't create the instances manually. You let the DI framework do the job for you. But, if you are instead interested in compile time dependency injection, see the following page:
PlayFramework: Compile Time Dependency Injection

Play Framework PathBindable with Dependency Injection

I'm migrating a Scala Play application to 2.5 and am currently moving my components to dependency injection. There's one place left where I'm at a loss how to do it though. I have a PathBindable implicit conversion defined in the companion object:
object Task {
implicit def pathBindable(implicit stringBinder: PathBindable[String]) =
new PathBindable[Task] {
...
}
}
The implementation of the PathBindable needs to look up the object from a repository, but I haven't found a way to dependency-inject the repository here. As a workaround I'm using the now deprecated Play object:
val tasks = Play.application(Play.current).injector.instanceOf[TasksRepository]
Any ideas how to solve this properly?
According to Lightbend Engineer Greg Methvin, PathBindables should only depend on the state in the path. The reason is that the code runs on the IO thread and should therefore be fast and not block.
I think this is the only way you can access stuff like this in objects.
A better idea is to create a the transformer like this:
class TaskPathBinder #Inject() ( tasks : TaskRepository ) extends PathBindable[Task]{
// implementiation
}
and than inject it in services like this
class NeedsTaskPathBinder #Inject() ( service : SomeSerive ) (implicit taskPathBinder : TaskPathBinder) {
...
}
Hope the you get the idea.

Play-ReactiveMongo plugin: play2 testing a controller with a reactiveMongoApi

In the following, I am using the Play2 ReactiveMongo plugin in version 0.11.0.play24 (https://github.com/ReactiveMongo/Play-ReactiveMongo)
for Play 2.4.
As mentioned in the documentation located at http://reactivemongo.org/releases/0.11/documentation/tutorial/play2.html, a Play2 controller with Mongo is instantiated as follows:
class MyController #Inject() (val reactiveMongoApi: ReactiveMongoApi)
extends Controller with MongoController with ReactiveMongoComponents { }
Therefore, since the controller is now a class and not an object, it is not possible to use it as a singleton in the test cases.
However, I do not know how to inject the reactiveMongoApi in order to instantiate a MyController() with the right parameters in a test case (ScalaCheck or other...)
Do you have any idea/example on how to test such a controller with ScalaCheck or Specs2?
Thank you in advance!
You can produce a mock for ReactiveMongoApi (depending which mock framework you use):
val reactiveMongoApi = mock[ReactiveMongoApi]
and then you can do this:
new MyController(reactiveMongoApi)
That's the simplest approach. To use the actual ReactiveMongoApi object:
val app = new GuiceApplicationBuilder()
.in(Mode.Test)
.configure("play.modules.enabled" -> "play.modules.reactivemongo.ReactiveMongoModule")
.build
val reactiveMongoApi = app.injector.instanceOf[ReactiveMongoApi]
If it gets more complicated, for example, partially mocked nested dependency tree (this is more integration testing than unit testing), you may want to partially mock the Guice framework as explained here.
This project use Guice for dependency injection, Spec2 for testing controllers, and Frisby for testing endpoints.
https://github.com/luongbalinh/play-mongo