You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Gokul Singh <go...@wipro.com> on 2001/01/11 14:20:50 UTC

NullPointerException from HttpSessionFacade.invalidate()

Hi,

I am trying to build a login servlet and get a NullPointerException from HttpSessionFacade class in Tomcat 3.2.1.
The code of the simple version of the servlet which reproduces the
problem is attached at the end of this mail along with the stack trace of the Exception thrown.
This piece of code works fine on tomcat 3.1.1 but fails on tomcat 3.2.1

To reproduce the error,
1. start tomcat 3.2.1 afresh.
2. Login from a browser.The password field is not required as for now.
3. Open another browser (not a new instance of the same browser) on the same
machine or another machine.
4. Login with the same username.

the servlet does the following
1.it invalidates any existing session on this request.
2.it checks the context to find if the present user has any associated
session and if it is there tries to invalidate it. (This is where I get the
exception, given below).
3. creates a new session.
4. puts the new session into the context with the user id.

In tomcat 3.2 is the session object which I get ( actually HttpSessionFacade) valid only for the request or can span multiple Requests?
Any help would be greatly appreciated.

I am not on this mailing list. Please send a CC to me at gokul.singh@wipro.com when replying to this mail

Regds,
Gokul

========= 8<==== SERVLET CODE ========= 8< =======

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class TestSessionBehaviour
extends HttpServlet
{
 private static String STR="LOGIN.SESSION.USER.";
 public void doGet(HttpServletRequest req, HttpServletResponse res)
 throws IOException, ServletException
 {
  res.setContentType("text/html");
  PrintWriter out = res.getWriter();
  sendLoginPage(out);
  out.close();
 }

 public void doPost(HttpServletRequest req, HttpServletResponse res)
 throws IOException
 {
  String name = req.getParameter("id");
  HttpSession objSession = req.getSession(false);
  // if the present request has a session invalidate it.
  if(objSession != null)
   objSession.invalidate();
  // if this user has a valid session, invalidate it.
  objSession = (HttpSession)getServletContext().getAttribute(STR+name);
  if (objSession != null)
  {
   System.out.println("The session from context retrieved");
   try
   {
    objSession.invalidate();
   }catch(IllegalStateException ex)
   {   }
  }
  // create new session
  objSession = req.getSession(true);
  // store in the context the username and session.
  getServletContext().setAttribute(STR+name,objSession);

  // send reciept html
  res.setContentType("text/html");
  PrintWriter out = res.getWriter();
  sendReceipt(out);
  out.close();
 }


 private void sendReceipt(PrintWriter out)
 {
  out.println("<html><title>Receipt</title><body>The login is
recorded</body></html>");
 }


 private void sendLoginPage(PrintWriter out)
 {
  out.println("<html><title>Test Login</title><body>Please login <br><form
method=post> <table><tr>");
  out.println("<td>Name </td><td><input type=text name=id> </td></tr>");
  out.println("<tr><td>Password</td><td><input type=text
name=pass></td></tr>");
  out.println("<tr><td><input type=reset value=reset></td><td><input
type=submit value=login></td></table>");
  out.println("</form></body></html>");
 }

}

========= 8<===== EXCEPTION THROWN==== 8< =====

Internal Servlet Error:
java.lang.NullPointerException
 at
org.apache.tomcat.facade.HttpSessionFacade.invalidate(HttpSessionFacade.java
:136)
 at TestSessionBehaviour.doPost(TestSessionBehaviour.java:33)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
 at org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:404)
 at org.apache.tomcat.core.Handler.service(Handler.java:286)
 at org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372)
 at
org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:79
7)
 at org.apache.tomcat.core.ContextManager.service(ContextManager.java:743)
 at
org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpC
onnectionHandler.java:210)
 at
org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416)
 at
org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:498)
 at java.lang.Thread.run(Thread.java:484)
========= 8<============= 8< =============


-------------------------------------------------------------------
"The proverb warns that, 'You should not bite the hand that feeds
 you.'  But maybe you should, if it prevents you from feeding yourself."
--Thomas Szasz
-------------------------------------------------------------------

Re: Session passivation (was: NullPointerException fromHttpSessionFacade.invalidate())

Posted by Kief Morris <ki...@bitbull.com>.
I typed the following on 03:10 PM 1/15/2001 -0500
>If Manager.releaseSession() method is implemented (I don't really like that 
>method name though), then StandardSession.expire() and invalidate() should
>call it, and maybe some other places. 

Doh, actually the locking would probably be implemented in the StandardSession
class itself, so there wouldn't be any need to call the Manager.releaseSession().

Kief


Re: Session passivation (was: NullPointerException fromHttpSessionFacade.invalidate())

Posted by Kief Morris <ki...@bitbull.com>.
Craig R. McClanahan typed the following on 11:42 AM 1/15/2001 -0800

>> - If it is OK, should the container send activation/passivation events when a
>>   session is being serialized (or whatever) for replication purposes? 
>
>The following comment is in the Javadocs at the top of
>javax.servlet.http.HttpSessionActivationListener (the interface that defines 
>the
>passivate and activate listener methods):
>
>    A container that migrates sessions between VMs or
>    persists sessions is required to notify all attributes
>    bound to sessions implementing HttpSessionActivationListener.

