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

Reply via email to