I have used Guice in my web app without problems and I wanted to use it in desktop app. I am certainly missing one thing - some way to tell my app how to bind everything and know what is what. In web app, I had declaration for that in Application class, how should I do it in my desktop app?
Here is relevant code that I am using:
public class GuiceModule extends AbstractModule
{
#Override
protected void configure()
{
// Enable per-request-thread PersistenceManager injection.
install(new PersistenceManagerFilter.GuiceModule());
// Business object bindings go here.
bind(ProjectQueries.class).to(JdoProjectQueries.class);
bind(new TypeLiteral<Repository<Project>>() { }).to(JdoProjectRepository.class);
}
My main class:
#Inject
public Repository<Project> projectRepo;
public void createNewProject() {
...
projectRepo.persist(newProject);
}
I am of course getting on projectRepo.persist(newProject);
So, what else do I have to do to make it work?
EDIT:
Ok, that part work now, thanks :) It seems that I need to do a bit more though to make persistence work that way.
I am getting NPE here now:
public void persist(T entity)
{
pmProvider.get().makePersistent(entity);
}
get() returns null here
It looks like
install(new PersistenceManagerFilter.GuiceModule());
is not enough. What do I need to do? My Repository class starts with:
public abstract class JdoRepository<T> implements Repository<T> {
private final Class<T> clazz;
private final Provider<PersistenceManager> pmProvider;
protected JdoRepository(Class<T> clazz, Provider<PersistenceManager> pmProvider) { this.clazz = clazz; this.pmProvider = pmProvider;
}
At my PMF I have:
public static class GuiceModule extends AbstractModule {
#Override protected void configure() {
bind(PersistenceManager.class).toProvider(new Provider<PersistenceManager>() {
public PersistenceManager get() {
return PersistenceManagerFilter.pm.get();
}
});
}
}
Create Bootstrap class with main method.
Move your current static main method code to non-static one. For example Application#run.
Create main method in Bootstrap class:
public static void main(String[] args) {
Injector injector = Guice.createInjector(new GuiceModule())
Application app = injector.getInstance(Application.class);
app.run();
}
Run Bootstrap class.
Any object that is created using a Guice injector will inject objects into its properties and methods. So one way will be to create an injector in createNewProject.
Injector injector = Guice.createInjector(new BeanModule(),.....
YourMainClass startClass = injector.getInstance(YourMainClass.class);
startClass.kickOfEveryThing();....
You need to at least ask one root object to the injector. This root object will be injected with objects, which will be injected with objects, etc. The the process needs to bootstrap.
See http://code.google.com/p/google-guice/wiki/GettingStarted
Injector injector = Guice.createInjector(new GuiceModule());
Main main = injector.getInstance(Main.class);
Related
I am very familiar with using spring to inject using #Bean & #Autowired. I have switched over to looking at guice and I am wondering what is the minimum involved to have it functioning. The following basic example throws a NPE:
import javax.inject.Inject;
public class ClassA {
String a = "test";
#Inject
public ClassA() {
System.out.println(a);
}
public void go() {
System.out.println("two");
}
}
The following class attempting to instantiate a new instance of ClassA:
import javax.inject.Inject;
public class ClassB {
#Inject
ClassA guice;
public ClassB() {
guice.go();
}
public static void main(String[] args) {
ClassB b = new ClassB();
}
}
I have tried all sorts of combinations of the following with no success:
public class SupportModule extends AbstractModule {
#Override
protected void configure() {
bind(ClassA.class);
//bind(ClassA.class).to(ClassB.class);
//others too
}
}
I must be missing a key thing somewhere here, I'm not quite sure where? do I need some manual instantiation of guice/configuration itself? I assume I possibly do.
guice.go(); <= NullPointerException occurs here, obviously the obj is null because my guice setup isn't right
In Spring i can do the following, I assume Guice can aid me in doing this too:
#Bean
public FrameworkProperties properties() {
return new FrameworkProperties();
}
and then just:
#Autowired
FrameworkProperties props;
do I need some manual instantiation of guice/configuration itself? I assume I possibly do.
Yes, you assumed right. You'll have to bootstrap the Injector modules that you have defined using the Guice.createInjector() method. Also, one other thing to note is when using a custom defined constructor like in ClassB, you'll have to use constructor injection. So in order to get this working, ClassB should look like:
public class ClassB {
private ClassA guice;
#Inject //This will inject the dependencies used in the constructor arguments
public ClassB(final ClassA guice) {
this.guice = guice;
guice.go();
}
public static void main(String[] args) {
/**
* If only type to type binding is required, you can skip creating a Module class &
* bootstrap the injector with empty argument createInjector like used below. But, when
* there are other kind of bindings like Type to Implementations defined in modules, you can use:
* final Injector injector1 = Guice.createInjector(new GuiceModule1(), new GuiceModule2());
*/
final Injector injector = Guice.createInjector();
final ClassB b = injector.getInstance(ClassB.class); //This will create dependency graph for you and inject all dependencies used by ClassB and downwards
}
}
Also, you can remove the #Inject annotation used in ClassA's constructor as you are not injecting any external dependencies in that constructor. You can look up the Guice's getting started wiki for more documentation.
class A {
public A() {
}
}
class B {
#Inject
#Named("A")
private A a;
public B() {
}
public A getA() {
return a;
}
}
class AModule extends AbstractModule {
#Override
protected void configure() {
}
#Provides
#Singleton
#Named("A")
public A providesA() {
return new A();
}
}
We are doing like this:
AModule module = new AModule();
Injector injector = Guice.createInjector(module);
B b = injector.getInstance(B.class);
System.out.println(sample.getA());
But we have many classes with A as dependency and we don't want to add this code every time we create an instance.
So, is there any way to auto inject instance of A while creating instance of B?
It is (usually) not correct to create as many top-level Injectors as you suggest in your question. Injector creation is expensive, and once Guice has calculated your graph of dependencies, you should not need to calculate it all over again. In general there should be one top-level Injector across your application, and any other Injectors are either "child injectors" or parts of a separate and unrelated object graph.
In order from "worst" to "best":
Keep the Injector statically
If you are introducing DI into a lot of existing or legacy code, then it may be tempting to stash the Injector into a publicly-accessible object.
public class InjectorHolder() {
private InjectorHolder() {} // Not instantiable
private static Injector injector;
public static void initializeInjector() {
injector = Guice.createInjector(new AModule(), new BModule(), andSoOn());
}
public static Injector get() {
return injector;
}
public static B getB() {
return injector.getInstance(B.class);
}
}
At this point you can call InjectorHolder.get().getInstance(B.class) or InjectorHolder.getB() from the parts of the app you've migrated so far. Note that this may be difficult to test, and relies on Guice directly from across your application—both of which are not ideal.
Use Guice static injections
Guice provides a few features for static injection, notably the method call requestStaticInjection(Class... types). With a call to that in your module, Guice will inject static members that have #Inject annotations as soon as the Injector is created.
public class StaticBModule extends AbstractModule() {
#Override public void configure() { requestStaticInjection(BFactory.class); }
}
public class BFactory() {
#Inject #Named("B") private static Provider<B> bProvider;
public B get() {
return bProvider.get();
}
}
Now you can call new BFactory().get() instead of new B(), and it'll all go to the same injector. Naturally, you could also allow new B() instead if you put a static Provider<A> into your B class and request static injection for that instead, or you could keep your BFactory as an instance and replace it during tests to issue the B instances you need. At that point, you might as well just retrofit the classes that call new BFactory() to instead include a static Provider<B>, and have them inject statically, and then migrate those, all the way up until you have a full DI solution (explained below).
You may also consult this SO question, which has an example.
Ideal solution
You've shown us A and B, but presumably some other class C uses many instances of B, and maybe YourApplication (which contains your static main method) uses C. You can use Guice to create an instance of YourApplication or C, and then C can contain an injected Provider<B> bFactory. Then, rather than call new B(), you can call bFactory.get() to create as many B instances as you might need.
This way, your classes depend on exactly what they depend on, with no static state or references to Guice other than at the top level.
Our project is setup as follows:
1) Main module: Contains a driver program which starts a Spark streaming server. It has its own Guice injector.
2) When message comes in, it goes to another module, which creates it's own Guice injector.
3) This module uses classes in other modules which themselves use dependent modules. Each of these modules creates its own Guice injector so that it can work independently, tested individually etc.
Here's a problem: Now we need a Singleton, but an object created as #Singleton is bound to an injector (Not to a ClassLoader), so when the Injector goes away the object goes away.
Questions:
1) Is our architecture bad? Should we not be creating an injector in every module?
2) How do we create a Singleton that will remain in a ClassLoader even when injector goes away?
BTW, we use Netflix Governator on top on Guice.
Note: Answer for the question which is supposedly duplicate of this question doesn't answer how a 'single' injector created on the top level module can be passed to the sub-modules. Also, if the sub-modules themselves don't have an injector, can we write standalone unit tests for them?
An idea for question 2 would be to use a provider that you can bind in all your different Modules. This provider would access a singleton that that exists 'outside' of Guice.
I have crafted a simple example where I provide access to a static field. You can change that to use the implementation of the Singleton pattern that suits your needs.
public class SingletonProvider implements Provider<TheSingleton> {
private static final TheSingleton instance = new TheSingleton();
#Override
public TheSingleton get() {
return instance;
}
}
Then we bind this to our different modules
public class Module1 extends AbstractModule {
#Override
protected void configure() {
bind(TheSingleton.class).toProvider( SingletonProvider.class);
}
}
public class Module2 extends AbstractModule {
#Override
protected void configure() {
bind(TheSingleton.class).toProvider( SingletonProvider.class);
}
}
And then I create two different injectors that return this same instance
public class Test {
public static void main(String[] args) {
Injector injector1 = Guice.createInjector(new Module1());
TheSingleton instance = injector1.getInstance(TheSingleton.class);
System.out.println("instance = " + instance);
Injector injector2 = Guice.createInjector(new Module2());
TheSingleton instance2 = injector2.getInstance(TheSingleton.class);
System.out.println("instance2 = " + instance2);
}
}
I have the following Guice module:
class MyModule extends AbstractModule {
#Override
protected void configure() {
bindListener(Matchers.any(), new TypeListener() {...});
}
#Provides
SomeClass createSomeClass(final Parameter param) {
log(param.getValue()); <-- this gets logged
...
}
}
What I found strange is that my TypeListener doesn't get notified about the Parameter type. Even though the provider is beign called and returns SomeClass. I also see the log statement so clearly the Parameter was injected by Guice.
#Override
protected void configure() {
bind(Parameter.class);
bindListener(Matchers.any(), new TypeListener() {...});
}
I'm aware of Untargetted bindings and the statement:
An untargetted binding informs the injector about a type, so it may prepare dependencies eagerly.
I would still expect Guice to call the TypeListener for any type which is either explicitly binded or injected for the first time.
So do I need to make untargetted binding for such classes as a rule of thumb?
NOTE: marking the Parameter constructor with #Inject doesn't solve the problem.
EDIT:
The complete example (hope I din't leave too much garbage) is as follows:
public class TestGuice {
public static void main(String[] args) {
Injector parentInjector = Guice.createInjector(new ParentModule());
Injector childInjector = parentInjector.createChildInjector(new SubModule());
childInjector.getInstance(Runnable.class).run();
}
static class ParentModule extends AbstractModule {
#Override
protected void configure() {
}
}
static class SubModule extends AbstractModule {
#Override
protected void configure() {
bind(SampleInjectedClass.class); // <-- Comment/uncomment here
final TypeListener typeListener = new TypeListener() {
public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
System.out.println("Type: " + type.getRawType());
}
};
bindListener(Matchers.any(), typeListener);
}
#Provides
Runnable createRunnable(final SampleInjectedClass sampleClass) {
return new Runnable() {
#Override
public void run() {
sampleClass.test();
}
};
}
}
static class SampleInjectedClass {
public void test() {
System.out.println("Test");
}
}
}
If the line is present the output is:
Type: class com.barcap.test.TestGuice$SampleInjectedClass
Type: class com.google.inject.internal.ProviderMethod
Test
If I remove the line I get:
Type: class com.google.inject.internal.ProviderMethod
Test
I noticed that if the injector wasn't created via the createChildInjector code the bind(...) is not necessary.
Just-in-time bindings created for child injectors will be created in an ancestor injector whenever possible. This means that, without the bind(SampleInjectedClass.class); line, the binding for SampleInjectedClass is created in the parent injector. Since the parent injector doesn't have your TypeListener, it won't be triggered.
Can you check your code? In my test on Guice 3, I couldn't reproduce what you're seeing.
Also, from the TypeListener docs, emphasis mine and typo sic:
public abstract void hear (TypeLiteral<I> type, TypeEncounter<I> encounter)
Invoked when Guice encounters a new type eligible for constructor or members injection. Called during injector creation (or afterwords if Guice encounters a type at run time and creates a JIT binding).
Though all the rest of your dependencies will be called on the TypeListener immediately when the injector is created, implicit ("just-in-time") bindings will not.
However, based on my example above, it appears that when a parameter is included in a provider method, it is registered on the same listener immediately. Can you produce a short self-contained example that shows the behavior you're asking about?
I'm still new to Guice and haven't used any DI frameworks before. After reading the official wiki and many other documents I'm still unable to wrap my head around it completely.
In my particular case I want to write a EL taglib function that uses some other (to-be-injected) class. As all taglib functions have to be declared as static, I can't just #Inject my dependency via constructor or setter. I thought of using the requestStaticInjection() method described in http://code.google.com/p/google-guice/wiki/Injections#Static_Injections but I unable to get it to work and haven't been able to find any good tutorial.
Thanks in advance for any help,
Arman
It doesn't get much more clear than that Guice documentation but here's a unit test that shows an example of how you can use static injection:
public class StaticInjectionExample {
static class SomeClass {}
static class TagLib{
#Inject
static SomeClass injected;
public static void taglibFunction(String foo) {
injected.something(foo);
}
}
static class TestModule extends AbstractModule {
#Override
protected void configure() {
requestStaticInjection(TabLib.class);
}
}
#Test
public void test() {
Injector injector = Guice.createInjector(new TestModule());
TagLib receiver = injector.getInstance(TagLib.class);
// Do something with receiver.injected
}
}