OK, so it's clear that the activation events are appropriate only when
the session is actually being removed from a JVM. What I'm trying
to understand is whether a web app developer can ensure that they
get the chance to muck with an object used as a session attribute
before and after it is copied to a Store for backup. The spec says
the serialization events is not necessarily called by the container, so 
it seems the answer to this question is: no.

>> This also raises a Catalina issue I forgot to mention in the message with my
>> PersistentManager patches. Currently there isn't any way (that I could see)
>> to tell when a request has finished handling a session. It's possible that my
>> persistence code could swap a session out while it's being used in a request.
>>
>
>No, there isn't :-(.  We need a registration mechanism a request can call 
>that says "I
>am currently using this session" and "I am done using this session."

Ok, but the request doesn't have any way to know when this kind of
thing happens, so it can be done by the session itself.

>> +         if (manager != null && request.getSession(false) != null)
>> +           manager.releaseSession(request.getSession());
>>     }
>
>There is the possibility of referencing more than one session in the same 
>request, in
>at least a couple of circumstances:
>
>* The originally requested session is no longer valid,
>  and a new one is created.
>
>* The currently valid session is invalidated, and a
>  new one is created.
>
>so any registration/locking mechanism needs to deal with this correctly.

If Manager.releaseSession() method is implemented (I don't really like that 
method name though), then StandardSession.expire() and invalidate() should
call it, and maybe some other places. 

I'm not sure about the originally requested session being invalid: the findSession()
method of the Manager should know about this when it hands it out - *should* it
return an invalid session? Would it be wrong for findSession() to check whether
the session is valid and return null or a new session if so? 

>>
>> Kief
>>
>
>Craig
>

Kief


Re: one session for many web sites

Posted by "Craig R. McClanahan" <cr...@apache.org>.

On Mon, 14 May 2001, Mihai Popoaei wrote:

> 
> Hello,
> 
> How can I have the same session for many web sites?
> 
> By default, for the first request tomcat creates a implicit session and
> sends a cookie with domain=servername. What I wanna do is setting this
> cookie for domain=partian domain name (like .kiki.ro) (that means this
> cookie will come back for all the hosts ending with .kiki.ro and I'll have
> the same session for all the sites :)). I think I have to say that I use
> the same application context for all this sites...
> 
> Another problem is using the same session between applications... I know
> it is not conform the sun specifications (... HttpSession objects must be 
> scoped at the application / servlet context level. The underlying
> mechanism, such as the cookie used to establish the session, can be shared
> between contexts, but the object exposed, and more importantly the
> attributes in that object, must not be shared between contexts. ...),
> but there must be a way to do that...
> 

You are perfectly free to "roll your own" session implementation that
meets your needs (cross-host and cross-webapp).  However, the standard
APis don't support these uses, so this will definitely be an application
specific (and probably Tomcat-specific) approach.

When you try this, you'll discover that having a cookie recognized
correctly is the least of your problems.  You'll also need to ensure that
all of the classes are loaded from a shared class loader -- classes that
are loaded from one web-app's /WEB-INF/classes or /WEB-INF/lib directory
are not visible to any other web-app.

> 
> thx,
>  --
> :], Mihai P.
> 
Craig



Re: one session for many web sites

Posted by Mihai Popoaei <xb...@is.necomm.ro>.
On Mon, 14 May 2001 cmanolache@yahoo.com wrote:

> Salut Mihai,
	Salut.
> 
> > How can I have the same session for many web sites?
> > 
> > By default, for the first request tomcat creates a implicit session and
> > sends a cookie with domain=servername. What I wanna do is setting this
> > cookie for domain=partian domain name (like .kiki.ro) (that means this
> > cookie will come back for all the hosts ending with .kiki.ro and I'll have
> > the same session for all the sites :)). I think I have to say that I use
> > the same application context for all this sites...
> > 
> > Another problem is using the same session between applications... I know
> > it is not conform the sun specifications (... HttpSession objects must be 
> > scoped at the application / servlet context level. The underlying
> > mechanism, such as the cookie used to establish the session, can be shared
> > between contexts, but the object exposed, and more importantly the
> > attributes in that object, must not be shared between contexts. ...),
> > but there must be a way to do that...
> 
> 
> As long as you know this is not standard :-), you will have to make some
> changes to the session interceptor or create a new one.

"Cross-webapps" sessions are not standard, but for "cross-host" sessions I
didn't find any specifications...

> In 3.3, the code is in modules.session.SessionId, you should probably 
> create a new module, add an option and code that supports what you
> need, and maybe publish the changes for others :-)

I taked a look into the sources and I didn't find any code that sets the
domain for JSESSIONID cookie... I don't know exactly what's going on, but 
I imagine that mod_jk or apache sets this (the domain) if it is not 
specified... Am I right?

 Thx again...

> I don't think this can be commited in jakarta-tomcat, as it is not
> standard and it's not a required feature, but it would be nice to have it
> somewhere.
> 
> 
> Costin
> 
> > 
> > 
> > thx,
> >  --
> > :], Mihai P.
> > 
> > xblue@
> >  necomm.ro
> >  fenrir.infoiasi.ro
> > 
> > icq:77484853
> > 
> > =====-----=====
> > 
> 

