Sam, Thank you! This is much the same use case and validates much of the direction I was going.
I like your idea of returning a bean as it does take care of the requirement that related items be obtained atomically. I can see how the mutable provider answers the use case, but I'm still wondering if it's possible to scope the providers and obtain additional benefits. For example, I think it would prevent the get() operation of the provider before the settings are available (before the scope is entered), and it would make it impossible to inject FooSettings directly. In an unscoped object you would be allowed to inject only a Provider<FooSettings>, whereas you could inject FooSettings directly objects that are declared to be in the same scope. Leigh. On Apr 15, 4:58 pm, Sam Berlin <[email protected]> wrote: > We've run into a similar situation for "settings". These are settings that > aren't required at construction time, are a bit expensive to initialize, can > change through the course of the program, and allow other parts of the > program programmatic access to changing them. We've gone through a few ways > of solving it, but I think have stumbled upon a good one. > > The first approach we took was to have a FooSettings interface that had a > bunch of getXXX methods and could be implemented in a variety of ways. The > components that required the settings' values would have a FooSettings > injected and the place that had the actual setting implementations would > create a BarBackedFooSettingsImpl class. This worked, but it was a PITA to > deal with the different implementations of FooSettings, and became unwieldy > if the settings were unrelated and required in lots of different places. > > The next attempt was to inject a "Setting" class directly, which was more in > the right approach, but exposed too much information to the users. The > users really just want to "get", but Setting exposed a set, revertToDefault, > and a lot of other unrelated methods. > > The solution we're using now is with a new MutableProvider interface. > MutableProvider extends Provider and add a set(T) method. Things that need > access to the getter just inject the Provider of the setting type (annotated > with some binding annotation that's unique for the setting). Things that > need access to both the setter and getter can inject the MutableProvider of > the type (also annotated with a unique binding annotation). The Provider > version of the setting is bound by using toProvider, and the MutableProvider > is bound to the same instance or key. > > While this doesn't solve your question about scopes, it does let what's > returned by a Provider change asynchronously. > > Sam > > On Wed, Apr 15, 2009 at 7:00 PM, Leigh Klotz <[email protected]> wrote: > > > In order to interface with an existing multi-process system, I need to > > be able to respond to external events which signal the readiness of > > new values for certain data items. > > > I could write a caching Provider for each item, and inject the > > Provider's implementation into the event handler where it could be > > flush the cache on receipt of an event. > > > However, it occurred me to model this process as a scope, much like > > @Singleton, but which occasionally gets flushed and re-populated. > > > Has anyone encountered a need for a long-term scope which is global > > like Singleton, but not stack- or thread-based? Is there a better way > > to model externally-influenced Provider object cache flushes? > > > Below are some details. > > > Why it's not @Singleton or ThreadLocal CustomScope: > > I can't use a Singleton scope the lifetime of the provided value is > > not as long as the lifetime of the Injector. I can't use a > > ThreadLocal scope (as in the Guice documentation CustomScopes > > example), because the same objects are shared in all threads, and the > > flow of control in the consuming threads has no bearing on the > > lifetime of the objects. > > > Concerns: > > This may sound like a recipe for a dirty read disaster, but I believe > > that I can use a new, asynchronous, long-term scope to implement the > > behavior I need to provide, as long as I accept one of the following: > > > 1. All objects which inject from this scope must be in the scope, or > > 2. If there is more than one binding in the scope and an object > > outside the scope injects two Providers for two different objects > > within the scope, the two provided objects must not have inter-object > > consistency constraints, because two provider.get() calls may straddle > > a scope generation boundary. > > > Fortunately, the application I'm converting to use Guice already > > satisfies #2 and I believe I can make use of #1 to make the > > relationships more explicit. > > > Implementation: > > I've put together an implementation of a LongTermScope using the > > CustomScopes guide and Tim Peirel's > > org.directwebremoting.guice.AbstractContextScope for inspiration, in > > order to avoid the synchronized() in @Singleton. The scope has an > > three operations: enter, exit, and flip, an atomic exit-enter. It > > supports the CustomScope seed method as well, internally using a > > constant-valued Future subclass I felt compelled to call Destiny. > > > Of course, this rolling-my-own-scope meets ConcurrentHashMap makes me > > nervous, so I'm interested in hearing of anybody has better ideas > > about how to model the event response, or has done something like this > > before. > > > If there's need, I can provide the code for what I've done, but I > > don't have any faith in it yet. > > > Thank you, > > > Leigh. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "google-guice" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/google-guice?hl=en -~----------~----~----~----~------~----~------~--~---
