Re: How to Retrieve Session User?
Re: How to Retrieve Session User?
- Subject: Re: How to Retrieve Session User?
- From: Mike Schrag <email@hidden>
- Date: Thu, 5 Apr 2007 07:52:48 -0400
It is almost what I had in mind, only that I don't want a different
map per thread, I need a single map no mater how many threads.
Why would we want a different map per thread when you use the
editing context as a key ?
When you receive a request (worequest), you have to set the map
every time, no ? (note that it's not worse than adding an entry
for every new eoeditingcontext)
ERXThreadStorage has a ThreadLocal in it. A ThreadLocal contains a
single object, uniqued by the thread it was assigned on. ERX
automatically pushes a dictionary into the ThreadLocal at the start
of the RR, and automatically removes the dictionary at the end of the
RR loop (i.e. 1 op at the start, 1 op at the end). This is really
handy for any number of "thread global" things (hence why it's a map
and not just the one object) -- WOSession, WOContext, current user,
etc. For instance, we have EO's that can trigger notifications.
It's useful to be able to access the WOContext (if it exists) so we
can clone it and get the original context request URI, etc so that
URLs built in the component emails match the URL that the user came
in on.
ERXThreadStorage is actually (by default) an InheritableThreadLocal,
so when you make a new thread, the dictionary is cloned onto the new
thread. Note that the contents are not cloned, just the dictionary.
You must be careful about this, because you don't necessarily own the
editing context of an EO that's in this map, and you should NOT
access ERXExtensions.session() on the new thread (session is
automatically put in the threadstorage for you). This is because the
session may actually be expired, so you can't depend on it being in a
live state in this new thread. Additionally with respect to EO's,
the editing context may be disposed for the object. The only truly
threadsafe way to deal with this is something like:
public static MyRunnable implements Runnable {
private EOGlobalID _userGID;
public MyRunnable(EOGlobalID userGID) {
_userGID = userGID;
}
public void run() {
ERXThreadStorage.removeValueForKey("session"); // not required, but
just so nobody gets any crazy ideas
ERXThreadStorage.removeValueForKey("wocontext"); // not required,
but just so nobody gets any crazy ideas
EOEditingContext ec = ERXEC.newEditingContext();
ec.lock();
try {
EOEnterpriseObject user =
ERXEOGlobalIDUtilities.fetchObjectWithGlobalID(ec, _userGID);
ERXThreadStorage.takeValueForKey(user, "user");
// perform your operation
}
finally {
ec.unlock();
}
}
}
...
public WOActionResults someRRMethod() {
EOEnterpriseObject user = (EOEnterpriseObject)
ERXThreadStorage.valueForKey("user");
EOGlobalID gid = user.editingContext().globalIDForObject(user);
Thread anotherThread = new Thread(new MyRunnable(gid));
anotherThread.start();
return null; // :) four keystrokes saved!
}
NB: in the RR method, I didn't lock, because Wonder locked for me.
In the other thread, depending on the settings you have, it MAY be
doing per-call locking for you, but I generally do a top level lock
anyway just to get a full transaction lock to be safe (if you turn on
lock coalescing, for instance, you definitely want to be careful not
being in an RR thread -- I believe that keys off of having an
wocontext on your thread).
ms
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden