Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lifecycle support #62

Closed
gissuebot opened this Issue Jul 7, 2014 · 117 comments

Comments

Projects
None yet
4 participants
@gissuebot
Copy link

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

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

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

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

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

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

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From crazyboblee on March 14, 2012 17:11:10

I think closing/destroying objects when they go out of scope is a red herring.

It sounds like people really want the ability to start and stop per injector services in the right order. While the lifecycle of the service is the same as the injector's, the object isn't necessarily in singleton scope–maybe the service isn't eligible for injection into other objects (see Binder.requestInjection()).

@PostConstruct and @PreDestroy seem like a bad fit here. First, they don't speak to starting and stopping services. Second, and less important than the naming and semantics, using annotations will be slower and more error prone than using a marker interface.

How do we decide which objects are eligible to be started? Strawman: any object that's created or injected during injector creation. This includes eager singletons, objects passed to requestInjection(), and any transitive dependencies. Note: This could get a little weird if you use DEVELOPMENT vs. PRODUCTION stages.

One could use an InjectionListener named ServiceManager to collect any object that implements Guava's Service interface. After injector creation, you call ServiceManager.start(). ServiceManager stops collecting objects (by ignoring any further callbacks), and then it iterates over the objects in the order in which they were created–so you can use dependencies to control the order services are started in–and it starts each service.

When you're ready to stop, call ServiceManager.stop(). It'll stop the services in the reverse order.

Once Guice supports concurrent singleton injection (by inspecting the dependency graphs), ServiceManager could keep track of which threads the callbacks come in on. Then it could make sure that objects instantiated in the same thread are also started in the same thread.

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From hani@formicary.net on March 14, 2012 17:38:09

So checking for a @PostConstruct is a performance hit when you're already going through all methods and fields checking for @Inject? Why is it any slower?

The flow as I see it is, if guice creates an object, it is responsible, once the full object graphs has been constructed, for calling @PostConstruct. I don't see it getting weird with things like .injectMembers() and .requestInjection(), in those cases @PostConstruct would not apply because guice did not construct the object. Admittedly with stages it might get weird, but nothing that well specified behaviour cannot address. For a novice/beginner dev, there are plenty of non-intuitive and cryptic behaviours and features in Guice, but they're pretty well specified so it's not terrible.

Keep in mind also that all this is possible. I have all the extra behaviour I'd like in Mycilla Guice. There's just some fundamental issue I must be misunderstanding as to why it's so unthinkable for Guice to get those features.

The 'prove we need it argument' is not very compelling anymore, 100 comments and 5 years on from the initial request. I'd like to reverse the challenge, and ask for a non-core Guice developer to argue we absolutely should not have it!

Clearly all arguments in favor of this feature are not ones that have resonated with any Guice developers, so just close it and say it'll never happen.

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From crazyboblee on March 14, 2012 17:56:52

Iterating over methods and checking for an annotation is an order of complexity slower than "instanceof Service," especially if you didn't already need to reflect on those methods. This is just to say that it would be nice to not force this overhead on Android apps.

Why would we only start instances that Guice instantiated? Seems like an arbitrary limitation.

To be fair, I think you're asking for something different from what everyone else is asking for. Other people want to start/stop services, orthogonally to injector creation. That makes some sense to me, but needs further specification. For example, which objects exactly are eligible to be started?

You've said that you don't care about stopping things and you just want @PostConstruct. This does not make sense to me because @PostConstruct is barely different from a constructor. Also, if you just want @PostConstruct support, it's trivial to hook in with an InjectionListener already.

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From endre.stolsvik on March 14, 2012 19:46:47

Quick question: Have Guice gotten intelligent about the order in which it instantiates objects?

Earlier, it just did one or the other random order, not caring about each instance dependencies, creating those annoying proxies when it got to any dependency it didn't already have available.

Then one got the option of specifying that proxies should not be used.

However, the order hadn't gotten any smarter, so one still could arbitrarily crash into the ordering-problem, only now it stops with exception, not creating the proxy.

This even though a simple reordering of the flow would have fixed it.

First create the leafs; the ones without dependencies. Then work your way up: Create instances whose dependencies at this point be fulfilled. If you at some point iterate through the entire list of "to be instantiated" w/o instantiating any, then you have a dependency-loop.

Loops are only evaluated by constructors. Fields and methods can always be injected afterwards.

.. which leads to my point #1 about stuff like @PostConstruct..

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From endre.stolsvik on March 14, 2012 19:52:41

You need @PostConstruct because that would only be invoked after ALL dependencies have been injected - both the constructor and field/methods.

This because you might need some service of some injected instance to start up. And that instance was injected by means of field injection. No good with constructor startup then.

