Play Framework: Inject multiple dependencies using constructor injection in the controller - scala

What is the right way to inject multiple dependencies using constructor injection for a controller in Play Framework (2.4.x, which provides guice based DI out of the box) in Scala?
For example,
class ExampleController #Inject() (serviceOne: ServiceOne, serviceTwo: ServiceTwo) extends Controller {
}
The above won't compile saying only one or no constructor arg can be injected.
Was not able to find any good references regarding as how to get this working. Any help is appreciated. Thanks.

You may need to prepend val to the parameters:
class ExampleController #Inject() (val serviceOne: ServiceOne, val serviceTwo: ServiceTwo) extends Controller {
And also check that you have the correct import:
import javax.inject.Inject
Here you also can find an example with multiple dependencies, maybe it helps.

Your code is correct. Additionally to that, you need to configure a module in your application.conf
play.modules.enabled += "com.example.HelloModule"
And then in this very Module you need to describe your dependency injected classes:
import play.api.inject._
class HelloModule extends Module {
def bindings(environment: Environment,
configuration: Configuration) = Seq(
bind[Hello].qualifiedWith("en").to[EnglishHello],
bind[Hello].qualifiedWith("de").to[GermanHello]
)
}
For the offical documentation see this link.

Related

With Play framework what am I doing wrong in setting up my routers

I'm a newbie to Play and Scala (version 2.6) and I can't figure out how to get the routing to work in a simple fashion. Cobbling together examples from the 2.6 documentation I've manage to create a custom application loader, which I understand is required to perform Evolutions migrations. The example I found included a var router = Routes.empty The BuiltInComponentsFromContext appears to require a router to be used, but in doing so, with the way I've done it my routes are now broken and now all I get are "Action Not Found" messages.
Here is my application.conf:
play.application.loader=MyApplicationLoader
router = my.application.Router
Here is the Application Loader
import play.api.ApplicationLoader
import play.api.ApplicationLoader.Context
import play.api.BuiltInComponentsFromContext
import play.api.db.{Database, DBComponents, HikariCPComponents}
import play.api.db.evolutions.EvolutionsComponents
import play.api.routing.Router
import play.filters.HttpFiltersComponents
//import com.softwaremill.macwire._
class MyApplicationLoader extends ApplicationLoader {
def load(context: Context) = {
new MyComponents(context).application
}
}
class MyComponents(cntx: Context)
extends BuiltInComponentsFromContext(cntx)
with DBComponents
with EvolutionsComponents
with HikariCPComponents
with HttpFiltersComponents
{
// this will actually run the database migrations on startup
//lazy val router = Router.empty
val router = Router.empty
applicationEvolutions
}
It looks to me by declaring:
val router = Router.empty
I'm essentially invalidating any of the routes I've declared in my conf/routes file, and it occurs to me to use the Router.load method, but I can't find an example of how to pass the required environment and configuration values to the method. Assuming I don't want to use static routes how do I do this?
Assuming that you only use compile-time dependency injection just for the sake of the Evolutions (because otherwise you'd faced the same problems earlier), the answer is that you don't have to do that. Evolutions work with the default dynamic dependency injection as well. The part of the documentation you probably basing your assumptions on actually says that if you are already using the compile-time dependency injection, here is how to modify it to make evolutions work. If you look at the source code of the EvolutionsModule you may see that ApplicationEvolutions is bound eagerly. It means that an instance of ApplicationEvolutions will be created at the start of the app during application initialization. And in the source code of the ApplicationEvolutions itself you can see that start() is called from the constructor. So if you provided configuration, the rest should work on its own.

How do make a `CustomExecutionContext` available for dependency injection in a Play 2.6 controller?

I'm following along with Play 2.6's Scala documentation and sample code for creating non-blocking actions, and am running into some runtime issues. I have created a new Play application using the Scala template (sbt new playframework/play-scala-seed.g8).
The code that the Play documentation suggests should work in a new controller is (this code is taken verbatim from the Play documentation page, with some extra imports from me):
// some imports added by me to get the code to compile
import javax.inject.Inject
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import akka.actor.ActorSystem
import play.api.libs.concurrent.CustomExecutionContext
import play.api.mvc._
import play.api.mvc.ControllerComponents
// end imports added by me
import play.api.libs.concurrent.CustomExecutionContext
trait MyExecutionContext extends ExecutionContext
class MyExecutionContextImpl #Inject()(system: ActorSystem)
extends CustomExecutionContext(system, "my.executor") with MyExecutionContext
class HomeController #Inject()(myExecutionContext: MyExecutionContext, val controllerComponents: ControllerComponents) extends BaseController {
def index = Action.async {
Future {
// Call some blocking API
Ok("result of blocking call")
}(myExecutionContext)
}
}
Then, according to the documentation for using other thread pools, I've defined the my.executor thread pool in the application.conf file of my application:
my.executor {
fork-join-executor {
parallelism-factor = 20.0
parallelism-max = 200
}
}
I should note that I do not want to use the default execution context as I want to prepare for running futures in a separate context that may be used for a limited resource like a database connection pool.
All of this compiles just fine with sbt compile. However, when I run this with sbt run and access my app in a web browser, I get this error:
CreationException: Unable to create injector, see the following errors:
1) No implementation for controllers.MyExecutionContext was bound.
while locating controllers.MyExecutionContext
for the 1st parameter of controllers.NewController.(NewController.scala:17)
while locating controllers.NewController
for the 2nd parameter of router.Routes.(Routes.scala:29)
at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:121):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
I've used Play 2.3 in the past, and know that dependency injection works when you define an instance of an object (via #Singleton or in a module); however, Play 2.6's documentation on DI indicates that "Guice is able to automatically instantiate any class with an #Inject on its constructor without having to explicitly bind it. This feature is called just in time bindings is described in more detail in the Guice documentation."
My question is: what specific lines of code or configuration do I need to add to Play's own sample to make this work, and why?
I found one possible solution when reading further in the Binding Annotations section of the Scala Dependency Injection documentation page. In particular, it states:
The simplest way to bind an implementation to an interface is to use the Guice #ImplementedBy annotation.
So, by adding that to the my MyExecutionContext trait, like so:
import com.google.inject.ImplementedBy
#ImplementedBy(classOf[MyExecutionContextImpl])
trait MyExecutionContext extends ExecutionContext
an instance of the MyExecutionContextImpl is instantiated and properly injected into the controller.
Too bad that this #ImplementedBy annotation isn't listed in the sample code for the non-blocking action documentation!