-- 
:], Mihai P.

xblue@
 necomm.ro
 fenrir.infoiasi.ro

icq:77484853

=====-----=====


Re: one session for many web sites

Posted by cm...@yahoo.com.
Salut Mihai,

> How can I have the same session for many web sites?
> 
> By default, for the first request tomcat creates a implicit session and
> sends a cookie with domain=servername. What I wanna do is setting this
> cookie for domain=partian domain name (like .kiki.ro) (that means this
> cookie will come back for all the hosts ending with .kiki.ro and I'll have
> the same session for all the sites :)). I think I have to say that I use
> the same application context for all this sites...
> 
> Another problem is using the same session between applications... I know
> it is not conform the sun specifications (... HttpSession objects must be 
> scoped at the application / servlet context level. The underlying
> mechanism, such as the cookie used to establish the session, can be shared
> between contexts, but the object exposed, and more importantly the
> attributes in that object, must not be shared between contexts. ...),
> but there must be a way to do that...


As long as you know this is not standard :-), you will have to make some
changes to the session interceptor or create a new one.

In 3.3, the code is in modules.session.SessionId, you should probably 
create a new module, add an option and code that supports what you
need, and maybe publish the changes for others :-)

I don't think this can be commited in jakarta-tomcat, as it is not
standard and it's not a required feature, but it would be nice to have it
somewhere.


Costin

> 
> 
> thx,
>  --
> :], Mihai P.
> 
> xblue@
>  necomm.ro
>  fenrir.infoiasi.ro
> 
> icq:77484853
> 
> =====-----=====
> 


one session for many web sites

Posted by Mihai Popoaei <xb...@is.necomm.ro>.
Hello,

How can I have the same session for many web sites?

By default, for the first request tomcat creates a implicit session and
sends a cookie with domain=servername. What I wanna do is setting this
cookie for domain=partian domain name (like .kiki.ro) (that means this
cookie will come back for all the hosts ending with .kiki.ro and I'll have
the same session for all the sites :)). I think I have to say that I use
the same application context for all this sites...

Another problem is using the same session between applications... I know
it is not conform the sun specifications (... HttpSession objects must be 
scoped at the application / servlet context level. The underlying
mechanism, such as the cookie used to establish the session, can be shared
between contexts, but the object exposed, and more importantly the
attributes in that object, must not be shared between contexts. ...),
but there must be a way to do that...


thx,
 --
:], Mihai P.

xblue@
 necomm.ro
 fenrir.infoiasi.ro

icq:77484853

=====-----=====


Re: Session passivation (was: NullPointerException fromHttpSessionFacade.invalidate())

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
Kief Morris wrote:

> Craig R. McClanahan typed the following on 03:44 PM 1/14/2001 -0800
> >"Christopher K. St. John" wrote:
> >> >
> >> > If your server implements session swapping or distribution (as we are
> >currently
> >> > developing in the 4.1 repository), it is pretty much guaranteed that
> >different
> >> > session object instances may be used during the lifetime of the same
> >session.
> >> >
> >>
> >>  But don't you get session lifecycle events if that happens?
> >
> >Yes ... sessionWillPassivate() before the old session is removed, and
> >sessionDidActivate() after the new one has been installed.
>
> I hadn't thought about the issue of web apps keeping references to a session,
> this underlines the concern I mentioned earlier about passivation events and
> backing up sessions. If web app code depends on these events to tell it when
> a session is being removed from memory, then they shouldn't be fired when
> a session is just being backed up to a Store. But these may be needed for
> pre/post passivation/activation cleanup tasks.
>

IMHO the answer is yes ... passivation to the Store means that the container is
releasing all it's references to the session instance currently in use, and any future
reference to this session will cause it to be reactivated (possibly in the same JVM,
possibly in a different one), but with a new object instance.  The activation event
will allow any interested listeners to update their references.

The passivation/activation lifecycle here is very similar to what happens with EJBs,
for the same reasons.

>
> I may send a message to the api feedback address to get clarification on the
> spec. Namely:
>
> - Is it OK for the container to keep multiple copies of a session in a distributed
>   web application? The spec doesn't say no, although it does say that only one
>   instance of the app should be handling requests for a session at a time, which
>   implies you could have multiple copies if you have a locking mechanism and
>   maintain data consistency.
>

Some containers do this (I think iPlanet does?) to support hot failover.  I don't see
any spec prohibition to this, as long as you obey the part about request processing
all being within one JVM at any one point in time.

>
> - If it is OK, should the container send activation/passivation events when a
>   session is being serialized (or whatever) for replication purposes? Whatever
>   the answer is, it would be nice if the spec clarified it explicitly so webapp
>   developers can depend on it being consistent on different containers.
>

The following comment is in the Javadocs at the top of
javax.servlet.http.HttpSessionActivationListener (the interface that defines the
passivate and activate listener methods):

    A container that migrates sessions between VMs or
    persists sessions is required to notify all attributes
    bound to sessions implementing HttpSessionActivationListener.

