I am using the play framework version 2.49, I am trying to do a dependency injection and it is my first time doing this. I have 3 Folders Interface : Repository : Controllers. The interface lays out abstract methods that I implement inside a repository folder then inject into a controller action. I am only lost when it comes to the controller action. Here is a sample code of mines
Interface
package Interface
abstract class Iprofiles {
def edit_profile
def view_profile
def forgot_password
}
Repository
package Repository
import Interface.Iprofiles
import slick.driver.PostgresDriver.api._
class ProfileRepository extends Iprofiles {
val db= Database.forConfig("database")
// These 3 methods will have Database logic soon
def edit_profile: Unit
def view_profile: Unit
def forgot_password: Unit
}
Controller
package controllers
import play.api.data.Form
import play.api.data.Forms._
class Relations extends Controller {
def MyAction() = Action {
// How can I inject edit_profile in the repository folder here
Ok()
}
}
My Repository methods are empty right now but I will have Data logic in them soon. In My controller MyAction() method for example how can I do a DI and include edit_profile from the repository folder ? I have been searching for how to get this done but nothing has worked
Dependency Injection on the JVM is currently only about injecting object references, not method references. That is, in a class you declare a dependency to a type (typically an interface) and define the mapping from this (interface) type to an implementation (type) in the injector configuration.
During injection -typically during object construction - you get a reference to an object of the implementation type injected.
Then you can call all methods on that injected object.
So you need an attribute taking the reference and this is typically filled via a constructor parameter.
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.
I have been using Play! Framework for Scala for nearly a year now. I am currently using version 2.5.x.
I am aware of the evolution of controllers in Play and how developers have been forced away from static object routes.
I am also aware of the Guice usage in play.
If you download activator and run:
activator new my-test-app play-scala
Activator will produce a template project for you.
My question is specifically around this file of that template.
my-test-app/app/services/Counter.scala
package services
import java.util.concurrent.atomic.AtomicInteger
import javax.inject._
/**
* This trait demonstrates how to create a component that is injected
* into a controller. The trait represents a counter that returns a
* incremented number each time it is called.
*/
trait Counter {
def nextCount(): Int
}
/**
* This class is a concrete implementation of the [[Counter]] trait.
* It is configured for Guice dependency injection in the [[Module]]
* class.
*
* This class has a `Singleton` annotation because we need to make
* sure we only use one counter per application. Without this
* annotation we would get a new instance every time a [[Counter]] is
* injected.
*/
#Singleton
class AtomicCounter extends Counter {
private val atomicCounter = new AtomicInteger()
override def nextCount(): Int = atomicCounter.getAndIncrement()
}
You can also see its usage in this file:
my-test-app/app/controllers/CountController.scala
package controllers
import javax.inject._
import play.api._
import play.api.mvc._
import services.Counter
/**
* This controller demonstrates how to use dependency injection to
* bind a component into a controller class. The class creates an
* `Action` that shows an incrementing count to users. The [[Counter]]
* object is injected by the Guice dependency injection system.
*/
#Singleton
class CountController #Inject() (counter: Counter) extends Controller {
/**
* Create an action that responds with the [[Counter]]'s current
* count. The result is plain text. This `Action` is mapped to
* `GET /count` requests by an entry in the `routes` config file.
*/
def count = Action { Ok(counter.nextCount().toString) }
}
This means every controller which has the constructor of #Inject() (counter: Counter) will receive the same instance of Counter.
So my question is:
Why use #Singleton and then #Inject it into a controller, when for this example you could just use a Scala object?
Its a lot less code.
Example:
my-test-app/app/services/Counter.scala
package services
trait ACounter {
def nextCount: Int
}
object Counter with ACounter {
private val atomicCounter = new AtomicInteger()
def nextCount(): Int = atomicCounter.getAndIncrement()
}
Use it like so:
my-test-app/app/controllers/CountController.scala
package controllers
import javax.inject._
import play.api._
import play.api.mvc._
import services.{Counter, ACounter}
/**
* This controller demonstrates how to use dependency injection to
* bind a component into a controller class. The class creates an
* `Action` that shows an incrementing count to users. The [[Counter]]
* object is injected by the Guice dependency injection system.
*/
#Singleton
class CountController extends Controller {
//depend on abstractions
val counter: ACounter = Counter
def count = Action { Ok(counter.nextCount().toString) }
}
What is the difference? Is injection the preferred, and why?
Is injection the preferred way? Generally yes
A couple advantages of using dependency injection:
Decouple controller from the concrete implementation of Counter.
If you were to use an object, you would have to change your controller to point to the different implementation. EG Counter2.nextCount().toString
You can vary the implementation during testing using Guice custom bindings
Lets say that inside of Counter you are doing a WS call. This could cause some difficulty unit testing. If you are using dependency injection with Guice, you can override the binding between Counter and AtomicCounter to point to an offline version of Counter that you have written specifically for your tests. See here for more info on using Guice for Play tests.
Also see the motivations that Play had for migrating to DI.
I say generally because I've seen dependency injection go horribly wrong using Spring and other Java frameworks. I'd say you should use your own judgement but err on the side of using DI for Play.
Maybe because Scala's singleton object can't have parameters? For example, if you have a service class that has a DAO injected, and you want to use service in controller, you have to inject it. The easiest way(IMO) is DI with Guice... Also, you can have your dependencies in one place(module) etc...
I am not sure, if I understand your question, but injection is preferred because:
different parts of your application are less coupled
it is easier to replace your dependency with different class providing the same functionality (in case you would need to do that in future) - you will need to change few lines of code and not look for all occurrences of your object
it is simpler to test (especially when you need to mock something)
Shortly speaking: D from SOLID principles: "Depend upon Abstractions. Do not depend upon concretions".
I have DAO defined as follows:
#Singleton
class MyDAO #Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
I have an integration test which references this DAO:
class SomeIntegrationTest {
lazy val someVal = new MyDAO
}
How can I inject the DatabaseConfigProvider into the MyDAO in the SomeIntegrationTest? I cannot inject one in the constructor of the test because test classes do not take constructor parameters.
You can get your dependency injected by doing
val dbConfigProvider = app.injector.instanceOf[DatabaseConfigProvider]
where app is an instance of your FakeApplication. Without it, there is no way Play can inject your dependency for you. You can get an instance of FakeApplication by extending OneAppPerSuite, see the provided link for more details.
In general, there are three main ways you can gain access to some object(s) in your test:
manual creation of objects using the new keyword (not considered best practice)
injection via injector as shown here (either injecting objects directly or injecting a provider/factory which can get them for you)
in case of unit testing a class with some dependencies, having those dependencies mocked
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.