How do you create a non-Thread-based Guice custom Scope?

565 views
Skip to first unread message

Russ

unread,
Mar 24, 2010, 2:47:45 PM3/24/10
to google-guice

It seems that all Guice's out-of-the-box Scope implementations are
inherently Thread-based (or ignore Threads entirely):

Scopes.SINGLETON and Scopes.NO_SCOPE ignore Threads and are the edge
cases: global scope and no scope.

ServletScopes.REQUEST and ServletScopes.SESSION ultimately depend on
retrieving scoped objects from a ThreadLocal<Context>. The retrieved
Context holds a reference to the HttpServletRequest that holds a
reference to the scoped objects stored as named attributes (where name
is derived from com.google.inject.Key).

Class SimpleScope from the custom scope Guice wiki also provides a per-
Thread implementation using a ThreadLocal<Map<Key<?>, Object>> member
variable.

With that preamble, my question is this: how does one go about
creating a non-Thread-based Scope? It seems that something that I can
use to look up a Map<Key<?>, Object> is missing, as the only things
passed in to Scope.scope() are a Key<T> and a Provider<T>.

Thanks in advance for your time.

Fred Faber

unread,
Mar 24, 2010, 3:08:48 PM3/24/10
to google...@googlegroups.com
You can do this if your lookup key is accessible to the thread performing the lookup, at lookup time.

For instance, you can have a static variable somewhere:

YourScope implements Scope

  Map<String, Map<Key<?>, Object>> allScopeMaps = ...


  @Override
  scope(...) {
     String currentScope = MyScopeManager.getCurrentScope();
      Map<Key<?>, Object> scopedObjects = allScopeMaps.get(currentScope);
     ....
   }
}

And your "scope manager" can then do explicitly what a thread local scope does implicitly, which is effectively to namespace the set of currently scoped objects.

-Fred
      


--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.


Russ Milliken

unread,
Mar 24, 2010, 4:11:01 PM3/24/10
to google...@googlegroups.com
I don't understand your reference to a Thread.  I want a Scope that is not Thread-based.  MyScopeManager in your example should not determine which objects are "in scope" based on what Thread is in context.  Given that, how should my Scope implementation or MyScopeManager determine in which scope the given Key resides?

Thanks,

-Russ

Fred Faber

unread,
Mar 24, 2010, 5:00:39 PM3/24/10
to google...@googlegroups.com

the scope manager could pick a random number. or it could use the time of day.  or it can reference a static value set by another thread.  I don't mean to be facetious but it is really that arbitrary.

do you have a use case in mind? I would be happy to fill in more details if need be.

On Mar 24, 2010 4:11 PM, "Russ Milliken" <russ.m...@gmail.com> wrote:

I don't understand your reference to a Thread.  I want a Scope that is not Thread-based.  MyScopeManager in your example should not determine which objects are "in scope" based on what Thread is in context.  Given that, how should my Scope implementation or MyScopeManager determine in which scope the given Key resides?

Thanks,

-Russ

On Wed, Mar 24, 2010 at 3:08 PM, Fred Faber <ffa...@gmail.com> wrote:

>
> You can do this if your lookup key is accessible to the thread performing the lookup, at lookup ...


>
>       
>
> On Wed, Mar 24, 2010 at 2:47 PM, Russ <russ.m...@gmail.com> wrote:
>>
>>
>>

>> ...

--

> You received this message because you are subscribed to the Google Groups "google-guice" group.

> ...


--

You received this message because you are subscribed to the Google Groups "google-guice" group.

To p...

Max Bowsher

unread,
Mar 24, 2010, 5:02:09 PM3/24/10
to google...@googlegroups.com


On what do you wish to base your Scope, if not on Thread identity?


Max.

Russ Milliken

unread,
Mar 24, 2010, 6:08:25 PM3/24/10
to google...@googlegroups.com
For the sake of argument let's say that I want my scope to be tied to objects created in a certain method buried deep down in my infrastructure.  This method may be re-entered in the same Thread, and I want another "scope" to be started upon re-entrance.  Think of a Swing app: things happen on and off the Event Dispatch Thread, and I don't want Guice and my Scope deciding whether or not to reuse an object based on the injection request occurring on EDT or not.

I understand that the Servlet model is predicated on things being Thread-contained but that simply isn't the case for a Swing app where there's lots of Thread hopping going on.

-Russ

--
You received this message because you are subscribed to the Google Groups "google-guice" group.

Russ Milliken

unread,
Mar 24, 2010, 6:16:55 PM3/24/10
to google...@googlegroups.com
You mean, the ScopeManager can "put something in" upon scope entry and remove it upon scope exit?  That's cool, but the question is, what is passed to Scope.scope() to allow me to look up the Map of scoped objects?  The only things passed to Scope.scope() are Key<T> and Provider<T>.  Neither of these things are available to me at "scope entry" time.

-Russ

Sam Berlin

unread,
Mar 24, 2010, 6:18:41 PM3/24/10
to google...@googlegroups.com
For Swing apps, I could imagine writing a scope that's based on the current visible Dialog/Frame/Window (or even the currently focused widget).  For those cases, you would want to have a Map where the keys are the Frame (or Window, Dialog, etc..).  I don't have the API committed to memory, but I'm fairly certain there's a way to get the currently focused Frame.  Doing something like scopeData.get(Frame.currentFocusedFrame()).get(key) would return the data there.  You would need to also hook into Window system to catch when frames are disposed so that you can exit the scope, too.

Sam

Fred Faber

unread,
Mar 24, 2010, 6:30:46 PM3/24/10
to google...@googlegroups.com
Yes, as Sam illustrates in his post, you'll need to rely on a global handle somewhere, such as "Frame.currentFocusedFrame()".  Essentially it'd just a global lookup by the thread which is in the scope() method. 

-Fred

Max Bowsher

unread,
Mar 24, 2010, 7:42:26 PM3/24/10
to google...@googlegroups.com
Russ Milliken wrote:
> For the sake of argument let's say that I want my scope to be tied to
> objects created in a certain method buried deep down in my
> infrastructure. This method may be re-entered in the same Thread, and I
> want another "scope" to be started upon re-entrance. Think of a Swing
> app: things happen on and off the Event Dispatch Thread, and I don't
> want Guice and my Scope deciding whether or not to reuse an object based
> on the injection request occurring on EDT or not.
>
> I understand that the Servlet model is predicated on things being
> Thread-contained but that simply isn't the case for a Swing app where
> there's lots of Thread hopping going on.

Fundamentally, the Java programming language only gives you two ways of
accessing state when buried deep in infrastruture:

1) Static fields
2) ThreadLocals

So those are the only options you have for implementing Guice scopes.


If you're using a windowing toolkit and want a scope specific to it, you
could use a static or threadlocal to get a reference to a relevant
windowing object and thus ask the windowing object about its current
state .... but you still need a static or threadlocal in there to get a
reference to the windowing toolkit.

Max.

signature.asc

Bob Lee

unread,
Mar 24, 2010, 7:52:58 PM3/24/10
to google...@googlegroups.com
You can also use a child injector instead of a scope. For example, you could have an injector per window.

Bob
Reply all
Reply to author
Forward
0 new messages