That seems pretty clear to me ... is it missing something?

>
> This also raises a Catalina issue I forgot to mention in the message with my
> PersistentManager patches. Currently there isn't any way (that I could see)
> to tell when a request has finished handling a session. It's possible that my
> persistence code could swap a session out while it's being used in a request.
>

No, there isn't :-(.  We need a registration mechanism a request can call that says "I
am currently using this session" and "I am done using this session."

>
> I'm not sure what the best way is to handle this. Possibly ContainerBase.invoke()
> could make a call to a new method in the Manager interface after the valves
> have all been invoked? Something like:
>
>     public void invoke(Request request, Response response)
>         throws IOException, ServletException {
>
>         if (first != null)
>             first.invoke(request, response);
>         else if (basic != null)
>             basic.invoke(request, response);
>         else
>             throw new IllegalStateException
>                 (sm.getString("containerBase.notConfigured"));
>
> +         if (manager != null && request.getSession(false) != null)
> +           manager.releaseSession(request.getSession());
>     }
>
> Then the manager can enforce a locking mechanism on the session.
>

There is the possibility of referencing more than one session in the same request, in
at least a couple of circumstances:

* The originally requested session is no longer valid,
  and a new one is created.

* The currently valid session is invalidated, and a
  new one is created.

so any registration/locking mechanism needs to deal with this correctly.

>
> Kief
>

Craig



Session passivation (was: NullPointerException from HttpSessionFacade.invalidate())

Posted by Kief Morris <ki...@bitbull.com>.
Craig R. McClanahan typed the following on 03:44 PM 1/14/2001 -0800
>"Christopher K. St. John" wrote:
>> >
>> > If your server implements session swapping or distribution (as we are 
>currently
>> > developing in the 4.1 repository), it is pretty much guaranteed that 
>different
>> > session object instances may be used during the lifetime of the same 
>session.
>> >
>>
>>  But don't you get session lifecycle events if that happens?
>
>Yes ... sessionWillPassivate() before the old session is removed, and
>sessionDidActivate() after the new one has been installed.

I hadn't thought about the issue of web apps keeping references to a session,
this underlines the concern I mentioned earlier about passivation events and
backing up sessions. If web app code depends on these events to tell it when
a session is being removed from memory, then they shouldn't be fired when
a session is just being backed up to a Store. But these may be needed for
pre/post passivation/activation cleanup tasks.

I may send a message to the api feedback address to get clarification on the 
spec. Namely:

- Is it OK for the container to keep multiple copies of a session in a distributed 
  web application? The spec doesn't say no, although it does say that only one
  instance of the app should be handling requests for a session at a time, which
  implies you could have multiple copies if you have a locking mechanism and
  maintain data consistency.

- If it is OK, should the container send activation/passivation events when a
  session is being serialized (or whatever) for replication purposes? Whatever
  the answer is, it would be nice if the spec clarified it explicitly so webapp
  developers can depend on it being consistent on different containers.

This also raises a Catalina issue I forgot to mention in the message with my
PersistentManager patches. Currently there isn't any way (that I could see)
to tell when a request has finished handling a session. It's possible that my
persistence code could swap a session out while it's being used in a request.

I'm not sure what the best way is to handle this. Possibly ContainerBase.invoke()
could make a call to a new method in the Manager interface after the valves
have all been invoked? Something like:

    public void invoke(Request request, Response response)
	throws IOException, ServletException {

	if (first != null)
	    first.invoke(request, response);
	else if (basic != null)
	    basic.invoke(request, response);
	else
	    throw new IllegalStateException
		(sm.getString("containerBase.notConfigured"));

+         if (manager != null && request.getSession(false) != null)
+	    manager.releaseSession(request.getSession());
    }

Then the manager can enforce a locking mechanism on the session.

Kief


Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
"Christopher K. St. John" wrote:

> "Craig R. McClanahan" wrote:
> >
> > If your server implements session swapping or distribution (as we are currently
> > developing in the 4.1 repository), it is pretty much guaranteed that different
> > session object instances may be used during the lifetime of the same session.
> >
>
>  But don't you get session lifecycle events if that happens?
>

Yes ... sessionWillPassivate() before the old session is removed, and
sessionDidActivate() after the new one has been installed.

My point in the remark above is that it is *not* a good assumption that a session
instance will be the same physical object throughout the session's lifetime.  And, on
a servlet 2.2 based server, there is no mechanism to tell you when it changes,
because the events are new to 2.3.

>
> -cks
>

Craig



Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by "Christopher K. St. John" <cs...@quik.com>.
"Craig R. McClanahan" wrote:
> 
> If your server implements session swapping or distribution (as we are currently
> developing in the 4.1 repository), it is pretty much guaranteed that different
> session object instances may be used during the lifetime of the same session.
> 

 But don't you get session lifecycle events if that happens?


-cks

Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
Hans Bergsten wrote:

>
> I agree that it's reasonable to assume that the same HttpSession
> instance is used throughout the session in the most common case,
> but I don't agree that the spec mandates this implementation (and
> I don't think it should mandate implementation details unless it's
> absolutely necessary for portability). But in a container that
> saves sessions to disk to conserve memory, or during server restart,
> you will most definitely see more than one instance. Same thing
> for a distributable application, where the session may migrate
> to another server.
>

