google / guice

Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 11 and above, brought to you by Google.
https://github.com/google/guice
Apache License 2.0
12.48k stars 1.67k forks source link

Lifecycle support #62

Closed gissuebot closed 9 years ago

gissuebot commented 10 years ago

From hani@formicary.net on March 14, 2007 09:22:31

Support for JSR-250 (javax.annotation) would also be very useful for all those people using init() methods and the list.

The mapping I think is:

@PostConstruct -> Called right after construction @Resource -> Analogous to @Inject @PreDestroy -> No concept of destruction, is there? @Generated -> Doesn't apply

Original issue: http://code.google.com/p/google-guice/issues/detail?id=62

gissuebot commented 10 years ago

From dhanji on March 14, 2007 16:36:02

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?

gissuebot commented 10 years ago

From peter.royal@pobox.com on March 14, 2007 16:43:44

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)

gissuebot commented 10 years ago

From hani@formicary.net on March 14, 2007 17:39:38

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.

gissuebot commented 10 years ago

From dhanji on March 14, 2007 18:27:15

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.

gissuebot commented 10 years ago

From dhanji on March 14, 2007 18:29:00

yea come to think @Inject on no arg was a terrible idea

gissuebot commented 10 years ago

From kevinb9n on March 15, 2007 07:55:42

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.

Status: Accepted

gissuebot commented 10 years ago

From hani@formicary.net on March 15, 2007 07:58:59

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?

gissuebot commented 10 years ago

From kevinb9n on March 15, 2007 11:04:51

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. :)

gissuebot commented 10 years ago

From crazyboblee on March 15, 2007 14:03:26

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);

gissuebot commented 10 years ago

From dhanji on March 15, 2007 17:45:01

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.

gissuebot commented 10 years ago

From crazyboblee on March 15, 2007 17:54:09

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.

gissuebot commented 10 years ago

From dhanji on March 15, 2007 18:00:38

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.

gissuebot commented 10 years ago

From dhanji on March 15, 2007 18:05:21

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.

gissuebot commented 10 years ago

From james.strachan on March 16, 2007 00:04:08

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.

gissuebot commented 10 years ago

From crazyboblee on March 16, 2007 08:23:24

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.

gissuebot commented 10 years ago

From james.strachan on March 17, 2007 00:29:22

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 :)

gissuebot commented 10 years ago

From kevinb9n on March 19, 2007 11:31:12

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.

Owner: crazyboblee
Labels: -Type-Defect Type-Enhancement

gissuebot commented 10 years ago

From ekuleshov on April 20, 2007 14:22:04

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.

gissuebot commented 10 years ago

From stolsvik on June 05, 2007 09:47:12

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.

gissuebot commented 10 years ago

From crazyboblee on June 05, 2007 09:55:29

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.

gissuebot commented 10 years ago

From stolsvik on June 05, 2007 12:06:43

.. 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?

gissuebot commented 10 years ago

From crazyboblee on June 05, 2007 13:07:41

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.

gissuebot commented 10 years ago

From kevinb9n on June 05, 2007 13:59:00

In other words, no object should ever hold a resource "occupied" between method invocations?  Only within the confines of a single method call?

gissuebot commented 10 years ago

From crazyboblee on June 05, 2007 14:25:51

I wouldn't say that. More detailed use cases would help.

gissuebot commented 10 years ago

From peter.kitt.reilly on June 05, 2007 15:17:06

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.

gissuebot commented 10 years ago

From stolsvik on June 06, 2007 17:40:48

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!)

gissuebot commented 10 years ago

From crazyboblee on June 06, 2007 18:09:05

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.

gissuebot commented 10 years ago

From stolsvik on June 08, 2007 06:27:11

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-prototype 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.

gissuebot commented 10 years ago

From stolsvik on July 11, 2007 06:00:47

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?

gissuebot commented 10 years ago

From stolsvik on July 11, 2007 12:47:54

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).)

gissuebot commented 10 years ago

From stolsvik on August 08, 2007 06:40:24

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?! :))

gissuebot commented 10 years ago

From blair-old-google-id@orcaware.com on February 13, 2008 10:14:14

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=2669 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.

gissuebot commented 10 years ago

From limpbizkit on May 30, 2008 01:21:52

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.

Status: New

gissuebot commented 10 years ago

From james.strachan on September 30, 2008 03:45:13

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.

gissuebot commented 10 years ago

From james.strachan on October 06, 2008 06:39:07

I've taken a stab at adding support for @PreDestroy and Spring's DisposableBean lifecycles; building above my patch for issue 78 : https://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.

Attachment: gist    _complete_with_predestroy.patch_

gissuebot commented 10 years ago

From sven.linstaedt on October 07, 2008 08:51:21

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.

gissuebot commented 10 years ago

From james.strachan on October 07, 2008 08:57:23

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

gissuebot commented 10 years ago

From heinz.in.ulm on December 05, 2008 02:06:25

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.

gissuebot commented 10 years ago

From james.strachan on April 03, 2009 03:04:36

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 https://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

gissuebot commented 10 years ago

From dhanji on April 03, 2009 03:12:05

"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...

gissuebot commented 10 years ago

From james.strachan on April 03, 2009 03:36:13

@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 :)

gissuebot commented 10 years ago

From james.strachan on April 03, 2009 03:47:53

@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 :)

gissuebot commented 10 years ago

From dhanji on April 03, 2009 04:20:58

@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...

gissuebot commented 10 years ago

From elijah.epifanov on April 13, 2009 16:27:00

Why didn't anyone mention a hibernate Session, which MUST be closed after use?

gissuebot commented 10 years ago

From elijah.epifanov on April 13, 2009 16:40:06

And more provocative question:

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?

gissuebot commented 10 years ago

From dhanji+legacy@google.com on April 13, 2009 17:09:11

@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).

gissuebot commented 10 years ago

From james.strachan on April 15, 2009 08:49:27

BTW the patch on this issue: https://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/da6af0961cf4a5d6 I certainly hope that some mechanism can be added though :)

gissuebot commented 10 years ago

From ericaro on January 05, 2010 08:48:02

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();                                   &n...

gissuebot commented 10 years ago

From ericaro on January 05, 2010 08:48:02

...bsp;             } 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 ).

gissuebot commented 10 years ago

From limpbizkit on July 22, 2010 23:32:12

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();   } https://code.google.com/p/guava-libraries/source/browse/trunk/src/com/google/common/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.