8

Is there a recommended pattern for shutting down / closing objects created with Guice?

The lifecycle I'm aiming for is:

  1. Prepare a Guice Module
  2. Create an injector
  3. Use the injector through your code to obtain objects (injector.getInstance(Foo.class))
  4. ...
  5. Close any resources held by said objects (file handles, TCP connections, etc...). I want this to be a deterministic step (not "some day when the GC runs").
ripper234
  • 222,824
  • 274
  • 634
  • 905
  • You might want to add some sample code to your question, because I don't really get what you mean. – dlinsin Nov 04 '09 at 14:53
  • Added some more details. – ripper234 Nov 04 '09 at 15:23
  • 8
    "Use the injector through your code to obtain objects (injector.getInstance(Foo.class))" - this is decidedly *not* how Guice, or any DI, is intended to be used. That's just a service locator. It should be building your object graph and the injector should only be created and referenced in some root bootstrapper class. – ColinD Nov 04 '09 at 15:31
  • It should be created only in a bootstrapper, but any object can use it to get access to other objects. Preferably, it should simply depend on the objects it needs and have them injected automagically, but that's not always the case. In any case, that's not relevant to my question. – ripper234 Nov 04 '09 at 15:34
  • 4
    Yes, that's why I commented rather than replying. I think that any place you might want to use injector.getInstance(Foo.class) you should be able to inject a Provider and use that instead, though. – ColinD Nov 04 '09 at 15:41
  • What's the difference? Perhaps I should start another question, but why is injecting a Provider better than injecting an Injector? One reason I guess is to allow not using an injector in unit tests ... but this means if a class needs to create several objects it needs all their providers, while a single injector suffices. – ripper234 Nov 04 '09 at 16:19
  • 4
    But then the class declares clearly what it depends on, whereas when you see a class that has a reference to the injector you have no idea what it might be getting out of there. And yeah, it's a pretty big difference for unit testing... don't have to configure an injector, just make a fake provider that returns instances however you want it to. You're no longer depending on the mechanism for providing dependencies... only on the dependencies themselves. – ColinD Nov 04 '09 at 17:58
  • +1 ColinD. BTW: if you want to handle transactions try warp persist: http://code.google.com/p/warp-persist/ ... unit-of-works can be specified. maybe that's what you can use? – Karussell Feb 03 '10 at 21:13
  • 1
    These comments are a waste of time! Great question! – rektide Mar 18 '13 at 14:45

1 Answers1

2

I want this to be a deterministic step (not "some day when the GC runs").

Sorry but then Java is the wrong language for you. The DI framework does not know when all the references to an object are gone. Only the GC knows this.

If you have a "closable" resource then use the try/finally pattern to close it (see below).

Closable c = // ...
try {
   c.use();
} finally {
   c.close();
}

Now to back peddle a little. Guice can know when a scope starts and ends. Your custom scope could run a clean up step when it finishes. This scope could even return proxies so the objects would be invalid if you attempted to access them out side of the allowed scope.

(Oh and +1 to ColinD - Inject providers. :)

EDIT: Guiceyfruit seams to have some support for Lifecycles

Michael Lloyd Lee mlk
  • 14,561
  • 3
  • 44
  • 81
  • 2
    I think this is just a classic misunderstanding of what the GC is for (particularly easy to make this mistake if you've programmed in C++). In a garbage collected language, object lifetime/GC has nothing to do with releasing resources like file handles or network sockets. – Simon Howard Nov 05 '09 at 10:46
  • The code block doesn't allocate the object, so it is not responsible for releasing it. Specifically singletons (within a Guice module) are obtained by Injector.getInstance(), but should not be closed after used. – ripper234 Nov 05 '09 at 15:30
  • 1
    This whole issue depends a lot on exactly what you're doing and in what context. Different objects have different lifecycles, different scopes, etc. so there is no catch-all easy solution. Are you doing this in a webapp? Are you mainly talking about closing singletons on shutdown? – ColinD Nov 05 '09 at 16:07
  • Singletons can only be "released" during the application shutdown (so via a shutdown hook). I'm sure you could write a scope that handled that. – Michael Lloyd Lee mlk Nov 05 '09 at 16:10
  • 1
    Also, if a code block retrieves a no-scoped object from a provider and uses it, it would definitely be responsible for closing that object if necessary despite not creating it itself. – ColinD Nov 05 '09 at 16:10
  • The code block doesn't allocate the object - Is the object created via a provider (or injected Injector) or injected into that object. If it is provided I would say that class that requested it is responsible for releasing it. – Michael Lloyd Lee mlk Nov 05 '09 at 16:11
  • @mlk, regarding your statement: _"The DI framework does not know when all the references to an object are gone. Only the GC knows this."_ True, but the DI framework is holding a reference to singleton instances and providers and modules! And there ought to be some way to trigger the release of all these things from the DI, to tell the injector & modules to give them up. For example, in RestEasy, I've implemented this- https://issues.jboss.org/browse/RESTEASY-843 . When a servlet context is destroyed it calls JSR250 PreDestroy annotated methods on modules to manually trigger cleanup. – rektide Mar 18 '13 at 22:35
  • I agree you can do it with items with clearly defined scopes (as with Guicetfruit linked above). That is what the whole "Now to back peddle a little" was about. – Michael Lloyd Lee mlk Mar 19 '13 at 09:41