If your server implements session swapping or distribution (as we are currently
developing in the 4.1 repository), it is pretty much guaranteed that different
session object instances may be used during the lifetime of the same session.

This is also true if you take advantage of the current support in Tomcat 3.2 and
4.0 for saving and restoring sessions across a server restart.

Craig



Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by "Christopher K. St. John" <cs...@quik.com>.
Hans Bergsten wrote:
> 
> But in a container that
> saves sessions to disk to conserve memory, or during server restart,
> you will most definitely see more than one instance. Same thing
> for a distributable application, where the session may migrate
> to another server.
> 

 You can see more than one instance, but you will always
be notified by an HttpSessionEvent. That's part of the
"normal session lifecyle" I mentioned, and I think that
we agree there is no ambiguity in that case.


> and that I'm pretty sure that
> whatever it is you want to do can be done in a way that's more
> likely to be portable
>

 You may very well be right, but that's irrelevant. It
doesn't matter if there's a better way, it matters that
according to a reasonable interpretation of the current
spec, it should be legal. 


> All I'm saying is that it's dangerous to rely on behavior
> that's not clearly defined by the spec, 
>

 Well, yes, but you have to be able to make _some_ 
assumptions, or the spec would be 12 feet thick. In
general, you can assume that if the spec doesn't
specifically allow counterintuitive behavior, then
it's disallowed. 

 There is admittedly a very fine balancing act that the
spec has to pull off: it must be loose enough to allow
innovative implementations, but strict enough to allow
interoperability.

 But give me a break: what JServ is doing in this case
is just fantastically counterintiutive.

 This probably needs to be summarized and sent as 
spec feedback, but unless he says otherwise I will
assume Gokul Singh is going to do it (Gokul?)


-cks

Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by Hans Bergsten <ha...@gefionsoftware.com>.
"Christopher K. St. John" wrote:
> 
> Hans Bergsten wrote:
> >
> > "Christopher K. St. John" wrote:
> > >
> > >   7.3 Session Scope
> > >
> > >   HttpSession objects must be scoped at the
> > >   application / servlet context level. The
> > >   underlying mechanism, such as the cookie
> > >   used to establish the session, can be shared
> > >   between contexts, but the object exposed, and
> > >   more importantly the attributes in that object,
> > >   must not be shared between contexts.
> > >
> > >  By mentioning that the HttpSession object cannot
> > > be shared outside the ServletContext, it strongly
> > > implies that it can be shared within the context.
> > > If that sort of thing isn't allowed, then 7.3 might
> > > need to be clarified.
> >
> > This section refers to the fact that a servlet in one context should
> > not be able to gain access to the same session data as a servlet
> > in another context (i.e., resources in two different context's can
> > not "be part" of the same session) for security reasons .
> >
> > It has nothing to do with whether a servlet in one context is allowed
> > to hold on to the actual session object or not, which has to do with
> > how much freedom the spec gives to container vendors in terms of
> > pooling and life-cycle management for the internal objects.
> >
> 
>  Because Section 7.3 explicity discusses the HttpSession
> object itself (as opposed to the objects it contains), it
> suggests that the HttpSession object has an identity.
> 
>  I don't think there is any question that after the end
> of the lifecycle of an HttpSession object, it can be
> recycled. But what earlier messages in this thread suggested
> was that JServ was recycling HttpSession objects _during_
> the lifetime of the session, so that req.getSession(false) could
> return two different objects even within the same session.
> 
>  That would mean that the practice of synchronzing on the
> HttpSession object was also not kosher? Since two servlets
> within the same session at the same time could not be sure
> of getting the same HttpSession object? Are you really
> suggesting that that behavior is allowed by the spec?

All I'm saying is that it's dangerous to rely on behavior that's
not clearly defined by the spec, and that I'm pretty sure that
whatever it is you want to do can be done in a way that's more
likely to be portable than relying on any particular behavior
in Tomcat with regards to the container-managed objects, like
HttpSession, HttpServletRequest etc.

I agree that it's reasonable to assume that the same HttpSession 
instance is used throughout the session in the most common case, 
but I don't agree that the spec mandates this implementation (and 
I don't think it should mandate implementation details unless it's 
absolutely necessary for portability). But in a container that
saves sessions to disk to conserve memory, or during server restart,
you will most definitely see more than one instance. Same thing
for a distributable application, where the session may migrate
to another server.

Why would you synchronize on the HttpSession instance? It's
up to the container to make sure that you can add and remove
objects from the session in a thread-safe manner. If you need
to synchronize for thread-safety of your application objects,
sync on the application object or an internal "lock object"
instead.