Also, according to JCIP IIRC, one shall not leak unfinished objects. In a constructor, you could e.g. register yourself with the OnIncomingUserEventService, and then your object instantiation crashes with a NPE for some other reason. Therefore, thou shall not ever do "startup stuff" in a constructor. Only construct yourself, do not e.g. attach yourself to other object graphs.

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From endre.stolsvik on March 14, 2012 20:12:46

When you folks create features out of this request, please enable me to do custom initialization.

I have always ended up in needing several initialization phases, not only a single @PostConstruct.

What I've needed, is at least a "now you've got all your dependencies and configuration, do your init code", and then a "now you can do listener registration with each other".

So my ideal solution to this is to get a list (preferably in instantiation order) so that I can invoke my different init methods on the relevant objects. This could be fetched by user code when the injector was finished setting up the entire graph (and have invoked @PostConstruct?) - and then the user could would do what life cycling it needs to do.

What I currently do, is to have a LifeCycle service which instances can depend on. There is also the LifeCycled interface. The objects register with the LifeCycle service, either in constructor (which is bad according to JCIP), or in the method injecting the LifeCycle service (better). After injector is finished, I run through all the instances that have registered with the LifeCycle service, all of which shall implement the LifeCycled interface. I then invoke method "phase1" on all objects, then method "phase2" on all objects, etc. (On application shutdown, I have corresponding phase-destroy methods on the LifeCycled interface, which are invoked in the opposite order).

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From noctariushtc on March 14, 2012 22:17:02

It would be nice to see some help in Guice to build a service framework but it isn't needed, since startup order of services could be possibly different from injection dependecy order.

In my framework I made it something like Bob meantioned. I used an the InjectionListenr / ProvisionListener to collect services implementing the frameworks service interface and after injection finished the frameworks ServiceManager collects and orders the services startup dependencies, searches for postConstruct() handlers and finally calls the startup() method of every service.
When the framework is shutting down first all services preDestroy() method is called and finally the destroy() method.
Right after that point the ServiceManager and the Injector are destroyed.

It was a bit tricky at some small points but that is more a problem of the framework, which can be sticked together from plugins (all have their own AbstractModule) and a plugin descriptor, not a Guice problem.

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From limpbizkit on March 14, 2012 22:17:18

PROPOSAL 102.

Add an extension that uses Guava's Service interface, and that makes it easy to bind services and start them.

Perhaps a basic service registration DSL:
  class MyAppServiceModule extends ServiceModule {
    public void configureServices() {
      bindService(JettyService.class);
      service(JettyService.class).dependsOn(ConnectionPoolService.class);
    }
  }

Plus a mechanism to start and stop services. This could track user-specified service dependencies.

public static void main(String... args) {
  Stopwatch stopwatch = new Stopwatch();
  Injector injector = ...
  logger.info("Injector creation took " + stopwatch.elapsed());
  stopwatch.reset();

  ServiceManager serviceManager = injector.getInstance(ServiceManager.class);
  serviceManager.registerServiceFailureHandler(new ServiceFailureHandler() {
    public void serviceFailed(Service service, Throwable failure) {
      logger.log(WARNING, "Service " + service + " failed; shutting down", failure);
      serviceManager.shutdown();
    }
  });
  serviceManager.registerShutdownOnExitHook(); // gracefully shut down on CTRL-C
  serviceManager.startAllAndWait();
  logger.info("Service startup took " + stopwatch.elapsed());
  logger.info("Ready");
}

Ideally ServiceManager has a rich API that lets you do all the natural things you want to do with services. Stuff like starting them up, shutting them down, listening for state changes, printing statistics like startup time, and interrogating the dependency graph. It could even do its own logging (in a verbose mode?) to keep the common case concise.

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From noctariushtc on March 15, 2012 00:43:17

A nice concept but isn't this the first step to make Guice a second Spring? Guice wasn't designed as an application framework, I'm not sure if it would be good to go that way.

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From marchign on March 15, 2012 14:16:48

Using a marker interface or annotations makes no great difference to me.

I think that the reason why people (including me) request this feature is because it provides a simple machinery to forward the "scope begin" / "scope end" events to objects in that scope without requiring any dependency among who starts/stops the scopes and the object living there.

Following this view, I think that it would make sense to generalize the eagerness attribute to each scope: instead of bind(X).to(Y).asEagerSingleton(), one could use something like bind(X).toY().eager().in(Singleton.class). In this way one could perform some initialization phase at (session / request / whatever ) start time.

I think that this extension would also make less arbitrary the choice of which objects Guice should starts and stop. The user could force an object to be initialized (and destroyed) by Guice at scope beginning (end) simply by binding it eagerly in that scope.

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From cowwoc@bbs.darktech.org on March 15, 2012 14:44:18

Regarding annotations vs marker interfaces, why would you need to iterate over the methods? Wouldn't you only scan the class itself for an annotation (same as a marker interface)?

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From cgruber@google.com on July 16, 2012 11:03:09

