Noob questions - injector instances, shutdown, unit tests and reflection

1,265 views
Skip to first unread message

Ashwin Jayaprakash

unread,
Aug 22, 2011, 2:14:51 PM8/22/11
to google...@googlegroups.com
Hi, I've been making an attempt to learn Guice, but these questions kept cropping up. Hopefully someone here can provide answers.

  • Does constructor injection use reflection all the time or is there an option to switch to bytecode generation?
  • Is there a way to discard/shutdown the singletons? I saw Issue-62 and this seems to have been open since 2007 !!
    • How do you shutdown a module and restart it - example, when it has seen network/DB/JMS errors?
  • Can multiple Injector instances be created?
    • This would be useful for running multiple versions of the module in parallel
    • Or at least for module-level testing, I felt the need for starting the same module with different configurations
  • How do you guys make Guice work in JUnit?
    • I looked at various projects like Jukito, Guiceberry but they are all way too complex, unnecessary and really do nothing to help
    • Again, it all comes down to being able to start/stop multiple/single Injectors
    • Do you just use @Before anno in Junit to start the module once. But how do you shut it down for the next test?
  • Why isn't there a way to get the Injector from the Guice class? After creating the Injector, I had to store a reference to it in a singleton class' static field
    • This singleton-for-the-Injector kind of defeated the purpose of the whole thing. I was beginning to think that a simple Registry/Factory of my own would've accomplished many of these things

Thanks,
Ashwin.

Yuri de Wit

unread,
Aug 22, 2011, 4:21:59 PM8/22/11
to google...@googlegroups.com
Hi Ashwin, 

  • How do you guys make Guice work in JUnit?
    • I looked at various projects like Jukito, Guiceberry but they are all way too complex, unnecessary and really do nothing to help
    • Again, it all comes down to being able to start/stop multiple/single Injectors
    • Do you just use @Before anno in Junit to start the module once. But how do you shut it down for the next test?