Hans
-- 
Hans Bergsten		hans@gefionsoftware.com
Gefion Software		http://www.gefionsoftware.com
Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com

Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by "Christopher K. St. John" <cs...@quik.com>.
Hans Bergsten wrote:
> 
> "Christopher K. St. John" wrote:
> >
> >   7.3 Session Scope
> >
> >   HttpSession objects must be scoped at the
> >   application / servlet context level. The
> >   underlying mechanism, such as the cookie
> >   used to establish the session, can be shared
> >   between contexts, but the object exposed, and
> >   more importantly the attributes in that object,
> >   must not be shared between contexts.
> >
> >  By mentioning that the HttpSession object cannot
> > be shared outside the ServletContext, it strongly
> > implies that it can be shared within the context.
> > If that sort of thing isn't allowed, then 7.3 might
> > need to be clarified.
> 
> This section refers to the fact that a servlet in one context should
> not be able to gain access to the same session data as a servlet
> in another context (i.e., resources in two different context's can
> not "be part" of the same session) for security reasons .
> 
> It has nothing to do with whether a servlet in one context is allowed
> to hold on to the actual session object or not, which has to do with
> how much freedom the spec gives to container vendors in terms of
> pooling and life-cycle management for the internal objects.
> 

 Because Section 7.3 explicity discusses the HttpSession
object itself (as opposed to the objects it contains), it
suggests that the HttpSession object has an identity. 

 I don't think there is any question that after the end
of the lifecycle of an HttpSession object, it can be
recycled. But what earlier messages in this thread suggested
was that JServ was recycling HttpSession objects _during_
the lifetime of the session, so that req.getSession(false) could
return two different objects even within the same session.

 That would mean that the practice of synchronzing on the
HttpSession object was also not kosher? Since two servlets
within the same session at the same time could not be sure
of getting the same HttpSession object? Are you really
suggesting that that behavior is allowed by the spec?

 If so, I find that very unintuitive.


-cks

Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by Hans Bergsten <ha...@gefionsoftware.com>.
"Christopher K. St. John" wrote:
> 
> Hans Bergsten wrote:
> >
> > The spec may not be explicit enough about this, but the session object
> > you get back from the getSession() object is a container-managed object
> > that the application is not supposed/allowed to keep long-lived
> > references
> > to. It's the same as with all other container-objects made available to
> > the
> > application; request, response, JSP tag handlers, etc.
> >
> 
>  I would have agreed with you before I read the
> following in the 2.3PFD spec:
> 
>   7.3 Session Scope
> 
>   HttpSession objects must be scoped at the
>   application / servlet context level. The
>   underlying mechanism, such as the cookie
>   used to establish the session, can be shared
>   between contexts, but the object exposed, and
>   more importantly the attributes in that object,
>   must not be shared between contexts.
> 
>  By mentioning that the HttpSession object cannot
> be shared outside the ServletContext, it strongly
> implies that it can be shared within the context.
> If that sort of thing isn't allowed, then 7.3 might
> need to be clarified.

This section refers to the fact that a servlet in one context should
not be able to gain access to the same session data as a servlet
in another context (i.e., resources in two different context's can 
not "be part" of the same session) for security reasons .

It has nothing to do with whether a servlet in one context is allowed 
to hold on to the actual session object or not, which has to do with 
how much freedom the spec gives to container vendors in terms of 
pooling and life-cycle management for the internal objects.

Hans
-- 
Hans Bergsten		hans@gefionsoftware.com
Gefion Software		http://www.gefionsoftware.com
Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com

Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by "Christopher K. St. John" <cs...@quik.com>.
Hans Bergsten wrote:
>
> The spec may not be explicit enough about this, but the session object
> you get back from the getSession() object is a container-managed object
> that the application is not supposed/allowed to keep long-lived
> references
> to. It's the same as with all other container-objects made available to
> the
> application; request, response, JSP tag handlers, etc.
> 

 I would have agreed with you before I read the
following in the 2.3PFD spec:

  7.3 Session Scope

  HttpSession objects must be scoped at the
  application / servlet context level. The
  underlying mechanism, such as the cookie
  used to establish the session, can be shared
  between contexts, but the object exposed, and
  more importantly the attributes in that object,
  must not be shared between contexts.

 By mentioning that the HttpSession object cannot
be shared outside the ServletContext, it strongly
implies that it can be shared within the context.
If that sort of thing isn't allowed, then 7.3 might
need to be clarified.


-cks

Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by Hans Bergsten <ha...@gefionsoftware.com>.
Gokul Singh wrote:
> [...]
> > The reason you see a behavior difference is that Tomcat 3.1 did not
> recycle session object instances, but Tomcat 3.2 does.
> 
> There lies the catch and the source of problem in my understanding.
>  In different requests relating to
> the same session, I may get referance to HttpSessionFacade instances which
> are different, but I expect them to be same (although not guarantied by
> specs but I thought it was a tacit agreement between container and servlet
> developer). 
> [...]

The spec may not be explicit enough about this, but the session object
you get back from the getSession() object is a container-managed object
that the application is not supposed/allowed to keep long-lived
references 
to. It's the same as with all other container-objects made available to
the
application; request, response, JSP tag handlers, etc.