Migrating Play Framework 2.5 - moving from Global.onStart to Dependency Injection

So I am trying to migrate a PlayFramework application from version 2.4.3 to 2.5.6. I am using Squeryl and akka-quartz-scheduler, and Squeryl requires setting up a session manually and akka-quartz-scheduler runs as its own entity, as none of the other modules really depend on it, though it will depend on others. So previously there has been a Global-object to handle them on start up:
import org.squeryl.{Session, SessionFactory}
object Global extends GlobalSettings {
private lazy val injector = Guice.createInjector(CustomModule)
override def onStart(app: Application) {
SessionFactory.concreteFactory = // Squeryl initialization http://squeryl.org/sessions-and-tx.html
injector.getInstance(classOf[CustomScheduler]).initialize()
}
}
This has worked before. However, on 2.5.6 I'm trying to shift away from Global.scala altogether. I'm not sure if this is the best way to do this, but from documentation it seems like it. So I'm trying to create Singleton classes, and load them eagerly before the application loads like instructed here as a replacement for onStart. So like instructed on eager bindings -page I have:
import com.google.inject._
class CustomModule extends AbstractModule {
override def configure() = { // or without override
println("configure called")
bind(classOf[SquerylInitialization]).to(classOf[SquerylInitialization]).asEagerSingleton()
bind(classOf[CustomScheduler]).to(classOf[CustomScheduler]).asEagerSingleton()
}
}
import play.api.{Configuration, Application}
import play.api.db.{DB, DBApi}
import org.squeryl.{SessionFactory, Session}
#Singleton
class SquerylInitialization #Inject()(conf: Configuration, dbApi: DBApi) extends Logging {
SessionFactory.concreteFactory = // Squeryl initialization http://squeryl.org/sessions-and-tx.html
}
import akka.actor.{ActorSystem, ActorRef}
#Singleton
class CustomScheduler #Inject()(system: ActorSystem) extends Logging {
val scheduler: QuartzSchedulerExtension = QuartzSchedulerExtension(system)
// other initialize code here
}
The CustomModule inheriting the AbstractModule and its configure()-method is never called. It is said in Guice documentation that "Alternatively, play will scan the classpath for classes that implement AbstractModule". Documentation might not be the most recent, but that seems to be the way it works.
If for instance on all classes using Squeryl I use dependency injection to load SquerylInitialization it works, but I'm not sure if that's good way to do it as it would have to be required by tons of Classes, and there is hardly any Class depending on the CustomScheduler.
So basically the questions are:
Why isn't the CustomModule calling the configure()-method and eager
loading the Classes, and how that should be fixed?
Is this the standard way to load this kind of functionality, or should some other way used?
So basically comments are correct and the documentation was just out of date, so including
play.modules.enabled += "module.CustomModule"
helped. Thought I tried that as well, but turns out I didn't. Answer just a comment so can't accept that.

Use WSClient in scala app (play framework)

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.

How to get application.conf variable in an object using Scala and Play 2.5.x?

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.