How to pass ControllerComponents in compile time injection - playframework-2.6

My controller is defined as follows
class UserController #Inject()(userRepo: Repository[UUID, User],cc:
ControllerComponents)(implicit exec: ExecutionContext) extends
AbstractController(cc)
I want to inject Repository[UUID, User] into this component. I suppose I have to create an application loader and extend BuiltInComponentsFromContext and define my routes.
class AppComponents(context: Context) extends (context) with CassandraRepositoryComponents {
lazy val applicationController = new controllers.UserController(userRepository)
lazy val assets = new controllers.Assets(httpErrorHandler)
override def router: Router = new Routes(
httpErrorHandler,
applicationController,
assets
)
}
My code isn't compiling because I have to pass a ComponentController while creating UserController in lazy val applicationController = new controllers.UserController(userRepository). But I don't know from where to get this ComponentController. What should I do?

The BuiltInComponentsFromContext has instance of ComponentController
class AppComponents (context: Context) extends BuiltInComponentsFromContext(context)
with CassandraRepositoryComponents
with HttpFiltersComponents
with controllers.AssetsComponents
with CSRFComponents{
//TODOM - check if userRepository will be a singleton. Don't want new connection for each request.
lazy val userRepositoryController = new controllers.UserController(userRepository, controllerComponents) //controllerComponents is defined in BuiltInComponentsFromContext
...
}

Related

How to implement dependency injection in Flutter manually?

Since there is no official library from the flutter team, I'm trying to implement the dependency injection in flutter manually using the singleton pattern, after a long search this is what I came up with:
class Injector{
Injector._internal();
static final _singleton = new Injector._internal();
factory Injector() => _singleton;
SomeClass get someClass => new SomeClass();
}
Now, Injector is singleton that has one instance once instantiated and SomeClass is the dependency I want to inject in my code. The above code works, but the problem is where should I instantiate the Injector class and make it available every where in my code. Do you think Global Variable is good in this situation or is there a better way? Thanks.
To implement your own dependency injection I usually use a combination of
A 'Bindings' class which has getters to all injected services
A static getter/setter which holds a single instances of the Bindings class. This is important for overriding the bindings.
The getters which return classes should lazily construct them if they have dependencies. This allows you to override any parts of your graph by extending the Bindings class and setting it in the global bindings. For example, below I have three classes with the third depending on the first two.
class Foo {}
class Bar {}
class Fizz {
Fizz(this.foo, this.bar);
final Foo foo;
final Bar bar;
}
class Bindings {
/// Can be final since there are no dependencies
final Foo foo = new Foo();
final Bar bar = new Bar();
Fizz _fizz;
Fizz get fizz {
_fizz ??= new Fizz(foo, bar);
return _fizz;
}
}
Bindings get bindings => _bindings;
Bindings _bindings;
set bindings(Bindings value) {
_bindings = value;
}
Now suppose I want to override Foo for testing. I can extend the Bindings class and override the field/getter that returns Foo. and in my test setup, I set bindings with this new instance. Now when Fizz is created, the MockFoo instance is used instead of Foo
class MockFoo implements Foo {}
class BindingsOverride extends Bindings {
#override
final Foo foo = new MockFoo();
}
void main() {
bindings = new BindingsOverride();
}
Edit: In an earlier version I was using a static class. I don't think you need to refer to foo and bar through the bindings instance, you can just refer to the members directly.
This is my solution for this problem. First I created a dart file named injector.dart with this code:
// the singleton is private to this package
final _injector = new _Injector();
// expose depedencies
final foo = _injector.foo;
final bar = _injector.bar;
class _Injector{
// create a singleton
_Injector._internal();
static final _singleton = new _Injector._internal();
factory _Injector() {
return _singleton;
}
// the dependecies
Foo get foo => new Foo();
Bar get bar => new Bar();
}
This is how the code work, first we create a singleton class _Injector that creates needed dependencies and then exposes these dependencies with top-level variables. This way the dependencies are accessible anywhere the injector.dart package is accessible.
What do you think guys? is this good or is there a better implementation? Thanks

how to pass ComponentController to a controller