I'm not sure why you're keeping references to the session objects in
you're application, but if you describe what you're trying to do I'm
sure I can give you a hint about another way to accomplish the same
thing without the problems you have with your current solution.
-- 
Hans Bergsten		hans@gefionsoftware.com
Gefion Software		http://www.gefionsoftware.com
Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com

Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by cm...@yahoo.com.
> Another solution, IMHO, is to make sure all these objects are only used
> within the thread they where allocated for. Briefly, add a package scope
> setThreadID() method to the classes that implement pooled objects like 
> this and let the container call this method with the current thread ID 
> before it delivers the object to the application. Then compare the
> current 
> thread ID with the assigned thread ID in all methods the application can 
> call. If they are not the same, throw IllegalStateException.

Well, that's a great idea - but it means adding a native method ( 
currentThread ) to absolutely all calls to all classes in the servlet API.
I did a test some time ago ( in another context ) - it's not a huge hit,
but it is visible.

Of course, the alternative ( either a sync() block if a pool is used or
garbage collection if the facade is not recycled ) may be as expensive,
but I was hoping that it can be done only for "untrusted" apps.
( on the other side, it's also possible to do 
if( untrusted && Thread.currentThread() != myThread ) ... ) )

I'll try both and see what happens. 

> Again, the spec is not clear on this. Maybe it needs to be clarified
> with regards to how the container-objects can be used by the application
> (some attempts to clarify this is being added to the JSP 1.2 spec with
> regards to tag handler classes).

One thing is clear - the current implementation ( at least 3.x ) doesn't
do any synchronization on request/response calls - if a servlet is using
more than one thread it's up to the servlet author to synchronize.
( most calls do not need any synchronization anyway, but it hasn't been
tested or verified ).

