You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Joerg Heinicke <jo...@gmx.de> on 2005/05/10 18:56:01 UTC
[IMP] synchronization on session object in Cocoon
Hello,
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]:
public Session getSession(boolean create) {
javax.servlet.http.HttpSession serverSession = this.req.getSession(create);
if ( null != serverSession) {
if ( null != this.session ) {
if ( this.session.wrappedSession != serverSession ) {
// update wrapper
this.session.wrappedSession = serverSession;
}
} else {
// new wrapper
this.session = new HttpSession( serverSession );
}
} else {
// invalidate
this.session = null;
}
return this.session;
}
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. What we
probably need is a Map mapping the server sessions to the wrapper objects.
WDYT?
Joerg
[1] http://svn.apache.org/viewcvs.cgi/cocoon/tags/RELEASE_2_1_7/src/java/org/
apache/cocoon/environment/http/HttpRequest.java?rev=158761&view=markup
Re: [IMP] synchronization on session object in Cocoon
Posted by Joerg Heinicke <jo...@gmx.de>.
Sylvain Wallez <sylvain <at> apache.org> writes:
> 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.
http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double_p.html
Joerg
Re: [IMP] synchronization on session object in Cocoon
Posted by Sylvain Wallez <sy...@apache.org>.
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
Re: [IMP] synchronization on session object in Cocoon
Posted by Joerg Heinicke <jo...@gmx.de>.
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;
}
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.
WDYT?
Joerg
[1] http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/
HttpSessionAttributeListener.html
#attributeReplaced(javax.servlet.http.HttpSessionBindingEvent)
[2] http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/http/
HttpSessionBindingListener.html
Re: [IMP] synchronization on session object in Cocoon
Posted by Sylvain Wallez <sy...@apache.org>.
Joerg Heinicke wrote:
>Hello,
>
>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]:
>
>public Session getSession(boolean create) {
> javax.servlet.http.HttpSession serverSession = this.req.getSession(create);
> if ( null != serverSession) {
> if ( null != this.session ) {
> if ( this.session.wrappedSession != serverSession ) {
> // update wrapper
> this.session.wrappedSession = serverSession;
> }
> } else {
> // new wrapper
> this.session = new HttpSession( serverSession );
> }
> } else {
> // invalidate
> this.session = null;
> }
> return this.session;
>}
>
>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.
Sylvain
--
Sylvain Wallez Anyware Technologies
http://apache.org/~sylvain http://anyware-tech.com
Apache Software Foundation Member Research & Technology Director