Unclear whether this needs to be in core, or can be fully expressed in an extension, but if it is to be, we need to expand the SPI to support it, as I think it would incur a cost on those who didn't need it if it were in core.  For now, I'm putting this into a "New" component in the issues, as we figure out how best to do this.

Status: Acknowledged
Labels: Component-NewExtension

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From antony.stubbs on November 07, 2012 06:40:24

You guys might want to look at GuiceBox's @Stop annotation...

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From davide.cavestro on May 10, 2013 13:21:30

Please note this is blocking even GWT/GIN @PostConstruct annotation implementation.
For GIN there's not 3rd party plugins available providing this kind of features, and GIN guys are waiting for this guice feature in order to introduce some useful features.
GIN issue tracker ref: https://code.google.com/p/google-gin/issues/detail?id=176

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From goktug@google.com on May 10, 2013 16:23:59

Clarification: I said "I don't see this [@PostConstruct] being added without Guice chooses to do so".

We might end up having extensions points some time in the future and then one can write extension similar to that - but that is a different story...

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From mcculls on May 12, 2013 15:06:28

Support for @PostConstruct and @PreDestroy is already available in the lifegycle extension: http://onami.incubator.apache.org/lifecycle/org.apache.onami.lifecycle.standard/index.html There is also a new listener hook implemented in trunk called ProvisionListener: https://code.google.com/p/google-guice/source/browse/core/src/com/google/inject/spi/ProvisionListener.java Which will enable more fine-grained and flexible lifecycle support. I currently use this to re-implement Plexus lifecycle support (involving legacy components with tricky dependency cycles and multiple lifecycle phases) on top of Guice.

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From davide.cavestro on May 12, 2013 23:20:57

so, is lifegycle (and generally speaking guice extensions) directly compatible with GIN?

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From mcculls on May 14, 2013 03:16:51

GIN only uses Guice at compile time, so additional work is required to support extensions - for example, assistedinject and multibinder have both been adapted in GIN (but the API/design is based on the original extension). See the various submodules under https://code.google.com/p/google-gin/source/browse/#svn%2Ftrunk%2Fsrc%2Fcom%2Fgoogle%2Fgwt%2Finject%2Fclient So while the API and code to support lifecycles is available, it will need to be adapted for GIN. Whether this is done by porting and re-implementing the underlying TypeListener/ProvisionListener API on top of GIN's GWT runtime, or by looking at lifegycle's higher-level design and porting that, is a question for the GIN folks.

(PS. the original home for lifegycle was http://99soft.github.io/lifegycle/ before it moved to Apache/Onami)

@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From cowwoc@bbs.darktech.org on December 29, 2013 11:49:16

Bob,

In comment #93 you said "Maybe I don't want the object to be closed." When I asked you for a concrete use-case you responded with some general statement about avoiding unexpected behavior.

  1. Do you have a concrete use-case where you wouldn't want to close() at the end of a scope? You asked me for a concrete use-case where you would want to do so, and I have provided one.
  2. In my view, we're not doing anything unexpected... certainly no more than closing resources at the end of a try-with-resources block. This behavior should be baked into the specification of what it means to be a Scope. Just to clarify: I am implying that request-scoped resources get disposed at the end of the request, but singleton-scoped resources do not. Meaning, we do not close() inherited bindings.
@gissuebot

This comment has been minimized.

Copy link
Author

commented Jul 7, 2014

From b.k.oxley on January 04, 2014 22:13:28

This would be great & simple functionality to fold into Guice.  Lifegycle uses a simple type listener & module to implement, so the is optional, a good candidate for guice extensions.

Simply supporting "@PostConstruct" and "@PreDestroy" is 90+% of what I need in some of my projects.  Presently we depend on Spring; I would love to migrate to Guice for these.

This was referenced Jul 7, 2014

@gembin

This comment has been minimized.

Copy link

commented Jun 5, 2015

+1, any plan to support this feature?
It's a very common functionality.

@Ghoughpteighbteau

This comment has been minimized.

Copy link

commented Jun 26, 2015

At the least, it would be great to have an official "We don't have this implemeted yet, but if you want to shutdown cleanly, do this."

@sameb

This comment has been minimized.

Copy link
Contributor

commented Jun 26, 2015

We have no plans of implementing lifecycle support.

You can use Guava's Service + ServiceManager(https://github.com/google/guava/wiki/ServiceExplained) to have services with a lifecycle. The simplest way is to bind a multiset of Set<Service> and construct a ServiceManager with that set.

For things where you want to do something after creation/injection (otherwise known as provisioning), you can use a ProvisionListener (http://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/spi/ProvisionListener.html, bound with Binder.bindListener).

Guice has no concept of "finishing" a scope or object, so anything where you want to do something on-destroy must be done through a separate framework that's better suited to lifecycle management.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.