I would like to know if it's possible to inject dependencies using Guice without having to pass by the routing.
If it is how can I call my class Test #Inject()... within my application ?
I think there are two ways to use Guice in Play framework:
1) Directly instantiate an object based on the binding:
Add Guice to your Build.scala app dependencies
val appDependencies = Seq(
"com.google.inject" % "guice" % "3.0"
)
Create a Global class, which extends GlobalSettings, and bind interface to implementation in configure():
public class Global extends GlobalSettings {
private Injector injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(TestInferface.class).to(TestImpl.class);
}
});
}
In your Controller or any other class, use the #Inject annotation to get an instance of the interface:
#Inject
private Test test;
2) Dependency Injection for Play Controller
Override GlobalSettings.getControllerInstance to manage controller class instantiation either via Guice:
#Override
public <A> A getControllerInstance(Class<A> controllerClass) throws Exception {
return injector.getInstance(controllerClass);
}
How to use the Guice injection?
GET /test1 #controllers.ApplicationTest1.index()
GET /test2 #controllers.ApplicationTest2.index()
Route definitions starting with # will be managed by play.GlobalSettings#getControllerInstance method.
Related
I have recently updated dagger 2.8 to 2.9 dagger. and documentation of the last release have been added as follows:
-Added #BindsInstance for component builders to easily bind instances that are constructed outside of the graph.
-Producers: Added ProducerMonitor.ready (), which is called when all of a producer's inputs are available.
-Removed #Provides(type =...) usage. Use the annotations in dagger.multibindings instead. #Produces.type was also removed.
-All binding methods are now validated, even if they are unused in a particular #Component
-#Component.dependencies can no longer include #Modules.
I want to know how these new features:
Thank you!!
Note: I am new to dagger 2, but you want to be able to make maximum use of this library.
#bindsInstance is used for removing constructor from module and chaining modules where you get component.
Without #BindsInstance
#Module
public class AppModule {
private final Application application;
public AppModule(Application application) {
this.application = application;
}
#Provides
#Singleton
Application provideApplication() {
return application;
}
#Provides
#Singleton
public SharedPreferences providePreferences() {
return application.getSharedPreferences("store",
Context.MODE_PRIVATE);
}
}
These modules(ToastMakerModule, and SensorControllerModule) are for learning purposes they get context and instantiate , may not be practical for real examples
public class ToastMaker {
private Application application;
public ToastMaker(Application application) {
this.application = application;
}
public void showToast(String message) {
Toast.makeText(application, message, Toast.LENGTH_SHORT).show();
}
}
#Module
public class ToastMakerModule {
#Singleton
#Provides
ToastMaker provideToastMaker(Application application) {
return new ToastMaker(application);
}
}
#Singleton
#Component(modules = {AppModule.class, ToastMakerModule.class, SensorControllerModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
// DaggerAppComponent.build() returns this Builder interface
#Component.Builder
interface Builder {
AppComponent build();
Builder appModule(AppModule appModule);
Builder sensorControllerModule(SensorControllerModule sensorControllerModule);
Builder toastMakerModule(ToastMakerModule toastMakerModule);
}
}
Build component like this
appComponent = DaggerAppComponent
.builder()
.appModule(new AppModule(this))
.sensorControllerModule(new SensorControllerModule())
.toastMakerModule(new ToastMakerModule())
.build();
With #BindsInstance
#Module
public class AppModule {
#Provides
#Singleton
public SharedPreferences providePreferences(Application application) {
return application.getSharedPreferences("data",
Context.MODE_PRIVATE);
}
}
Component
#Singleton
#Component(modules = {AppModule.class, ToastMakerModule.class, SensorControllerModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
#Component.Builder
interface Builder {
AppComponent build();
// #BindsInstance replaces Builder appModule(AppModule appModule)
// And removes Constructor with Application AppModule(Application)
#BindsInstance
Builder application(Application application);
}
}
and build component like this
appComponent = DaggerAppComponent
.builder()
.application(this)
.build();
#BindsInstance lets the component host the dependency directly and hence the lifetime is the lifetime of the component. This can be used to avoid #Singleton scope. Does it even matter? Avoiding singleton scope helps DaggerAppComponent access the provider without a costly DoubleCheck. So yes, it is possible to still use the module and not use any scopes. However, using module still means that DaggerAppComponent is going to use a Provider factory to inject the dependency. Using #BindsInstance, the provider is not needed at all unless the dependency is injected lazily via Lazy<> or Provider<>.
Any dependencies (like String constants etc) that is known as AppComponent is being created are good candidates for #BindsInstance. Note this is based on Dagger 2.19.
If there is #inject, then it means there must be #provide?
inject field gets its value from #provide method of module?
Yes if you use Module
#Module
public class SomeModule {
#Provides
Unscoped unscoped() {
return new Unscoped();
}
#Provides
#Singleton
Scoped scoped() {
return Scoped();
}
}
BUT classes with #Inject constructor get automatically appended to your scoped component even if no module is specified for it:
#Singleton
public class Scoped {
#Inject
public Scoped() {
}
}
public class Unscoped {
#Inject
public Unscoped() {
}
}
If there is #Inject annotation then it's dependency can be provided in two ways :
By Using Provides annotation in module
#Provides
TasksPresenter provide TasksPresenter(TasksRepository tasksRepository, TasksContract.View tasksView) {
return new TasksPresenter(tasksRepository,tasksView);
}
By Using Constructor Injection
#Inject
TasksPresenter(TasksRepository tasksRepository, TasksContract.View tasksView) {
mTasksRepository = tasksRepository;
mTasksView = tasksView;
}
One thing to observe here is Constructor Injection solve two thing
Instantiate object
Provides the object by adding it to Object graph.
Im trying to refactor my app to use play 2.4 dependency injection instead of cake pattern.
How do you inject a class with parameter, for example
class A(valX: Int) { } // How do you Inject val X ?
class B #Inject() (a : A)
Usually you wouldn't pass a parameter like an Integer in dependency injection - you'd use different ways to pass it on, like via a method parameter or a setter method. Via dependency injection you can inject only instances that are under control of your dependency injection system.
This is a simple example:
public class MyClass {
private int myParameterY;
private final MyOtherClass myInjectedInstance;
#Inject
ComponentResults(MyOtherClass injectedInstance) {
this.myInjectedInstance = injectedInstance;
}
// Pass myParameterX
public void myMethodThatNeedXAndY(int myParameterX) {
// Do something with myParameterX and myParameterY
}
// Use this setter to initialize myParameterY
public void setParameterY(int Y) {
this.myParameterY = Y;
}
}
Or if it is a constant you could use 'bind' in your Guice configuration.
bind(Integer.class).annotatedWith(Names.named("myParameterZ")).toInstance(1);
And then use this annotations to inject it:
#Named("myParameterZ")
I'm writing a Java EE 6 application that makes use of Morphia to persist objects to MongoDB. I'd like to be able to #Inject my DAO classes where necessary, so I created a Factory class that instantiates the DAO appropriately. It looks something like this:
public class MyDAOFactory {
#Inject
private Datastore mongoDatastore = null;
/**
* Creates the DAO
*/
#Produces
#ApplicationScoped
public MyDAO createDAO() {
MyDAO dao = new MyDAO(
this.mongoDatastore);
return dao;
}
}
The code compiles fine, but when I run my application on JBoss EAP 6.1 it complains because MyDAO does not have a no-arg constructor. I would add one, but the Morphia BasicDAO class does not have one either, so I don't know that it would work that way.
Is there a way to #Inject a DAO instance into my EJB, Servlet, etc.? Or do I need to manually instantiate it every time?
It seems that CDI needs the no-arg constructor for MyDAO for some reason. Maybe because of how you use this bean (see specs ch.5.4 "Client Proxies" for possible reasons).
You cannot create a default constructor, because the base class does not have one and, from what I see from the code the super constructors make immediate use of their args. Therefore passing null to super() from a no-arg constructor will throw errors.
My suggestion is to create an interface (optionally extending org.mongodb.morphia.dao.DAO), e.g. MyDAOInterface that has all public business methods of MyDAO. Then modify MyDAO to implement this interface and change your producer to return MyDAOInterface:
public interface MyDAOInterface extends DAO {...}
public class MyDAO implements MyDAOInterface {
// same implementation
}
public class MyDAOFactory {
#Inject
private Datastore mongoDatastore = null;
/**
* Creates the DAO
*/
#Produces
#ApplicationScoped
public MyDAOInterface createDAO() {
MyDAO dao = new MyDAO(this.mongoDatastore);
return dao;
}
}
By the way, programming to interfaces has the extra benefit of making your code more testable, so it is worth the minor hassle.
I need to use GWT with a service-based domain layer - not beans with DAOs. Is the GWT 2.1 architecture with MVP and RequestFactory fitted for this? Or should I stay with RPC?
Thanks
GWT 2.1.1 adds a Locator and ServiceLocator mechanism to allow you to control how the RequestFactory server code obtains references to entities and service object instances.
For example, you can declare code like
class MyService.class {
// Note that this is not a static method
public void doSomething() {....};
}
class MyServiceLocator implements ServiceLocator {
public Object getInstance(Class<?> clazz) {
// Or use Guice, Spring, whatever provides instances of MyService
return new MyService();
}
}
interface MyRequestFactory extends RequestFactory {
#Service(value=MyService.class, locator=MyServiceLocator.class)
interface ServiceRequest extends RequestContext {
Request<Void> doSomething();
}
ServiceRequest myService();
}
If you need even more control over how RequestFactory interacts with your server domain objects or service code, you can inject instances of ServiceLayerDecorator into the service layer.