Closed GoogleCodeExporter closed 9 years ago
Couldnt @Inject be made available on zero-arg methods (and invoked after all
other
@Injects)? That would solve @PostConstruct
That being said, I feel that lifecycle methods are a legacy of setter-injection
and
are superfluous in guice, especially as constructor injection is now on par with
spring-style setter injection (auto-wire with annotations).
It's also significant (different from guice) that @Resource (with no name=..)
connotes field names being used as ids. Should that be considered an implicit
@Named?
Original comment by dha...@gmail.com
on 14 Mar 2007 at 11:36
lifecycle (which is what this is) will certainly be needed. +1 to hani's
JSR-250 suggestion.
(and its bogus to say that cxtor injection is now "on par" with setting
injection. picocontainer has been doing
cxtor injection just as long as spring has been doing setter (trivial to tweak
pico to use annotations). guice just
does it in a super-elegant and java5-friendly way)
Original comment by peter.royal@pobox.com
on 14 Mar 2007 at 11:43
Nooo!
@Inject on no-arg methods is a hack. Nothing is being injected, it'd be an
abuse of the annotation.
I do think that @Resource should work the way it's supposed to too (via field
name). Guice should be flexible
enough to be able to plug in different resolution mechanisms, and this is just
one of them.
Original comment by h...@formicary.net
on 15 Mar 2007 at 12:39
proper lifecycle is much more of an app-server/container issue. IMO I think
lifecycle
is overkill (you can currently do it just fine with ctors and @Inject-ed
methods).
just imho of course. =)
yes I am well aware pico did ctor injection long before anyone else, that's not
what
I was referring to.
Original comment by dha...@gmail.com
on 15 Mar 2007 at 1:27
yea come to think @Inject on no arg was a terrible idea
Original comment by dha...@gmail.com
on 15 Mar 2007 at 1:29
I am also deeply suspicious of the entire idea of "initialization" as separate
from
object construction. I think I'm lacking that great example that shows me why
construction is sometimes not enough.
That said, I can imagine some real value in an object being notified when its
Scope
has let it go. (Or, sometime after its Scope has let it go; and perhaps
individual
Scopes themselves need the flexibility to govern how strong their guarantee is
in
this regard.) Some objects, while 'alive', consume resources. You might for
example
need to close yourself some closeables.
I wonder if this could be accomplished by having Guice or the Scope detect that
your
object implements Closeable.
Original comment by kevin...@gmail.com
on 15 Mar 2007 at 2:55
Here's a very simple example.
You have field injection, and would like to do some init work.
You can't do it in the ctor since the fields can't be injected until after the
ctor has run.
If you want concrete 'init' work, imagine I want to cache some data from an
injected DataSource, if it's a field,
how would I do this caching?
Original comment by h...@formicary.net
on 15 Mar 2007 at 2:58
Stock answer: then don't use field injection? Now I need more meat to the
example to
tell me why it has to be field injection. :)
Original comment by kevin...@gmail.com
on 15 Mar 2007 at 6:04
I'm inclined to lean on garbage collection for finalization logic. Or to
delegate
responsibility to something like OSGi.
We really need an external post-injection/pre-scoping hook. Then you could do
whatever you want in a generic fashion:
1) Call an init() method or some annotated method.
2) Create a phantom reference to an object so you can close its resources before
garbage collection when the scope goes away.
3) Peform ad hoc injections. For example, Struts calls setters on interceptors
with
parameters from the config file.
Maybe something like this:
interface ProviderInterceptor<T> {
T intercept(Key<T> key, Provider<T> next);
}
Then you could apply them like this:
void bindInterceptor(Matcher<Key<...>> keyMatcher, ProviderInterceptor<...>
interceptor);
Original comment by crazybob...@gmail.com
on 15 Mar 2007 at 9:03
Im with kevin--use ctor injection its safer (final publication), better
(obvious to
non-guice factories) and has a tight contract (cannot partially inject a ctor
like u
can with fields).
the only reason I use field inj is convenience/laziness.
gc is probably a different stage of the lifecycle than closing/shutting
down--we have
no control over gc, but my canonical example is: a servlet container may
conceivably
want to signal a close hook to its beans (perhaps to cleanup the session), i.e.
injector.close(), which would be totally different to when those beans actually
get
finalize()-d.
That having been said I still think proper lifecycle should be managed by an
appserver. Pico does both but clearly states them as disparate features in the
doc.
Original comment by dha...@gmail.com
on 16 Mar 2007 at 12:45
I think we need more use cases. I've never actually needed to run code when the
session ends. If I really need to do this, I can always use the servlet API
directly.
Sometimes I wonder if other frameworks support lifecycle methods just because
it's so
easy to do.
Original comment by crazybob...@gmail.com
on 16 Mar 2007 at 12:54
I suppose ctor injection would be out if you were "reinjecting" an object (with
injectMembers) and wanted to rerun the init--in that case you could still fall
back
on a setter/psuedo-ctor without needing an independent "init" method.
Original comment by dha...@gmail.com
on 16 Mar 2007 at 1:00
You may want to release resources on hotdeploys (like datasources)--which REALLY
shouldnt count on the gc but yea I cant think of many use-cases outside of
appserver-style ones.
I dont really like the idea of lifecycle in DI anyway.
Original comment by dha...@gmail.com
on 16 Mar 2007 at 1:05
Here's a use case.
Being able to DI any POJO developed for use in Spring or EJB3. There's a ton of
code
out there which relies on the Spring IoC model (injecting optional properties
then
having a validation step after injection to double check things are OK). Most
libraries I'm aware of (Jetty, ActiveMQ et al) all tend to have their own
initialisation hooks. Indeed I'm not aware of any IoC container apart from Guice
which does not support at the very least an initialisation callback mechanism.
If you're writing really simple POJOs which only have a set of mandatory
dependencies, then sure constructor injection avoids the need for an init step
(as
the Pico folks promoted years ago).
However as soon as you have complex objects with multiple optional properties
which
may or may not be set, some of which may be mutually exclusive and need some
kind of
on-start validation, its much much cleaner to have a single well defined init
method
called (where you can check all the various optional parameters are fine and do
any
on-start-up caching & calculation etc).
The great thing about the init method is its called by the IoC container in
context
immediately after injection; so if there are any configuration issues (mostly
the
init callback is used to double check configuration when optional injections
are used
after-all) then the IoC container is capable of giving a better error message
as its
aware of the module/binder/injector being used. This avoids a runtime barf
later on
when the injection context & information is lost.
Original comment by james.st...@gmail.com
on 16 Mar 2007 at 7:04
Sorry, I meant use cases for the "tear down"/"stop" side of things.
The general ProviderInterceptor mechanism I suggested above should be able to
support
any type of "init" design--calling a method on an interface, calling an
annotated
method, running external logic, etc.
Original comment by crazybob...@gmail.com
on 16 Mar 2007 at 3:23
OK the common use case in EJB3 or Spring POJOs is to close down expensive
resources
like JDBC connections and the like when a scope is closed; e.g. using a
request-scope
for processing web requests or more commonly, singleton POJOs created within an
application scope.
e.g. its fairly common in web applications to have some singleton POJOs which
need
closing down in the correct order (as there is often a dependency order so you
wanna
close things down in the reverse order to which they were started). For things
like
JDBC connections, background threads, sockets and the like you typically don't
wanna
just pray and hope on GC kicking in and finalizers sorting it out for you. e.g.
folks
usually want their web applications to close down nice and promptly.
This could be implemented using a provider interceptor; calling a stop method
is just
a reverse of calling a start method etc. Its just the stop interceptor needs to
register the stop method call with a listener to Scopes closing down.
So to nicely support Spring POJOs we'd just look for DisposableBean interface;
for
EJB3 we look for @PreDestroy then call 'em when the scope closes down (FWIW I'm
not
sure what Spring does for non-singletons :)
Original comment by james.st...@gmail.com
on 17 Mar 2007 at 7:29
The only action we plan to take on this is to resolve issue 78. After we do
that we
should be able to close this one.
Original comment by kevin...@gmail.com
on 19 Mar 2007 at 6:31
Tear down/close hooks can be very useful for session-scoped beans that may hold
resources or need to notify someone else about their destruction.
Original comment by ekules...@gmail.com
on 20 Apr 2007 at 9:22
I have this "Spring-based" swing application that I'd like to convert to Guice,
as
I'm fed up by the refactor-unfriendlyness of the string identifiers. I've just
started looking into Guice for real, so I might easily be missing lots..
However, right after ditching Spring from the classpath to start my convertion,
I
quickly ran into the problem of destroy-methods. I'd like to be able to
"reboot" the
entire application, and that obviously (at least to me, please enlighten me if
I'm
missing something) requires a rather extensive use of destroying.
Is there a way to get hold of all objects that Guice have instantiated? Is it
possible to inject some kind of listener that lets me know which objects are
created,
so that I could destroy them myself?
Basically, I'd like a Inject.destroy()/stop() method - but I'd be happy to make
it
myself it is possible.. Hooks into the "internals" would be great.
Original comment by stolsvik
on 5 Jun 2007 at 4:47
Don't you have some root object you could just throw away and re-create? Is
there
some reason that garbage collection won't work?
If not, construction listeners (coming in the next release) will do what you
need.
Original comment by crazybob...@gmail.com
on 5 Jun 2007 at 4:55
.. okay, listeners sounds good!
When it comes to garbage collection, I really don't like to rely on that for
"external resources" - I thought that was "basic java": you might, for example,
use
up all your database connections if there suddenly are two or more db pools
hanging
around, and System.gc() is just a _hint_ to the runtime that you'd like GC to
happen.
Threads won't die either w/o some explicit "we're going down" message.
Googling "finalization java" gives several articles pointing out this fact, e.g.
"Don't rely on finalizers to release non-memory resources. ...But the same
program
may fail on a different JVM whose garbage collector doesn't finalize often
enough to
keep the program from running out of file handles."
(Really a mailinglist question, but..) Is there a timeframe for next version? Is
there a place where I can find such info myself?
Original comment by stolsvik
on 5 Jun 2007 at 7:06
You should release a critical resource in a finally block in close proximity to
where
you acquired the resource. Waiting for a framework to call you back means you're
holding onto the resource longer than necessary and taking the risk that it
won't get
cleaned up.
We don't have a concrete date for the next release yet, but it won't be long.
Original comment by crazybob...@gmail.com
on 5 Jun 2007 at 8:07
In other words, no object should ever hold a resource "occupied" between method
invocations? Only within the confines of a single method call?
Original comment by kevin...@gmail.com
on 5 Jun 2007 at 8:59
I wouldn't say that. More detailed use cases would help.
Original comment by crazybob...@gmail.com
on 5 Jun 2007 at 9:25
If objects are created in a scope, it only
makes sense that they can be informed that the scope
is gone.
The "classic" example is an object grabbing an expensive
non-gcable native in a scope and being informed that the
scope is gone - so it can release the resource in a timely
fashion. It may not be possible to release the resource
in the body of a function - i.t may for example be a handle
to a window.
Original comment by peter.ki...@gmail.com
on 5 Jun 2007 at 10:17
crazyboblee: so I should make my database _pool_ where I need a database
connection,
and then kill it when I don't need the connection anymore in a finally? Great
idea.
It is of course possible to handle _all_ external resources ("heavy Closables")
outside of Guice, and take care of destruction myself. That will however lessen
the
value of Guice slightly, I believe.
(.. but so far I like it real good! XML-hell be gone!)
Original comment by stolsvik
on 7 Jun 2007 at 12:40
Ha ha. I was talking about releasing connections for example, but why does
Guice need
to tear down my connection pool? When should this happen?
We're trying to find a solution to a problem we haven't really defined.
Original comment by crazybob...@gmail.com
on 7 Jun 2007 at 1:09
bob: i think the thing here is "in and out of scopes", like kevin refers to
comment 6.
If I'm instantiated within some scope, I'd possibly like to know when that
scope is
no more, so that I can release any non-memory resources.
However, there is a difference between singleton and instance "beans" (objects)
here.
Spring solves this by explicitly stating that the destroy methods won't be run
on
"prototype" beans (which are "instance"), while singleton beans (which are
default in
Spring), and the other scopes (request and (global) session) will have their
destroy
run.
http://www.springframework.org/docs/reference/beans.html#beans-factory-scopes-pr
ototype
This is pretty much OK, I think, since those "expensive" objects most likely
will be
of a "singleton" character (a db pool, or some other ERP connection used
throughout
some scoped call), while instance objects are of a "use and ditch"-character,
probably just holding onto memory, and should be able to cope with only their
finalizer being run, OR the method they're injected into should handle the
closing.
This goes hand in hand with the logic that states that "don't clean anything
other
than RAM in finalizers".
Thus basically, if only Guice somehow would let me known which objects it's
currently
"caching" (since I guess it'll have to do just that to handle the "singleton
scope"),
I could really manage destroy myself.
Original comment by stolsvik
on 8 Jun 2007 at 1:27
As a further point towards init() methods.
I just got myself Brian Goetz's "Java Concurrency in Practice". In chapter 3.2.1
"Sharing Objects -> Publication and escape -> Safe construction practices"
(p.41),
one may read "Do not allow the this reference to escape during construction".
This
was actually something I hadn't thought about: if you in a constructor do some
EventListener registration, you let the *not yet fully constructed* object
"escape",
and the eventlistener registration may invoke methods further down the line, or
back
on the object. Another interesting issue is to start Threads in the constructor,
again exposing the not-yet initialized object to a new running stack context.
This
obviously also goes for staring timers and threadpools. Both of these errors
may lead
to a whole bunch of interesting fuck-ups.
Brian suggest as a solution "expose a start() or initialize() method...", or
make the
constructor private, and expose a static factory method instead (that does the
"init()"). I guess this could be realized by using Providers, but wouldn't it be
easier with a @Initialize annotation possible on no-args methods?
Original comment by stolsvik
on 11 Jul 2007 at 1:00
PS: I just realized that this bug concerns two entirely different concepts: the
JSR
250 annotations, and object lifecycle handling.
I HIGHLY vote for the JSR 250 annotations being honored, natively, by Guice. One
should even consider to just drop (at least deprecate) the corresponding Guice
annotations.
(I also vote for the lifecycle methods (obviously, given my comments).)
Original comment by stolsvik
on 11 Jul 2007 at 7:47
I just got this message: "This is a proxy used to support circular references
involving constructors. The object we're proxying is not constructed yet.
Please wait
until after injection has completed to use this object."
a) Why doesn't it say which object we're talking about - the class?
.. but my point is b) This is what happens when I need to do initialization
stuff in
the constructor (here obviously trying to use the injected stuff), not having a
dedicated init-method that could be invoked afterwards. How can i wait "until
after
injection has completed", when I need to do initialization stuff, and Guice
refuses
to have init-methods?!
.. but also c) Isn't silent proxying like this un-good (performance wise)?
Spring
handles circular dependencies only if one of the classes in the circle have a
setter
instead of constructor injection, which breaks the circle (it "eagerly caches
the
instance for resolving circular dependencies"). (And spring have support for
init-method, did I mention that?! :))
Original comment by stolsvik
on 8 Aug 2007 at 1:40
Following up on point 27, in a web application context, if you want to
redeploy the application many times without running out of memory, you
need to ensure that any resources that reference the web application's
class loader are properly freed or that any objects in the parent
class loader do not have references to objects inside the web
application. The gc on its own cannot clean this up.
If you don't programmatically close the resources, then references
from them to the web application class loader will prevent the class
loader, any classes loaded by it and all static variables from being
gc'ed. After a number of redeployments, the JVM runs out of permanent
generation space, throws a OutOfMemoryError and you have to bounce the
process.
One common resource that needs to be shutdown are any threads started
in the web application since they contain a reference to the class
loader.
So you need an explicit shutdown method.
See this page for a discussion of the different libraries that can
keep a class loader from being gc'ed.
http://opensource.atlassian.com/confluence/spring/pages/viewpage.action?pageId=2
669
In our case, we start an Ice server with 30 threads and a Java
memcached client which has its own pool management thread, both are
singletons. As stolsvik stated, it looks like I would need to ask the
Injector for the singleton's that it constructed and then run a
shutdown method on them.
The one problem with this is that then I manually have to make sure I
shut them down in the correct order, when Guice already knows the
correct order from the dependencies when it constructed them.
Original comment by blair-ol...@orcaware.com
on 13 Feb 2008 at 6:14
I believe this could be implemented as a custom scope that remembers everything
it's scoped. The scope
would know whenever it provides a given object, and it could track which object
need to be disposed when
the scope ends.
Usually we have a hook when a scope is exited, and we could dispose the
appropriate objects at that time.
The tricks:
- finding dispose() methods. This could be a marker interface on the returned instance, on the Key's type, or
even just an annotated method somewhere.
- not leaking memory
The nice thing about implementing this as a custom scope is that it doesn't
make Guice's internals more
complex than they already are. The bad thing about implementing it as a custom
scope is that it competes
with Guice's built-in scopes for request, session, etc.. It would be reasonable
for a first-pass at this to fork
Guice's servlet extension. And we might even fold-in the implementation if it
seems to work okay.
Original comment by limpbizkit
on 30 May 2008 at 8:21
[deleted comment]
I'm with limpbizkit; handling the @PreDestroy or close type of lifecycles is a
responsibility of the Scope instances; as they are the objects capable of
knowing when the scope is closed - so it can register objects in the scope and
then close them when it is being shut down.
Already the servlet REQUEST and SESSION scopes already maintain a registry of
objects within that scope - and they are easily capable of knowing when
those objects go out of scope. So there really should be an easy way to
register some kind of hook to process all objects about to be closed via a
Scope
closing; we can then let folks register SPI hooks to invoke different shut down
mechanisms (e.g. auto-detecting Spring's DisposableBean interface - or
using @PreDestroy or some other user annotation driven mechanism etc).
i.e. rather than the end user having to replace the standard guice scopes for
REQUEST/SESSION to get the @PreDestroy / DisposableBean behaviour this
should be a standard feature IMHO. It may be that Guice out of the box comes
with no registered destroy handlers, but we should allow folks to use
additional Guice libraries to support @PreDestroy / DisposableBean without
having to move away from standard Guice scopes.
I'd also like to see a standard guice ApplicationScope that was easy to use; so
folks could create one or more application scopes, let Guice do the
injection; then at some point later on, close the application scope and have
all the singletons in that scope shut down cleanly (like folks do in Spring /
Pico / HiveMind / Plexus).
For the initialisation hooks, the guice framework knows when an object has been
created; so the Scopes don't really need to be involved; but some
kinda post-construction handler mechanism would be cool - so folks could use
the SPI to invoke methods annotated with @PostConstruct or invoke
objects with some kind of custom lifecycle interface like Spring's
InitialisingBean.
So in summary, I'd love Guice to have some kinda lifecycle hook in the SPI
which the default APPLICATION/REQUEST/SESSION scopes invoked on the
close of a scope and invoked on the post-construction of an object. Hopefully
folks can register multiple implementations of this handler; so folks can
add an implementation for JSR 250, one for Spring, one for registering objects
into the OSGi registry if annotated with something and for other
frameworks and custom lifecycle interfaces etc.
Original comment by james.st...@gmail.com
on 30 Sep 2008 at 10:45
I've taken a stab at adding support for @PreDestroy and Spring's DisposableBean
lifecycles; building above my
patch for issue 78: http://code.google.com/p/google-guice/issues/detail?id=78.
So far they only work with Singleton scoped objects; but I've also added the
functionality into the REQUEST and
SESSION scoped Scopes too - though I've not yet added any code to the Servlet
package to invoke the close()
methods yet.
I've introduced a Closeable interface which a Scope or Provider can implement;
so if a Scope implements
Closeable you can then close it down cleanly; ensuring that all objects are
closed and each exception thrown
is collected (rather like we do with the Errors class when binding objects).
Also I've added a close() method to Injector so you can close down any
singleton objects.
e.g.
Injector injector = Guice.createInjector(...);
// do stuff
// now lets cleanly close down the singletons in this injector
injector.close();
There are many possible strategies we can use to actually close down an object
held within a
Singleton/REQUEST/SESSION scope . e.g. respecting java.io.Closeable; or using
@PreDestroy on a method or
Spring's DisposableBean or some developer-defined lifecycle API/annotation
mechanism etc.
So I've introduced a strategy interface, Closer which is a strategy to close
objects down. So you can bind as
many Closer implementations into your binder and this patch will invoke them
all on each object in the scope
being closed. e.g. so you could install the JavaIO, JSR250 and Spring closers
to respect those lifecycles. If you
look at some of the Closer implementations in this patch it will become a bit
more clear.
Note this patch has no effect to objects created outside of a singleton (and is
currently not invoked for
REQUEST/SESSION scopes).
The code InjectorImpl.close() and REQUEST/SESSION scopes is fairly
straightforward. The more complex
change was dealing with the Singleton scope; as the singleton SINGLETON object
creates Providers for each
key which internally stores the singleton object. So to be able to close all
the singletons on an injector you
need to iterate through all the Providers in the bindings looking for providers
which are Closeable. Since
there's a lot of wrapping of Providers along with InternalFactory; I made a
number of internal wrappers and
adapters also implement Closeable. This should have no runtime effect when
folks don't invoke the
Injector.close() method.
Original comment by james.st...@gmail.com
on 6 Oct 2008 at 1:39
Attachments:
Is there any chance to get these functionality as an _extension_ of guice? These
solution seems to add two (?) more dependencies (javax.annotation.* is part of
JRE6)
to the framework. The majority of developers will use at most one of the
lifecycle
mechanisms.
Solving this like limpbizkit had it in mind (using custom scopes) would allow
us to
use different lifecycle demarcation mechanisms (javax.annotation,
DisposableBean,
etc.) depending on the actual needs.
Additionally I would like to see a solution that does not based on a servlet
container. There are lots of people using guice in standalone applications and
these
people might have a need for lifecycle support too ;) Lifecycle support should
also
cope with other environments.
Original comment by sven.lin...@gmail.com
on 7 Oct 2008 at 3:51
BTW my patch is modular. The jsr250 module is optional (and is the module that
depends on JSR250) ditto the
Spring code is in the spring module.
However the support for ConstructorInterceptor has to kinda go into the core
guice package as its code is like
that of MethodInterceptor which is already in the core. The core guice module
still just depends on the
aopalliance.jar so no new dependency has been introduced in the core module;
the spring module is still
dependent on spring and the new optional jsr250 module is just dependent on the
JSR 250 API
Original comment by james.st...@gmail.com
on 7 Oct 2008 at 3:57
Hi, i write this because of some frustation reading the block here. For me it
seems
that some are thinking of guice as a tool for osgi and j2ee ONLY. if guice
should be
just that - ok - but then guice should be renamed to just another tool to make
the
j2ee world bigger. Guice is advertized as "next-generation dependency injection
container for Java 5 and later".
Back to the issue - guice outside of a managed container has no livecycle
management
at all if field or method injections are used. Except for "constructor only
injections" there is no single point of "being initialized". But field and
method
injection are part of guice - aren't they?
Isn't that missing livecycle a serious issue by itself? I think that's what Sun
has
forseen with it's javax.annotation package in java6 - smart,because this is an
architecture issue not just a usage case.
Someone asked here for usage cases - beside I think that's the wrong question
for a
fundamental package like guice - nevertheless here is one for a Swing based
application:
I wanted to use guice in a swing based environment to bootstrap a Swing
application.
Having hundreds of JPanel's needing access to hierachical application wide
services.
In a single panel there may be 2 to 50 other JComponent's and other classes
constructed. So to use juice I found three choices:
1.) use guice and constructor only injectors for the panels- then I endup with
constructors with up to 50 parameters and initialize the panel inside of this
huge
constructor - very very ugly
2.) pass (or inject) a Injector instance into all panels and use
injector.getInstance(...) - then I don't need guice - any singleton pattern
could do
that same thing better.
3.) don't use guice
I think we end up to go with the option 3.)
Note: the application wide services in our case are hierachical and would fit
very
well into guice Scope and Stage concept - many of these services are not just
singletons. Guice would have helped a lot if there would be a point where the
panels
could be "initialized" after being fully constructed (and injected). In this
environment there is no way around an init() or createComponent() or
postConstructed() pattern. Or you end up with "constructor-only" classes.
Just to strengthen my point for those knowing the Eclipse architecture: Eclipse
implementation solved this by using inheritance - ending up with a almost
endless -
in my opinion - very ugly class hierachy of 10th of levels of inheritance. Any
simple
eclipse panel (pane) knows by inheritance any service providers of eclipse!!! A
Service oriented architecture for an ui would have been much cleaner.
Original comment by heinz.in...@googlemail.com
on 5 Dec 2008 at 10:06
Just to keep this thread up to date; using trunk of Guice its now easy to
implement @Resource injection (this
works perfectly now in GuiceyFruit using the trunk of Guice) and @PostContruct
is pretty much there - though
there's a potential ordering issue of post inject hooks being invoked before
custom injections have all taken
place - see
http://code.google.com/p/google-guice/issues/detail?id=351
The only missing piece now is being able to close resources which are bound to
some scope (e.g. singleton,
request, session etc). There's no current way to implement @PreDestroy from JSR
250 or DisposableBean from
Spring using trunk of Guice.
I'll try refactor my old patches into a simpler patch just for this issue and
spin up a new issue to track its
progress
Original comment by james.st...@gmail.com
on 3 Apr 2009 at 10:04
"he only missing piece now is being able to close resources which are bound to
some scope (e.g. singleton,
request, session etc). There's no current way to implement @PreDestroy from JSR
250 or DisposableBean from
Spring using trunk of Guice."
Why not? you can register the objects before firing post-construct and provide
an api or jvm shutdown hook to
call pre-destroy...
Original comment by dha...@gmail.com
on 3 Apr 2009 at 10:12
@dhanji: actually thats a neat idea :)
I'm gonna take a stab at trying to implement that.
My only reservation is that all the scopes (application, request, session)
*already* store the objects (they have
to so that they can be reused within the scope).
So all we need really need is a way of iterating through all the objects in a
scope so they can be closed. (e.g.
iterating through the request/session scopes in the servlet or through the
injector's bindings for application
scope). It does feel a bit dirty and inefficient having another Map for each
application/request/session scope
and copying all objects into them just because Guice can't expose a hook to
process all objects within a
scope.
But in the meantime you're idea is a great workaround :)
Original comment by james.st...@gmail.com
on 3 Apr 2009 at 10:36
@dhanji: it also saves me the dread of trying to merge an old massive & complex
patch against trunk of Guice
which has changed alot - many thanks :)
Original comment by james.st...@gmail.com
on 3 Apr 2009 at 10:47
@james.strachan
=)
You can hook into most of the scopes, by rebinding the annotations to your own
scoping wrapper and fire the
destroy event appropriately. Note that Guice Servlet already fires destroy()
properly on the servlet lifecycle event
and can be hooked into in webapps...
Original comment by dha...@gmail.com
on 3 Apr 2009 at 11:20
Why didn't anyone mention a hibernate Session, which MUST be closed after use?
Original comment by elijah.e...@gmail.com
on 13 Apr 2009 at 11:27
And more provocative question:
- How can you call a Scope scope when it can't terminate?
This is just to highlight that a tool that provides means of creating objects
must
also provide means to properly destroy them. Or else how could I create an
expensive
object except of in Scopes.SINGLETON?
Original comment by elijah.e...@gmail.com
on 13 Apr 2009 at 11:40
@45
"Why didn't anyone mention a hibernate Session, which MUST be closed after use?"
If you use warp-persist this is done for you on transactions or Http requests
(or any granularity of session,
really). You can even set up a scope around the session or transaction, which
is consistent with our philosophy to
keeps scopes simple (by making scoping orthogonal to domain use cases).
Original comment by dha...@google.com
on 14 Apr 2009 at 12:09
BTW the patch on this issue:
http://code.google.com/p/google-guice/issues/detail?id=354 provides a
solution to the last remaining issue with lifecycle support - being able to
iterate through objects within a
scope so that you can close them (other than using a scope specific work around
such as the servlet
request/session scopes that @dhanji mentions). We're using this mechanism right
now in GuiceyFruit to
support @PreDestroy and Spring's DisposableBean interface.
I'm not sure which way this will go though; there's more discussion on various
possible implementations here:
http://groups.google.com/group/google-guice/browse_thread/thread/da6af0961cf4a5d
6
I certainly hope that some mechanism can be added though :)
Original comment by james.st...@gmail.com
on 15 Apr 2009 at 3:49
for the one expecting the feature, here is a "snipper" of mine:
//annotatedMethods is a simple method that return a list of any methods (and
super ones, that has the given annotation)
public static <T extends Annotation> List<Method> annotatedMethods(Class<?>
target, Class<T> annotationClass) {
List<Method> methods = new ArrayList<Method>();
while (target != null) {
for (Method m : target.getDeclaredMethods()) {
T annotated = m.getAnnotation(annotationClass);
if (annotated != null) {
methods.add(m);
}
}
target = target.getSuperclass();
}
return methods;
}
// the type listener itself
public class JFormDesignerTypeListener implements TypeListener {
public <T> void hear(TypeLiteral<T> typeLiteral, TypeEncounter<T>
typeEncounter) {
Class<? super T> raw = typeLiteral.getRawType();
List<Method> methods = annotatedMethods(raw, PostConstruct.class);
typeEncounter.register(new JFormDesignerInjector<T>(methods));
}
}
//and the JFormDesignerInjector :
class JFormDesignerInjector<T> implements MembersInjector<T> {
private List<Method> methods;
public JFormDesignerInjector(List<Method> methods) {
super();
this.methods = methods;
}
/**
* @param t
*/
public void injectMembers(final T t) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
for (Method m : methods) {
try {
m.setAccessible(true);
m.invoke(t, null);
} catch (InvocationTargetException ite) {
assert false : "Static Exception Occurred. @PostConstructor Method raises an exception:" + t.getClass() + ":" + m.getName() + " raises :" +
ite.getTargetException() + " : " + ite.getTargetException().getMessage();
} catch (Throwable e) {
assert false : "Static Exception Occurred. @See logs for more details in: " + JFormDesignerInjector.this.getClass().getName() + " " +
e.getMessage();
}
}
}
});
}
I've tried to simplified my actual code ( in fact I've mixed bean injections
from JFormDesigner and @PostConstructor ).
The main idea here is to use the swing invokelater to handle the
PostConstructor. this is quite nice for "swing" requirements ( as I had ).
Original comment by ericaro
on 5 Jan 2010 at 4:48
Dhanji and I discussed this at length this evening. We're thinking about taking
a Service interface, inspired by the one in Guava, with these methods. Note
that start() is renamed to startAsync() and likewise for stop:
interface Service {
boolean isRunning();
State state();
Future<State> startAsync();
void startAndWait();
Future<State> stopAsync();
void stopAndWait();
}
http://code.google.com/p/guava-libraries/source/browse/trunk/src/com/google/comm
on/base/Service.java?r=49
In addition, we'd like to support listeners on services, so objects could
register to be notified when a service changes state. The granularity of
registration may be by service instance or perhaps by Guice Key.
We were also discussing the interplay between services and scopes. It might be
useful to create a scope that's keyed off of a Provider<Service> for a
particular service, and whose objects are in scope only while a service is
running. This idea isn't fully baked.
Original comment by limpbizkit
on 23 Jul 2010 at 6:32
Original issue reported on code.google.com by
h...@formicary.net
on 14 Mar 2007 at 1:22