Re: NullPointerException from HttpSessionFacade.invalidate()
I've been lurking and searching through the archives searching for an answer to the issue which was eventually reported as bug #739 I've found some excellent descriptions of the problem but have been unable to discover a solution in the archives. I was hoping that someone can point me towards a workaround. Essentially we've written an app server that runs process on different threads. These threads all have access to an object which I'll just call an Mcache object. Part of the MCache is a hash table so when we pass the Mcache a session ID it returns that particular session. As is standard procedure when dealing with servlets we are saving data that must be available for the life of the session in the session object (which is now actually an HttpSessionFacade object). The problem of course is that I need to call setAttribute and getAttribute on this session. And when I do this I have to expect that the session that the Mcache object refers to by a particular sessionID is the same object at all times. However, it seems that any particular HttpSessionFacade may wrap any particular HttpSession, or even a null if that facade has been recycled. Obviously, when we create a session or get a session or do any of the things which are standard operating procedure with sessions we would not expect a particular instance of that session to suddenly change, or even suddenly become null. This is not standard behavior of a java.servlet.http.HttpSession and I would not expect the facade to do so either. So there must be some workaround. Because if all my sessions are being wrapped with HttpSessionFacade against my will, and those facades will change or nullify themselves against my will then we're basically saying "If you use Tomcat you can't use a session object because we can no longer guarantee that your session objects will even exist when you need them". This is obviously not what the Tomcat team intended. So there must be a way for me to get my session back based on a session ID that I have saved in my Mcache. What would be the correct procedure for getting the HttpSessionFacade that refers to an instance of a java.servlet.http.HttpSession that has a particular sessionID ? I thank you in advance for you assistance. Greg
Re: NullPointerException from HttpSessionFacade.invalidate()
Gokul Singh 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'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. I am trying to disallow a single user to have multiple login sessions valid at any given time. I have to enforce this even if the user tried to login from two different machines.Can you suggest a solution for this which works on tomcat 3.2.1 and uses servlet specs 2.2 only. Regds,Gokul When I had to do something similar, I maintained a Hashtable in a servlet context attribute that was keyed by username rather than by session id. My login logic (that processed the username and password) checked for the username already being in this Hashtable, and disallowed a login if it was already there. For logout, I also stuck in a session attribute which implemented HttpSessionBindingListener, so that I could remove this user's entry when the current session was invalidated. As others will undoubtedly point out, you still get to face the usual set of issues when a user has multiple windows open on the same client machine. Craig
Session passivation (was: NullPointerException from HttpSessionFacade.invalidate())
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 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
Gokul Singh wrote: > > - Original Message - > From: "Hans Bergsten" <[EMAIL PROTECTED]> > > > > Gokul Singh wrote: > > > > > > Hans Bergsten wrote: > > > > [...] > > > > > > I am trying to disallow a single user to have multiple login sessions > > > valid at any given time. I have to enforce this even if the user tried > > > to login from two different machines. > > A small addition here. The requirement is that the user be allowed to login > by creating a new session on login request and invalidating any valid > session that he may have at that time. > To be more elaborate. > 1. A user U logs in and has a session associated with him i.e. S1. > 2. user U goes to another machine and tries to login. > 3. The user U should get a new session S2 with S1 being invalidated. > > I hope the requirements are now clear. Okay, that's very different ;-) > [...] > The requirement is that the user can login any no. of times he wants. But he > should have only one valid session and that should be the session from the > last successful login attempt as mentioned above. > > Can you please tell me if this is possible using 2.2 specs and tomcat 3.2.1 Probably not by basing it on the standard session mechanism, since requests within one session can not access or invalidate another session. Again, this would not be possible even if the same HttpSession instance was kept throughout the session. But I must admit that I find the requirement a bit strange, since to me it amounts to pretty much the same as allowing multiple concurrent logins from the same user. Why does it matter if a user has more than one session active at the same time, on two different machines? What is it you want to accomplish by only allowing one valid session at a time? Anyway, you may have to look at a combination of a currentUsers list as a context attribute and your own "session data store", also as a context attribute, or in a database or some other external storage facility. > PS: I have joined this list today only. I am not sure if this posting is > appropriate for this list or not. > If it is inappropriate here, then please mail to me privately. By now, this is off-topic for this list. So if you want to continue the discussion, I suggest you mail me privately. Hans -- Hans Bergsten [EMAIL PROTECTED] Gefion Software http://www.gefionsoftware.com Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
- Original Message - From: "Hans Bergsten" <[EMAIL PROTECTED]> > > Gokul Singh wrote: > > > > Hans Bergsten wrote: > > > [...] > > > > I am trying to disallow a single user to have multiple login sessions > > valid at any given time. I have to enforce this even if the user tried > > to login from two different machines. A small addition here. The requirement is that the user be allowed to login by creating a new session on login request and invalidating any valid session that he may have at that time. To be more elaborate. 1. A user U logs in and has a session associated with him i.e. S1. 2. user U goes to another machine and tries to login. 3. The user U should get a new session S2 with S1 being invalidated. I hope the requirements are now clear. > archives for details). The bottom line is that a session is associated > with a "client", not a "user". Agreed. > > Can you suggest a solution for this which works on tomcat 3.2.1 and > > uses servlet specs 2.2 only. > > Something like this should work in any compliant container. Thanks for putting down the whole code for me. I already implement this philosophy in my code. But the requirements are slightly different as spelled above. > To make sure a user only logs in once, check if the loginID is > already in the context structure before allowing a new login > and creating the UserBean. The requirement is that the user can login any no. of times he wants. But he should have only one valid session and that should be the session from the last successful login attempt as mentioned above. Can you please tell me if this is possible using 2.2 specs and tomcat 3.2.1 Regds, Gokul PS: I have joined this list today only. I am not sure if this posting is appropriate for this list or not. If it is inappropriate here, then please mail to me privately. > > Hans > -- - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
> Gokul Singh 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'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. > > I am trying to disallow a single user to have multiple login sessions > valid at any given time. I have to enforce this even if the user tried > to login from two different machines. Okay, in that case comparing HttpSession objects wouldn't work even if Tomcat kept the same instance throughout the session. If the user tries to log in from two different machines, he/she would get always get two different sessions. Even when using two different browser windows on the same machine, he/she may end up with two different sessions (long story, search the JSP- and SERVLET-INTEREST list archives for details). The bottom line is that a session is associated with a "client", not a "user". > Can you suggest a solution for this which works on tomcat 3.2.1 and > uses servlet specs 2.2 only. Something like this should work in any compliant container. Create an instance of a class that implements the javax.servlet.http.HttpSessionBindingListener interface and save it in the session when the user logs in. Give the instance references to the ServletContext and the user's login ID. In the valueBound() method, add the loginID to a data structure kept as a context attribute, and in the valueUnbound() method, remove the user info from the data structure: public class UserBean implements HttpSessionBindingListener, Serializable { private ServletContext context; private String loginID; public UserBean(ServletContext context, String loginID) { this.context = context; this.loginID = loginID; } public void valueBound(HttpSessionBindingEvent e) { Vector currentUsers = (Vector) context.getAttribute("currentUsers"); if (currentUsers == null) { currentUsers = new Vector(); } currentUsers.addElement(loginID); } public void valueUnbound(HttpSessionBindingEvent e) { Vector currentUsers = (Vector) context.getAttribute("currentUsers"); currentUsers.removeElement(loginID); } } To make sure a user only logs in once, check if the loginID is already in the context structure before allowing a new login and creating the UserBean. Hans -- Hans Bergsten [EMAIL PROTECTED] Gefion Software http://www.gefionsoftware.com Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
Christopher K. St. John wrote:> > All I'm saying is that it's dangerous to rely on behavior> > that's not clearly defined by the spec, > >> But give me a break: what JServ is doing in this case> is just fantastically counterintiutive. I agree with Chris on this. > 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?) I think the specs do need to clarify this matter. So I think I am going to summarize it and send it to spec feedback. Regds, Gokul > > -cks>
Re: NullPointerException from HttpSessionFacade.invalidate()
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'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. I am trying to disallow a single user to have multiple login sessions valid at any given time. I have to enforce this even if the user tried to login from two different machines. Can you suggest a solution for this which works on tomcat 3.2.1 and uses servlet specs 2.2 only. Regds, Gokul
Re: NullPointerException from HttpSessionFacade.invalidate()
"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 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
"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 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
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 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
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 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
"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 [EMAIL PROTECTED] Gefion Software http://www.gefionsoftware.com Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
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 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
"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 [EMAIL PROTECTED] Gefion Software http://www.gefionsoftware.com Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
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 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
> 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 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
[EMAIL PROTECTED] 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 [EMAIL PROTECTED] Gefion Software http://www.gefionsoftware.com Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
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 [EMAIL PROTECTED] Gefion Software http://www.gefionsoftware.com Author of JavaServer Pages (O'Reilly), http://TheJSPBook.com - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
> 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 - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
Re: NullPointerException from HttpSessionFacade.invalidate()
- Original Message - From: Craig R. McClanahan To: [EMAIL PROTECTED] Cc: [EMAIL PROTECTED] 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 > - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]
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 theproblem 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 samemachine or another machine.4. Login with the same username.the servlet does the following1.it invalidates any existing session on this request.2.it checks the context to find if the present user has any associatedsession and if it is there tries to invalidate it. (This is where I get theexception, 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 [EMAIL PROTECTED] when replying to this mailRegds,Gokul= 8< SERVLET CODE = 8< ===import javax.servlet.*;import javax.servlet.http.*;import java.io.*;public class TestSessionBehaviourextends 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("ReceiptThe login isrecorded"); } private void sendLoginPage(PrintWriter out) { out.println("Test LoginPlease login method=post> "); out.println("Name "); out.println("Passwordname=pass>"); out.println("type=submit value=login>"); out.println(""); }}= 8<= EXCEPTION THROWN 8< =Internal Servlet Error:java.lang.NullPointerException atorg.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) atorg.apache.tomcat.core.ContextManager.internalService(ContextManager.java:797) at org.apache.tomcat.core.ContextManager.service(ContextManager.java:743) atorg.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:210) atorg.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416) atorg.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---