I'm following the documentation here and trying to implement a named cache in my play (Java) project. I have a beforeStart method defined as below in my Global class:
public class Global extends GlobalSettings {
#Inject
#NamedCache("system-cache")
CacheAPI cache;
#Override
public void beforeStart(Application app) {
...
...
cache.set("test", "test"); //Throws a NullPointerException
}
However, it seems like the dependency injection does not work for the Global object. I can access the default cache using:
import play.cache.Cache;
....
public class Global extends GlobalSettings {
public void beforeStart(Application app) {
Cache.set("test", "test"); //This works
}
}
How do I access a named cache in the GlobalSettings class?
You need to use an eager singleton - this will allow you do inject whatever you want, and have it run as the app is starting up.
From the documentation:
GlobalSettings.beforeStart and GlobalSettings.onStart: Anything that needs to happen on start up should now be happening in the constructor of a dependency injected class. A class will perform its initialisation when the dependency injection framework loads it. If you need eager initialisation (for example, because you need to execute some code before the application is actually started), define an eager binding.
Based on the documentation example, you would write a module that declares your singleton:
import com.google.inject.AbstractModule;
import com.google.inject.name.Names;
public class HelloModule extends AbstractModule {
protected void configure() {
bind(MyStartupClass.class)
.toSelf()
.asEagerSingleton();
}
}
In MyStartupClass, use the constructor to define your startup behaviour.
public class MyStartupClass {
#Inject
public MyStartupClass(#NamedCache("system-cache") final CacheAPI cache) {
cache.set("test", "test");
}
}
In play2.4 there have been many changes around the GlobalSettings, you should not use it, and move to guice based configuration where you can add "hooks" when your application start and stop.
Take s look here at changes done for java.
And Take a look here on how to add a hook to your application.
Related
This is regarding to the Play framework 2.5.x
I have few Guice modules which extended by the AbstractModule and they are added as bindings to the GuiceApplicationBuilder method like below.
#Override
public GuiceApplicationBuilder builder(ApplicationLoader.Context context) {
return initialBuilder
.in(context.environment())
.bindings(new LoggerModule())
.bindings(new BaseConnectionModule(configuration))
.bindings(new CacheModule(configuration))
.bindings(new DaoModule())
....
One of my module (say CacheModule) declared private variables in that which are also Guice injected to be used in that class(inside Guice #Provides methods). The bindings for those variable are done in one of a GuiceModule (say BaseConnectionModule) which bound prior to the current module as mentioned in above code.
My question is, when the application get started, such variables declared as private in the CacheModule are not get instantiated.
Can someone please answer to this?
In my Application class, I have my singleton Dagger Component as a static object and reach it via its static getter method.
public class MyApp extends Application {
private static UtilsComponent utilsComponent;
#Override
public void onCreate() {
......
}
public static UtilsComponent getUtilsComponent(){
if(utilsComponent == null){
utilsComponent = DaggerUtilsComponent.builder()
.formattersModule(new FormattersModule())
.build();
}
return utilsComponent;
}
}
What I want to know is that is this the right way to do this? Can it cause problems? If so, what are those?
It's okayish. But why would you put it in the Application class? Put it in standard singleton class called for example Injector. Still you might want to initialize that singleton in Application which is fine.
It is ok, but you will not be able to use inject Context- dependent objects in that way. For component, requiring Context, use non - static accessor in Application class.
Speaking more widely, there will be as many components as your want, but if if component provides #Singleton - annotated functionality, lifecycle of component should not be longer that one of feature using it.
I'm working with a Guice enabled framework.
When using classes that were created by the framework (or subclasses that override existing bindings), I can instantiate framework provided variables very easily. Whatever I need, it's just a matter of
#Inject
FrameworkProvidedType variable;
However, in my custom created classes, that doesn't work. All of the injected variables are null.
It's my understanding that in order to use injection, my class has to have a binding.
If I'm subclassing an existing framework class, I can override the binding in my module class. That's pretty straightforward.
But I have a new class and I don't know how to bind it to the underlying framework.
public Class myCustomClass {
private String iNeedthis;
private Context thisToo;
#Inject
FrameWorkThing magic;
public myCustomClass(String iNeedThis, Context thisToo){
this.iNeedThis = iNeedThis;
this.thisToo = thisToo;
}
public void DoMagic(){
//null pointer error because magic was not injected
magic.doMagic(this.iNeedthis);
}
}
How do I Guice-enable this new class?
I tried this in my Runtime Module
public Class<myCustomClass> bindMyCustomClass(){
return MyCustomClass.class;
}
and failed miserably.
No thanks to #bmorris591 who dismissed and downvoted the question out of the gate, I found an answer.
#Inject-ing a field into a class means that the class instance needs to be created by Guice.
Step 1 is creating a factory for the class. This may not be necessary, but it worked for me.
public interface MyCustomClassFactory {
public MyCustomClass create(String iNeedThis, Context thisToo);
}
Step 2 is installing the factory into Guice
#Override
public void configure(Binder binder) {
super.configure(binder);
binder.install(new FactoryModuleBuilder().build(MyCustomClass.class));
}
In my particular case - the framework I'm working with provides a Module class that is an implementation of com.google.inject.Module.
Within that class is a "configure(Binder binder)" function that is called on startup.
Step 3 is actually annotating the constructor
#Inject
public myCustomClass(String iNeedThis, Context thisToo){
this.iNeedThis = iNeedThis;
this.thisToo = thisToo;
}
Useful and related web page that put me on the right track:
http://beust.com/weblog/2012/08/21/advanced-dependency-injection-with-guice/
This talks about assisted injection, but it gave enough information and a simple enough to understand example that taking the next step was pretty easy.
Lot's of times, classes need to be instantiated (constructed), and then "wired" (configured) before they can be used. For instance:
// Construction.
EventBus bus = new EventBus();
FizzEventHandler fizzHandler = new FizzHandler();
BuzzEventHandler buzzHandler = new BuzzHandler();
// Wiring.
bus.register(fizzHandler);
bus.register(buzzHandler);
In Guice, we accomplish the first part (construction; injection) with a Binder:
public class MyModule extends AbstractModule {
#Override
public void configure() {
bind(EventBus.class).to(SimpleEventBus.class);
bind(FizzEventHandler.class).to(DefaultFizzEventHandler.class);
bind(BuzzEventHandler.class).to(DefaultBuzzEventHandler.class);
}
}
But where does the wiring take place? When my Guice-based app starts up, we engage the DI "bootstrapping" process:
public class MyApp {
private EventBus bus;
private FizzEventHandler fizzHandler;
// ...etc.
public static void main(String[] args) {
MyApp app = new MyApp();
app.run();
}
public MyApp() {
// Bootstrap DI.
MyModule myModule = new MyModule();
Injector injector = Guice.createInjector(myModule);
bus = injector.inject(EventBus.class);
fizzHandler = injector.inject(FizzEventHandler.class);
// ...etc.
// Wire
bus.register(fizzHandler);
}
}
This works OK for the top-level (root) DI classes. But as we get further "down" the dependency tree, and get into all the other objects used by the application, putting the wiring logic in constructors like this is ugly and (I believe) is a discouraged practice.
So I ask: where doe battle-weary Guice veterans place their wiring/config code?
I work on a reasonably big system (~3000 classes) which uses Guice. I would say that our approach is to do everything with constructors. There aren't distinct "construction" and "wiring" activities as you describe, there's only construction.
In your example, the event handlers would be constructor parameters to the bus, which would register them in its constructor.
If you want to have fairly flexible injection of all the components of a given type (here, you would want to inject all event listeners into the bus), you could use multibindings. However, i don't think we actually use this in our codebase; we just write out manual lists of everything that needs injecting, which turns out not to be all that arduous in practice.
I generally use multiple modules, separated out by logical function. So one module might have authentication in it, another has data repositories, another the messaging system that I'm using, etc. This allows you to have different modules for mocking, caching Vs. non-caching, or just different implementations of the same service, and to switch out chunks of dependencies quickly and easily.
To make things even more flexible you could have a configuration file which declares the modules that should be used when the injector starts up.
When I have some logic to be done right after I instantiate my object I usually do it in methods annotated with #Provides. Your example might looks like this :
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(FizzEventHandler.class).to(DefaultFizzEventHandler.class);
bind(BuzzEventHandler.class).to(DefaultBuzzEventHandler.class);
}
#Provides
public EventBus getEventBus(SimpleEventBuss simpleBus/* this here is going to be injected as it is a class not an interface and Guice is clever and it know how to do it ;) */
, FizzEventHandler fizz, BuzzEventHandler buzz) {
simpleBus.register(fizz);
simpleBus.register(buzz);
return simpleBus;
}
}
I have a use case where it appears that referencing a Guice injector from multiple locations is the only solution—though this is generally discouraged.
My application is built on top of Talend, an open source ETL platform. Most of my actual application is in Java classes that are called by Talend components. These components include Java snippets that I write and that, in turn, instantiate/invoke my classes.
Now I intend to use Guice throughout my Java classes but there is absolutely no way for me to inject dependencies into the Talend components (so that they would be available to the Java snippets). Instead, I need to actually create these dependencies. I’d like to at least have Guice control the instantiation, which means that instead of using new, it appears that the only way I can instantiate my classes (the ones with #Inject constructors) is to call injector.getInstance. This, in turn, implies that I need to keep the injector around, presumably using an old-fashioned factory that creates it in the first place and makes it available as a singleton.
I just can’t see any other way to handle this but perhaps I’m missing something.
Consider static injection. This will still hide persistent references to your injector across your app, but it will save you from having to pepper your code with injector.getInstance(...) calls. In any case you can inject Injector if you really need to.
class TalendDependencyModule extends AbstractModule {
#Override public void configure() {
requestStaticInjection(ExtractorDependencies.class);
requestStaticInjection(ProcessorDependencies.class);
}
}
public class ExtractorDependencies {
#Inject private static Provider<ParserService> parserServiceProvider;
#Inject private static Provider<SomethingElse> somethingElseProvider;
private ExtractorDependencies() { }
static ParserService getParserService() {
return parserServiceProvider.get();
}
/* ... */
}
I don't know how many Talend objects you have but you might want to consider using providers. For instance suppose you have your own class that you want Guice to manage creation of:
public interface INotTalendControlled {}
public class NotTalendControlled implements INotTalendControlled {}
This will be added to a Talend object whose dependencies cannot be injected via Guice (although I assume there is some manual process for doing so either constructor or setter):
public class TalendControlled {
private INotTalendControlled notTalendControlled;
private TalendControlled(INotTalendControlled notTalendControlled) {
this.notTalendControlled = notTalendControlled;
}
public INotTalendControlled getValue() {
return notTalendControlled;
}
}
If you want Guice to manage these lifecycles and the lifecycle of Talend controlled objects you can use a provider like so:
public static class TestModule extends AbstractModule {
#Override
protected void configure() {
bind(INotTalendControlled.class).to(NotTalendControlled.class);
}
#Provides
public TalendControlled provideInjectsToTalendObject(INotTalendControlled notTalendControlled) {
return new TalendControlled(notTalendControlled);
}
}
The #Provides method will hide of the use of new for all objects as you can now directly inject TalendControlled objects (#Inject TalenControlled talendControlled) and an explicit injector is not needed to construct their dependencies.