It would be nice to know that servlets are not allowed to create or use
threads ( and I don't think too many do that anyway ).

Thanks Hans.

Costin


Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by Hans Bergsten <ha...@gefionsoftware.com>.
cmanolache@yahoo.com wrote:
> 
> > There lies the catch and the source of problem in my understanding.
> >  In different requests relating to
> > the same session, I may get referance to HttpSessionFacade instances which
> > are different, but I expect them to be same (although not guarantied by
> > specs but I thought it was a tacit agreement between container and servlet
> > developer). What I suggest is that tomcat should recycle the
> > HttpSessionFacade instance only when the HttpSession instance is
> > recycled.This might be more inefficient as it will result in N instances on
> 
> You are right, I know what's the problem. It's not hard to fix, but this
> week I have no time ( and probably neither next week ), but this bug has
> been on my list.
> 
> In fact, there is a larger problem here - with very serious security
> and performance implications.
> 
> To get decent performance you need to recycle ( the cost of allocating
> few hundred objects per request is huge - it means the server will
> saturate on even small loads). Most servlet containers do recycle - the
> problem is common to all of them.
> 
> Unfortunately recycling opens a security hole: a (bad) servlet may keep
> reference to the HttpServletRequest, HttpServletResponse and HttpSession
> objects - and later access the them. That means it'll be able to access
> data in a HttpServletRequest that is in use by another servlet, in another
> application.
> 
> We have most of the elements to fix this hole - and with a decent ( small)
> perfomance hit. We need to make sure that a servlet receive only facades
> that are local to it's context. That's easy to do by either maintaining a
> per/context pool of facades or just doing nothing ( since the facade is
> very "light").
> 
> There is nothing that can be done with the original Request (and  I don't
> know any possible fix for this problem in containers that don't use
> facades ) - you know the context after you process the request, and then
> you've already allocated the request. It may be possible to process the
> request line before allocating the request - but that's ugly. Anyway,
> that's not a problem in 3.x.
> 
> Regarding HttpSessionFacade - you are right, ServerSession should have a
> get/setFacade and all getSession() calls should return the same
> facade. 1/2 of that is done in 3.3, I just need to do one more change -
> it's easy to duplicate this in 3.2 also. Of course, when the session is
> invalidated the facade must be either saved in a context-specific pool or
> just let it die.

Another solution, IMHO, is to make sure all these objects are only used
within the thread they where allocated for. Briefly, add a package scope
setThreadID() method to the classes that implement pooled objects like 
this and let the container call this method with the current thread ID 
before it delivers the object to the application. Then compare the
current 
thread ID with the assigned thread ID in all methods the application can 
call. If they are not the same, throw IllegalStateException.

Again, the spec is not clear on this. Maybe it needs to be clarified
with regards to how the container-objects can be used by the application
(some attempts to clarify this is being added to the JSP 1.2 spec with
regards to tag handler classes).

Hans
-- 
Hans Bergsten		hans@gefionsoftware.com
Gefion Software		http://www.gefionsoftware.com
Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com

Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by cm...@yahoo.com.
> There lies the catch and the source of problem in my understanding.
>  In different requests relating to
> the same session, I may get referance to HttpSessionFacade instances which
> are different, but I expect them to be same (although not guarantied by
> specs but I thought it was a tacit agreement between container and servlet
> developer). What I suggest is that tomcat should recycle the
> HttpSessionFacade instance only when the HttpSession instance is
> recycled.This might be more inefficient as it will result in N instances on

You are right, I know what's the problem. It's not hard to fix, but this
week I have no time ( and probably neither next week ), but this bug has
been on my list.

In fact, there is a larger problem here - with very serious security
and performance implications.

To get decent performance you need to recycle ( the cost of allocating
few hundred objects per request is huge - it means the server will
saturate on even small loads). Most servlet containers do recycle - the
problem is common to all of them.

Unfortunately recycling opens a security hole: a (bad) servlet may keep
reference to the HttpServletRequest, HttpServletResponse and HttpSession
objects - and later access the them. That means it'll be able to access
data in a HttpServletRequest that is in use by another servlet, in another
application.

We have most of the elements to fix this hole - and with a decent ( small)
perfomance hit. We need to make sure that a servlet receive only facades
that are local to it's context. That's easy to do by either maintaining a
per/context pool of facades or just doing nothing ( since the facade is
very "light"). 

There is nothing that can be done with the original Request (and  I don't
know any possible fix for this problem in containers that don't use
facades ) - you know the context after you process the request, and then
you've already allocated the request. It may be possible to process the
request line before allocating the request - but that's ugly. Anyway,
that's not a problem in 3.x.


Regarding HttpSessionFacade - you are right, ServerSession should have a
get/setFacade and all getSession() calls should return the same
facade. 1/2 of that is done in 3.3, I just need to do one more change -
it's easy to duplicate this in 3.2 also. Of course, when the session is
invalidated the facade must be either saved in a context-specific pool or
just let it die.

--
Costin


Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by Gokul Singh <go...@wipro.com>.
----- Original Message -----
From: Craig R. McClanahan
To: tomcat-dev@jakarta.apache.org
Cc: gokul.singh@wipro.com

Thanks for looking into the problem. I think the I was not able to convey
the problem properly. I have some clarifications below.

> The session object is valid for more than one request, but only up until
the time that it is invalidated.  After that, further access to the old
session object is illegal.

Agreed. But this is not what I am doing. The session is valid.
You can remove the lines of code
listed below from the code I posted and still you will get the Exception.
Remove the following two lines and follow the steps mentioned in the earlier
mail to reproduce the error.
==================
if(objSession != null)
   objSession.invalidate();
==================


> The reason you see a behavior difference is that Tomcat 3.1 did not
recycle session object instances, but Tomcat 3.2 does.


There lies the catch and the source of problem in my understanding.
 In different requests relating to
the same session, I may get referance to HttpSessionFacade instances which
are different, but I expect them to be same (although not guarantied by
specs but I thought it was a tacit agreement between container and servlet
developer). What I suggest is that tomcat should recycle the
HttpSessionFacade instance only when the HttpSession instance is
recycled.This might be more inefficient as it will result in N instances on
HttpSessionFacade if there are N valid sessions on the server, where as in
the present scenario, if my understanding is correct, there will be X
instances of HttpSessionFacade if there are X simultaneous requests. and X
is less than N.

To be more elaborate:
Lets us assume the following scenario.

1. A request comes which creates a new session. A HttpSession object (HS1)
is created and the Facade object (HSF1) wraps around it.
2. I store a referance to the session in the context that is a handle to
HSF1 which maps to the userid.
2. Another request comes from the same session . The object made available
to the request is not necessarily HSF1 and may be HSFx which wraps around
HS1.
3. At this point in time HSF1 may wrapped around another instance of HS or
nothing at all ( null).
4. I get the handle to the session which I want to invalidate from the
context which is HSF1. Now I am in trouble due to the point above.

In my opinion HSF1 should not refer to any other session till HS1 is
invalidated (or timed out).

What should I do to avoid this problem?

Why am I storing the referance of a session in context?
I want to prevent double login of the same user and on
the second login want to invalidate his previous login. The second login may
be from a different machine with no valid session.

Regds,
Gokul

>
> Craig McClanahan
>


Re: NullPointerException from HttpSessionFacade.invalidate()

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
Gokul Singh wrote:

> Hi,
>
> I am trying to build a login servlet and get a NullPointerException from
> HttpSessionFacade class in Tomcat 3.2.1.
> The code of the simple version of the servlet which reproduces the
> problem is attached at the end of this mail along with the stack trace of the
> Exception thrown.
> This piece of code works fine on tomcat 3.1.1 but fails on tomcat 3.2.1To
> reproduce the error,
> 1. start tomcat 3.2.1 afresh.
> 2. Login from a browser.The password field is not required as for now.
> 3. Open another browser (not a new instance of the same browser) on the same
> machine or another machine.
> 4. Login with the same username.
>
> the servlet does the following
> 1.it invalidates any existing session on this request.
> 2.it checks the context to find if the present user has any associated
> session and if it is there tries to invalidate it. (This is where I get the
> exception, given below).
> 3. creates a new session.
> 4. puts the new session into the context with the user id.
>
> In tomcat 3.2 is the session object which I get ( actually HttpSessionFacade)
> valid only for the request or can span multiple Requests?Any help would be
> greatly appreciated. I am not on this mailing list. Please send a CC to me at
> gokul.singh@wipro.com when replying to this mail
>
> Regds,
> Gokul

The session object is valid for more than one request, but only up until the
time that it is invalidated.  After that, further access to the old session
object is illegal.

The reason you see a behavior difference is that Tomcat 3.1 did not recycle
session object instances, but Tomcat 3.2 does.

Craig McClanahan