cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sylvain Wallez <sylv...@apache.org>
Subject Re: [IMP] synchronization on session object in Cocoon
Date Wed, 11 May 2005 16:03:46 GMT
Joerg Heinicke wrote:

>Sylvain Wallez <sylvain <at> apache.org> writes:
>
>  
>
>>>I think I have found a more general problem with synchronization in Cocoon. I
>>>tried to solve my problem with synchronization in flow script with an
>>>intermediate object. This object handles the synchronized instantiation of my
>>>component. Unfortunately I found out that "synchronized (session) { ... }"
>>>still did not work - two requests of the same session run into that block at
>>>the same time. I did some remote debugging. First I thought the reason is in
>>>flow script as it also wraps the session, but it unwraps it later. The reason
>>>is in HttpRequest class. Have a look at the code [1]:
>>>      
>>>
>
>  
>
>>>As you can see on every request a new wrapper is instantiated which is really
>>>bad. It is not possible to synchronize on Cocoon session objects.
>>>      
>>>
>>Wow, very good point!
>>
>>    
>>
>>>What we probably need is a Map mapping the server sessions to the wrapper
>>>objects.
>>> 
>>>      
>>>
>>Or more simply we could store the wrapper in the session itself using an 
>>attribute. That way it would be guaranteed to be created only once.
>>    
>>
>
>Yes, that's another possibility I also had in mind. But on the one hand this
>smells a bit (storing a wrapper in the object that the wrapper wraps), on the
>other hand you can not restrict access to it, so it can be manipulated from
>somewhere else. But the Map solution can indeed be very resource consuming and a
>bottle neck.
>
>I have implemented the session attribute solution. Would be nice if you can
>review it:
>
>public Session getSession(boolean create) {
>    // we must assure a 1:1-mapping of server session to cocoon session
>    javax.servlet.http.HttpSession serverSession = this.req.getSession(create);
>    if (serverSession != null) {
>        synchronized (serverSession) {
>            // retrieve existing wrapper
>            this.session =
>(HttpSession)serverSession.getAttribute(HTTP_SESSION);
>            if (this.session == null) {
>                // create wrapper
>                this.session = new HttpSession(serverSession);
>                serverSession.setAttribute(HTTP_SESSION, this.session);
>            }
>        }
>    } else {
>        // invalidate
>        this.session = null;
>    }
>    return this.session;
>}
>  
>

This approach has the problem of entering a synchronized block each time 
getSession is called. Although this may not that be much a problem in 
this particular case because it's unlikely that many parallel requests 
exist for a single request, we may totally avoid it except once. We also 
no more need to keep the wrapper as "this.session" as the servlet 
session stores the wrapper.

public Session getSession(boolean create) {
    javax.servlet.http.HttpSession serverSession = 
this.req.getSession(create);
    if (serverSession != null) {
        Session session = 
(HttpSession)serverSession.getAttribute(HTTP_SESSION);
        if (session = null) {
            return createSessionWrapper(serverSession);
        } else {
            return session;
        }
    } else {
        return null;
    }
}

private Session createSessionWrapper(HttpSession serverSession) {
    synchronized(serverSession) {
        // recheck in the synchronized section
        Session session = 
(HttpSession)serverSession.getAttribute(HTTP_SESSION);
        if (session = null) {
            session = new HttpSession(serverSession);
            serverSession.setAttribute(HTTP_SESSION, session);
        }
        return session;
    }
}

>An "update wrapper" (which was indeed an "update wrapped session") as in the old
>implementation is IMO no longer necessary as only the server session holds the
>wrapper - if it is a new server session we also must provide a new wrapper.
>
>To avoid or at least recognize manipulation of the session attribute it is maybe
>possible to let Cocoon's HttpSession implement HttpSessionAttributeListener and
>to check on attributeReplaced(HttpSessionBindingEvent) [1] whether the wrapper
>was replaced and not just removed on invalidation of the session. But first this
>is no 100%-solution as someone could first remove and later set the attribute
>and second it is again overhead (the event is triggered on every session
>attribute add/remove/replace).
>AFAICS the HTTPSessionBindingListener [2] does not help as there is no type of
>HttpSessionBindingEvent, just the information that the wrapper was removed - and
>this must happen when the session is invalidated.
>  
>

Sorry, what problem are you trying to solve with having the wrapper 
being notified of updates?

Sylvain

-- 
Sylvain Wallez                        Anyware Technologies
http://apache.org/~sylvain            http://anyware-tech.com
Apache Software Foundation Member     Research & Technology Director


Mime
View raw message