I have a controller. I want to pass a DAO component userRepo to it
class UserController #Inject()(userRepo: Repository[User,Integer],cc: ControllerComponents)(implicit exec: ExecutionContext) extends AbstractController(cc){...}
I am hooking compile time DI as follows:
class AppComponents(context: Context) extends BuiltInComponentsFromContext(context) with CassandraRepositoryComponents {
lazy val applicationController = new controllers.UserController(userRepository)
lazy val assets = new controllers.Assets(httpErrorHandler)
override def router: Router = new Routes(
httpErrorHandler,
applicationController,
assets
)
}
Question 1 - My issue is that I don't know what to pass as ControllerComponent
Question 2 - I am getting the following error missing parameter meta:AssetsMetaData for lazy val assets = new controllers.Assets(httpErrorHandler)
Question 3 - I suppose I am not using Routes correctly as well. I can see that IDE is displaying a potential error cannot resolve constructor
override def router: Router = new Routes(
httpErrorHandler,
applicationController,
assets
)
I am following the following tutorial but as it is based on Play 2.4, it will probably not run in 2.6. How could I make the code above work in Play 2.6?
http://manuel.kiessling.net/2016/01/17/compile-time-cassandra-injection-in-play-2-4/
Answer to 1 - BuiltInComponentsFromContext has an instance of ControllerComponents
Answer to 2 - Used assets defined in BuiltInComponentsFromContext.
Answer to 3 - The routes file expects that all the controllers are passed to it. In my case. I wasn't passing all the controllers.
Full code
class AppComponents (context: Context) extends BuiltInComponentsFromContext(context)
with CassandraRepositoryComponents
with HttpFiltersComponents
with controllers.AssetsComponents
with CSRFComponents{
lazy val userRepositoryController = new controllers.UserController(userRepository, controllerComponents) //answer 1
lazy val homeController = new controllers.HomeController(controllerComponents, csrfAddToken,csrfCheck) //answer 3. create all controllers and pass it to Routes below
//AtomicCounter is application's class, not Play's class to it is instantiated explicitly in the loader.
lazy val countController = new controllers.CountController(controllerComponents,new AtomicCounter())
lazy val asyncController = new controllers.AsyncController(controllerComponents, actorSystem)
lazy val userWSRoutes = new WSRouters.User.UserRouter(userRepositoryController) //I am using SIRD router, so creating them here
lazy val router = new Routes(httpErrorHandler, homeController,userWSRoutes, countController,asyncController, assets) //answer to 2
}

WebSocket.acceptWithActor and #Inject() in the Actor (Play 2.5)

WebSocket.acceptWithActor instantiates a new Akka actor without making use of Guice.
With Play 2.4, using the injector for my actor was still possible by importing play.api.Play.current.
Snippet from ReactiveMongo documentation:
import scala.concurrent.Future
import play.api.Play.current // should be deprecated in favor of DI
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.modules.reactivemongo.ReactiveMongoApi
import play.modules.reactivemongo.json.collection.JSONCollection
object Foo {
lazy val reactiveMongoApi = current.injector.instanceOf[ReactiveMongoApi]
def collection(name: String): Future[JSONCollection] =
reactiveMongoApi.database.map(_.collection[JSONCollection](name))
}
But in Play 2.5, play.api.Play.current is deprecated. How can I still inject ReactiveMongoApi in my actor? What is the recommended way of using an instance of ReactiveMongoApi in my actor?
Here is my code which works with Play 2.4 because my custom actor class ClientActor has access to ReactiveMongoApi through current.injector.instanceOf[ReactiveMongoApi]:
#Singleton
class Application #Inject() (system: ActorSystem) extends Controller {
val midiDiscoveryActor = system.actorOf(MidiDiscoveryActor.props, "midi-discovery-actor")
val midiActor = system.actorOf(MidiActor.props(midiDiscoveryActor), "midi-actor")
def index(page: String) = Action {
Ok(views.html.index(page))
}
def bidirectional = WebSocket.acceptWithActor[JsValue, JsValue] { request => out =>
ClientActor.props(out, midiActor, midiDiscoveryActor)
}
}
I don't think this is possible. Quoting James Roper:
The helpers that Play provides for dependency injecting actors are suited for a limited number of use cases. Though, the helpers are really just very thin wrappers over some common requirements - they're not needed at all. In the case Play's WebSocket actor support, the thing is, generally you want to manually instantiate the actor since you have to somehow pass it the out ActorRef. So, you can either do this using Guice assisted inject, and define a factor interface that takes the out actor ref (and whatever other arguments you want to pass to it), or simply instantiate it manually, passing dependencies from the controller to the actor, for example:
class MyController #Inject() (myDep: MyDep) extends Controller {
def socket = WebSocket.acceptWithActor[String, String] { request => out =>
MyWebSocketActor.props(out, myDep)
}
}
Play 2.5 has built in support for DI.
MidiActor signature needs to be modified as said below.
class MidiActor#Inject() (configuration: Configuration, #Named("midi-discovery-actor") midiDiscoveryActor: ActorRef) extends Actor with InjectedActorSupport{
.......
}
Create new Module and enable in application.conf
play.modules.enabled += MyModule
class MyModule extends AbstractModule with AkkaGuiceSupport {
def configure = {
bindActor[MidiDiscoveryActor]("midi-discovery-actor")
bindActor[MidiActor]("midi-actor")
}
}
Change your controller as below
#Singleton
class Application #Inject() (system: ActorSystem,#Named("midi-actor") midiActor: ActorRef,
#Named("midi-discovery-actor") midiDiscoveryActor: ActorRef) (implicit ec: ExecutionContext) extends Controller {
def index(page: String) = Action {
Ok(views.html.index(page))
}
def bidirectional = WebSocket.acceptWithActor[JsValue, JsValue] { request => out =>
ClientActor.props(out, midiActor, midiDiscoveryActor)
}
}

Bind list of objects using Guice + Kotlin

