Resetting Singletons

2,720 views
Skip to first unread message

christophe...@gmail.com

unread,
May 24, 2009, 10:47:55 AM5/24/09
to google-guice
Heya,

I really love Guice, it has made me a much better coder. It forces you
to think about design. Something I've not yet found a good solution
for is when I have to reset singletons. I'm not sure that is the way I
want to solve the issue though.

I have a bunch of singletons that should be singletons until the user
chose to reload parts of the application. Then I have to reset a few
objects to get a clean state. Some of the thoughts I have:

Maybe all the classes that should be resettable should rather have a
reset method?
Injecting factories that can give you new instances?

I'm using the second solution right now. The problem is when two
classes depends the same "resettable singleton", as I can't inject the
object directly from Guice as a Singleton.

Should I build my own app level "resettable singleton" functionality
or is there is there a Guice way?

Thanks!

Uwe Schäfer

unread,
May 24, 2009, 10:45:55 AM5/24/09
to google...@googlegroups.com
christophe...@gmail.com schrieb:

> I have a bunch of singletons that should be singletons until the user
> chose to reload parts of the application. Then I have to reset a few
> objects to get a clean state.

I´d use providers that register at a central (maybe singleton) manager,
that propagates the 'reset' action to them.

cu uwe

christophe...@gmail.com

unread,
May 24, 2009, 11:22:15 AM5/24/09
to google-guice
Thanks for the answer.

If I understood you correctly, that would imply that all resettable
classes have a reset method?

I guess one can't solve it in another way. Not even sure you can touch
the singleton instance reference so that it propagates to another
object that depends on it.

On May 24, 4:45 pm, Uwe Schäfer <u...@thomas-daily.de> wrote:
> christopher.oestl...@gmail.com schrieb:

limpb...@gmail.com

unread,
May 24, 2009, 1:03:13 PM5/24/09
to google-guice
On May 24, 7:47 am, "christopher.oestl...@gmail.com"
<christopher.oestl...@gmail.com> wrote:
> I have a bunch of singletons that should be singletons until the user
> chose to reload parts of the application.

If they need resetting, then they're not singletons! I recommend
writing a new scope, "ReloadableScope", and binding all of the
reloadable objects in that scope.

Anything that depends on a ReloadableScoped object should itself be
either ReloadableScoped or unscoped. If you have true singletons
depending on ReloadableScoped objects, you might run into problems.

Full instructions for implementing custom scopes are here:
http://code.google.com/docreader/#p=google-guice&s=google-guice&t=CustomScopes

christophe...@gmail.com

unread,
May 24, 2009, 1:20:44 PM5/24/09
to google-guice
Thanks for the answer!

I have real Singletons depending on objects that would be scoped as
reloadable. I guess this isn't an issue for Guice to solve then,
rather an application design issue. I'm thinking of injecting some
sort of container that holds the current instance of the object, the
container can be reset. Everywhere where I want to use object A I
would inject the container and do a .get(), something similar like a
provider but with a reset method.

Not sure I can come up with something better.
>  http://code.google.com/docreader/#p=google-guice&s=google-guice&t=Cus...

Leigh Klotz

unread,
Jun 5, 2009, 2:30:58 PM6/5/09
to google-guice
I posted something about this a month or so ago:

http://groups.google.com/group/google-guice/browse_thread/thread/1418dfe59246f819/f7ed43be6b907ade


I wrote a scope doing just this, called LongTermScope, which I can
send you, but after I did it I decided I didn't like it. One issue I
found is that there's no guarantee that two objects you inject in this
scope are from the same generation, even if they are both parameters
to the same injected constructor. Another was that it didn't seem
possible to prevent injection of LongTermScope objects directly into
Singletons (they'd need providers).

I'd previously thought to use two provider bindings instead, and in
fact Sam Berlin recognized the use case (resettable settings) from the
proposed solution and suggested the provider bindings instead.

I've taken Sam's idea and use MutableProvider extends Provider, and
Resettable. These are used to wrap existing settings beans, which
themselves are grouped to guarantee generational consistency.

This seems to be working for me, and I do this
@Inject FooBean
for objects that are short-lived.

@Inject Provider<FooBean>
for objects that might span a generation.

@Inject MutableProvider<FooBean>
for resources that need to write to the bean

@Inject Resettable<FooBean>
for resources that simply need to assert that that the Bean has
changed (flush cache).

I've made two implementations of these MutableProviders: one that is
simply a singleton, and another than adapts to some existing RMI code,
for which I just call the super constructor with the parameters
necessary for the service location.

I've also made some helpful routines for binding in ab abstract class
called MutableProviders. (Unfortunately, Guice subsequently came out
with Providers.of with a different meaning so I may need to change
this name.)

static <T extends Object> TypeLiteral<MutableProvider<T>> of(Class
<T> x);

so you can do this
bind(beanClass).toProvider(beanProviderClass);
bind(MutableProviders.of(beanClass)).to(beanProviderClass);

additionally I found had to use the LazySingleton scope hack to avoid
the providers being activated too early:
bind(beanProviderClass).in(MoreScopes.LAZY_SINGLETON);

There's probably a cooler way to do it, but I just defined a method in
my Module to do this:
private <B extends Object, P extends MutableProvider<B>> void defBean
(Class<P> beanProviderClass, Class<B> beanClass)
which then does the three lines above.

If you need annotations, there's a MultibleProviders.of variant that
does that.

Maybe I'll stick this in pastie if there's sufficient interest. Or
maybe Sam already has something better worked out.

Leigh.

Kevin Bourrillion

unread,
Jun 5, 2009, 5:26:22 PM6/5/09
to google...@googlegroups.com
On Sun, May 24, 2009 at 10:20 AM, christophe...@gmail.com <christophe...@gmail.com> wrote:

Thanks for the answer!

I have real Singletons depending on objects that would be scoped as
reloadable.

Just put them in the reloadable scope too!

This scope is a sub-scope of Singleton and a super-scope of Session and Request, so you can't inject a reloadable-scope object into a Singleton or a session-scope object into a reloadable-scope one.  It's lamentable that Guice still won't explicitly flag that as an error; it was one of the things I most wished we could have made it do from the very beginning.  The scope containment hierarchy must be obeyed.  Of course, Provider-injection can be used for the pesky backward dependencies, but it's better to try to avoid those.

I don't see how you could end up with two objects from different "instances" of a reloadable scope (or "configuration scope") injected into the same target.

I strongly recommend running far away from the ideas of mutable or "resettable" singletons or providers.

Sam Berlin

unread,
Jun 5, 2009, 5:35:29 PM6/5/09
to google...@googlegroups.com
In some cases, a MutableProvider is pretty useful.  Not so much for singletons, but more for provided variables.  Our specific use-case is settings.  Consider a binding "@Named("downloadThrottleSpeed") Provider<Integer>".  The core of the program injects it as a provider & gets the current throttle setting.  The UI injects it as a MutableProvider<Integer> and can set it.  Reuses the infrastructure of providers and nicely solves the ability to inject specific settings that can change over time.

Sam
Reply all
Reply to author
Forward
0 new messages