There is a 3rd way that relies on a custom Runner for JUnit (See http://cowwoc.blogspot.com/2008/10/integrating-google-guice-into-junit4.html): it is much simpler than  Guiceberry, for instance, but also has some limitations (e.g. how to use it with the @Parameters annotation with it?).

In some ways, I also find JUnit4 adds some complexity (needed?) and tries to implement it's own DI for things like rules and method hooks to initialize data (maybe this is indeed the way to go for a DI independent interface?). For unit tests it is great, but when I try to add more complex harness around my integration tests I find it lacking (I think that TestSetup/TestDecorators were great in JUnit3). Consider the case where I am running tests simulating a cluster. I want to feed my tests with data based on whether this is in node1, node2, etc scope. @BeforeClass/@AfterClass and @Before/@After are too limiting for that. I wish was a Guice-based Runner that would allow me to easily define additional scopes (clusterwide/singleton, per-node/multithreaded/singlethreaded, per test class, per test) for test data and simply inject Provider<XXX> into my tests, support @Parameters with optionally something like Quickcheck/Haskell and support free injection in the contructor or even test methods. 

  • Why isn't there a way to get the Injector from the Guice class? After creating the Injector, I had to store a reference to it in a singleton class' static field
    • This singleton-for-the-Injector kind of defeated the purpose of the whole thing. I was beginning to think that a simple Registry/Factory of my own would've accomplished many of these things
Could you just inject the Injector with @Inject?

@Inject
private Injector injector;

-- yuri

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/Z91EearG0MIJ.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

Bob Lee

unread,
Aug 22, 2011, 7:16:09 PM8/22/11
to google...@googlegroups.com
On Mon, Aug 22, 2011 at 11:14 AM, Ashwin Jayaprakash <ashwin.ja...@gmail.com> wrote:
  • Does constructor injection use reflection all the time or is there an option to switch to bytecode generation?
Reflection, but it's very fast. 
  • Is there a way to discard/shutdown the singletons? I saw Issue-62 and this seems to have been open since 2007 !!
    • How do you shutdown a module and restart it - example, when it has seen network/DB/JMS errors?
Guiceyfruit supports @PreDestroy: http://code.google.com/p/guiceyfruit/ 
  • Can multiple Injector instances be created?
    • This would be useful for running multiple versions of the module in parallel
    • Or at least for module-level testing, I felt the need for starting the same module with different configurations
Yes.
 
  • Why isn't there a way to get the Injector from the Guice class? After creating the Injector, I had to store a reference to it in a singleton class' static field
    • This singleton-for-the-Injector kind of defeated the purpose of the whole thing. I was beginning to think that a simple Registry/Factory of my own would've accomplished many of these things
You typically shouldn't use Injector directly after the initial lookup. When you depend on types, Guice can check your dependencies up front. When you get objects directly form the Injector, you don't find out about missing deps until run time.

Bob

Ashwin Jayaprakash

unread,
Aug 22, 2011, 7:32:18 PM8/22/11
to google...@googlegroups.com
Bob, thanks.

Guiceyfruit - cool, will look into it. I hope it is compatible with Guice 3.0 and works with Java SE.

I didn't quite follow what said here:

You typically shouldn't use Injector directly after the initial lookup. When you depend on types, Guice can check your dependencies up front. When you get objects directly form the Injector, you don't find out about missing deps until run time.
The Guice example (http://code.google.com/p/google-guice/wiki/GettingStarted) does exactly that - accessing from Injector:
public static void main(String[] args) {
   
/*
     * Guice.createInjector() takes your Modules, and returns a new Injector
     * instance. Most applications will call this method exactly once, in their
     * main() method.
     */

   
Injector injector = Guice.createInjector(new BillingModule());

   
/*
     * Now that we've got the injector, we can build objects.
     */

   
RealBillingService billingService = injector.getInstance(RealBillingService.class);
   
...
 
}
How else do you get the injectors started and create the bound services?

Ashwin Jayaprakash

unread,
Aug 22, 2011, 7:45:23 PM8/22/11
to google...@googlegroups.com
Guiceyfruit 2.0 does not seem to work with Guice 3.0:

Caused by: java.lang.NoClassDefFoundError: com/google/inject/internal/MatcherAndConverter
    at org.guiceyfruit.support.internal.Errors.<clinit>(Errors.java:442)
    at org.guiceyfruit.support.internal.CloseErrorsImpl.<init>(CloseErrorsImpl.java:33)
    at org.guiceyfruit.Injectors.close(Injectors.java:302)

Colin Decker

unread,
Aug 22, 2011, 7:45:20 PM8/22/11
to google...@googlegroups.com
I didn't quite follow what said here:

You typically shouldn't use Injector directly after the initial lookup. When you depend on types, Guice can check your dependencies up front. When you get objects directly form the Injector, you don't find out about missing deps until run time.
The Guice example (http://code.google.com/p/google-guice/wiki/GettingStarted) does exactly that - accessing from Injector:
public static void main(String[] args) {
   
/*
     * Guice.createInjector() takes your Modules, and returns a new Injector
     * instance. Most applications will call this method exactly once, in their
     * main() method.
     */

   
Injector injector = Guice.createInjector(new BillingModule());

   
/*
     * Now that we've got the injector, we can build objects.
     */

   
RealBillingService billingService = injector.getInstance(RealBillingService.class);
   
...
 
}
How else do you get the injectors started and create the bound services?

You should generally only use the Injector once, to get the object that acts as the root of your application. It gets its dependencies injected in to it and they get their dependencies injected in to them, etc. without any reference to the Injector in any of them. You can then call some method on that object to get your application running. Of course, exactly what you do differs depending on how you're using Guice... if you're using guice-servlet, for example, you just create the Injector and let guice-servlet handle the rest without ever calling getInstance on it yourself.

-- 
Colin 

Ashwin Jayaprakash

unread,
Aug 22, 2011, 9:15:06 PM8/22/11
to google...@googlegroups.com
Consequently, if I nullify the reference to my Injector and if I do not have any static references and statically injected fields will the whole graph of injected objects get GC'ed?

Even if I have @Singletons would they get GC'ed?

I'm guessing Singletons are per-Injector and not our old fashioned static-referenced singletons which never get GC'ed unless the ClassLoader itself it released?
Reply all
Reply to author
Forward
0 new messages