I'm writing a JavaFX application in Kotlin with the following controller definition:
class MainController {
#Inject private lateinit var componentDescriptors: List<ComponentDescriptor>
/* More code goes here */
}
I'm using Guice for Dependency management. And I'm trying to inject the list of class instances loaded via java.util.ServiceLoader. My problem is to define a binding that will inject the list of loaded object instances into the declared field. I tried annotation based provisioning:
internal class MyModule: AbstractModule() {
override fun configure() { }
#Provides #Singleton
fun bindComponentDescriptors(): List<ComponentDescriptor> =
ServiceLoader.load(ComponentDescriptor::class.java).toList()
}
and multibinding extension (switched List to Set in field definition of corse):
internal class MyModule: AbstractModule() {
override fun configure() {
val componentDescriptorBinder = Multibinder.newSetBinder(binder(), ComponentDescriptor::class.java)
ServiceLoader.load(ComponentDescriptor::class.java).forEach {
componentDescriptorBinder.addBinding().toInstance(it)
}
}
}
but both of these approaches leads to the same error:
No implementation for java.util.List<? extends simpleApp.ComponentDescriptor> was bound.
while locating java.util.List<? extends simpleApp.ComponentDescriptor>
for field at simpleApp.MainController.componentDescryptors(MainController.kt:6)
while locating simpleApp.MainController
1 error
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1042)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1001)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
at com.gluonhq.ignite.guice.GuiceContext.getInstance(GuiceContext.java:46)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:929)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
... 12 more
I'm starting to suspect that it somehow related to Kotlin gerenic variance and Guice strict type checking. But I don't know how to declare the binding so Guice will know what to inject into this field.
Yes, it happens because of variance but there's a way to make it work.
class MainController {
#JvmSuppressWildcards
#Inject
private lateinit var componentDescriptors: List<ComponentDescriptor>
}
By default Kotlin generates List<? extends ComponentDescriptor> signature for the componentDescriptors field. The #JvmSuppressWildcards makes it generate a simple parameterized signature List<ComponentDescriptor>.
#Michael gives the correct answer and explanation. Here's an example of one strategy for unit testing a Set multibinding for those that like to test their modules:
class MyModuleTest {
#JvmSuppressWildcards
#Inject
private lateinit var myTypes: Set<MyType>
#Before fun before() {
val injector = Guice.createInjector(MyModule())
injector.injectMembers(this)
}
#Test fun multibindings() {
assertNotNull(myTypes)
assertTrue(myTypes.iterator().next() is MyType)
}
}
#Michael comment is working. If you want to do the injection in constructor, you need do something like
class MainController #Inject consturctor(
private var componentDescriptors: List<#JvmSuppressWildcards ComponentDescriptor>
) {}

Cannot use grails g.link in domain class

I have static method in a domain class that returns a url. I need to build that url dynamically but g.link isn't working.
static Map options() {
// ...
def url = g.link( controller: "Foo", action: "bar" )
// ...
}
I get the following errors:
Apparent variable 'g' was found in a static scope but doesn't refer to a local variable, static field or class. Possible causes:
You attempted to reference a variable in the binding or an instance variable from a static context.
You misspelled a classname or statically imported field. Please check the spelling.
You attempted to use a method 'g' but left out brackets in a place not allowed by the grammar.
# line 17, column 19.
def url = g.link( controller: "Foo", action: "bar" )
^
1 error
Obviously my problem is that I am trying to access g from static context, so how do I get around this?
The g object is a taglib, which is not available inside a domain class like it would be in a controller. You can get at it through the grailsApplication as shown here: How To Call A Taglib As A Function In A Domain Class
A better way to do this in Grails 2+ is through the grailsLinkGenerator service, like so:
def grailsLinkGenerator
def someMethod() {
def url = grailsLinkGenerator.link(controller: 'foo', action: 'bar')
}
In both cases, you'll need to do some extra work to get grailsApplication/grailsLinkGenerator from a static context. The best way is probably to grab it off the domainClass property of your domain class:
def grailsApplication = new MyDomain().domainClass.grailsApplication
def grailsLinkGenerator = new MyDomain().domainClass.grailsApplication.mainContext.grailsLinkGenerator
If you're using Grails 2.x you can use the LinkGenerator API. Here's an example, I am re-using a domain class I was testing with earlier so ignore the non-url related functionality.
class Parent {
String pName
static hasMany = [children:Child]
static constraints = {
}
static transients = ['grailsLinkGenerator']
static Map options() {
def linkGen = ContextUtil.getLinkGenerator();
return ['url':linkGen.link(controller: 'test', action: 'index')]
}
}
Utility Class with Static Method
#Singleton
class ContextUtil implements ApplicationContextAware {
private ApplicationContext context
void setApplicationContext(ApplicationContext context) {
this.context = context
}
static LinkGenerator getLinkGenerator() {
getInstance().context.getBean("grailsLinkGenerator")
}
}
Bean Def for New Utility Bean
beans = {
contextUtil(ContextUtil) { bean ->
bean.factoryMethod = 'getInstance'
}
}
If you need the base URL, add absolute:true to the link call.

Resources