On 18/01/18 20:11, Christopher Schultz wrote: > Olaf, > > On 1/18/18 1:28 PM, Olaf Kock wrote: > >> On 18.01.2018 06:37, Christopher Schultz wrote: >>> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 >>> >>> Mark, >>> >>> On 1/17/18 4:31 PM, Mark Thomas wrote: >>>> On 17/01/18 17:05, Christopher Schultz wrote: >>>>> All, >>>>> >>>>> I have a use-case related to caching where I need to make >>>>> sure that an operation only happens one time with respect to >>>>> an object in the session. Basically, I want to build a cache >>>>> and put it into the session, but it needs to be thread-safe >>>>> enough that two threads can't see the object isn't there, >>>>> build such an object, and then put it into the session >>>>> (thereby overwriting each other). > >> ... >>>>> Yeah, I figured that. Otherwise, multi-threading basically >>>>> couldn't happen. I'm surprised the servlet spec doesn't >>>>> formally guarantee this because practically speaking, it's a >>>>> requirement. >> .... >>>> It should always be the same object. Looking at the code, I >>>> don't see any obvious holes. >>>> >>>> For the record, relevant code includes: >>>> o.a.catalina.connector.Request.getSession() >>>> o.a.catalina.session.ManagerBase.createSession(String) >>>> o.a.catalina.session.StandardSession.getSession() >>> Could this be something we could formally guarantee (via >>> documentation)? I'd like to lobby the servlet EG for the same >>> guarantee, but getting it done in Tomcat is more immediately >>> valuable for me :) >> I'm not sure that this can be done in an unambiguous way, >> especially not from the spec side: Assuming that objects might be >> serialized out to disk (for memory reason, unused in 15 minutes but >> not yet expired, cluster distribution etc) this would lead to quite >> a few disambiguities. You say that your object creation should >> happen once per session - is that per session AND machine? If >> creation of that object has side effects, or the object itself has >> state, your scenario might only be safe as long as there's no >> clustering / session replication involved, but can't be assumed >> when it is. > > I would think the language would be something like "session objects > within the JVM shall be == equals to each other when requested from > the container" but I didn't think about the "serializing to [eg] disk" > scenario. If you have a session obtained from the container, then have > a long-running request or websocket handler and the container > meanwhile persists the session elsewhere, some other thread would > almost certainly get an object that is != the session object in the > other thread. > > Hmm. I wonder if that is a problem, now, for Tomcat. > > The container is only "maintaining" a single session object ob behalf > of its worker threads... if an application retains a reference they > can get out of sync. There is no mechanism for the application to tell > the container "hey, I need this session for quite a while into the > future" and so the container might not know it is "in use". > > As for long-running HTTP requests, I believe Tomcat knows whether the > session is "currently" in use be a long-running request.
org.apache.catalina.session.StandardSession.ACTIVITY_CHECK > But I'm not > sure about WebSocket... that may depend upon exactly how the > websocket-based service actually uses the session and/or obtains it. WebSocket is a another issue. It needs special handling as WebSocket requests do not maintain the HTTP session. That was a deliberate decision of the WebSocket EG. > For me, it doesn't matter: I have no session-persistence (except > across restarts), I have no clustering, and I have no websocket usage. > So at this point, this is an academic exercise for me. > >> I'd say your safest bet is to validate the current >> implementation's behavior - e.g. your exact version of tomcat - and >> validate that it doesn't change in future versions. Based on Mark's >> comments it doesn't look like this is an area where tomcat's >> implementation would change soon. I'd just not expect it to be >> over-specified in the servlet spec. > > Given all of the possible complications, here, I think you are > probably correct. It does present a problem for anyone who wants to do > things like ensure thread-safety between invocations of server-side > code using a shared session. > > It seems I'm not the only one curious about this: > > https://stackoverflow.com/questions/9802165/is-synchronization-within-an > -httpsession-feasible > > http://yet-another-dev.blogspot.com/2009/08/synchronizing-httpsession.ht > ml > >> There's another argument that the servlet level might be the wrong >> level for creation of expensive objects, and that it's better >> delegated to the business layer. I can't judge that in your case, >> but quite often I've seen the servlet layer overly used for >> business problems. I don't like this a lot - your problem might be >> trivial to solve one or two layers down. > > Speaking of "expensive" objects, we do have a "user" object in the > session. If the user isn't there, we throw all kinds of exceptions and > don't let "users" actually do anything except go to their login pages. > > So I expect that I can (a) always rely on a "user" attribute being in > the session and (b) I can use that as my monitor. I'd check how it is wrapped before you do that. From memory, I'm not sure the same wrapper will always be used. Mark > As for where the "servlet level" or "business level" is the right > place to do these things... the lines are blurred when using e.g. a > web framework (e.g. Spring, Struts, etc.) since you are using objects > provided by the "servlet layer" (e.g. HttpSession) though you may be > using them through a particular interface -- like java.util.Map > instead of HttpSession. > > In these cases, there *must* be a wrapper object and you may or may > not be using the same one across threads. So it seems like the object > stored *in* the session will pretty much always be a safer monitor > than pretty much anything else you could use. > > The only reason this will work for me (100% bulletproof) is because > the "user" object is guaranteed to be present already. If I needed to > create a new object in the session to monitor, I'd need to either use > a HttpSessionListener to insert a "session monitor" into every session > -- not a bad idea -- or use a complicated series of synchronized > blocks using other monitors to bootstrap things to be absolutely sure > I didn't create (and use) two separate monitor objects in two > different threads. > > In this specific use-case I mentioned initially, a page is showing a > handful of <img> elements each of which make a request back to the > server for some dynamic data. All of that data benefits from a > session-backed cache and, because all of the requests come at the same > time from the client, there is great opportunity for race conditions. > > Thanks, > -chris > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org > For additional commands, e-mail: users-h...@tomcat.apache.org > --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org