Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access HTTP sessions in Java

How to get any http session by id or all currently active http sessions within web application (Java 2 EE) in an elegant way?

Currently I have a WebSessionListener and once session was created I put it in ConcurrentHashMap() (map.put(sessionId, sessionObj)), everything ok, I can retrieve HTTP session from that map in any time by session id, but it looks like the HttpSession objects will never finalize... Even session was invalidated the map still reference on invalidated session object... Also I have read this article and it looks like the WeakHashMap is not acceptable in my case...

In other words I need a possiblity to look in any HttpSession even get all currently active HttpSession and retrieve some attributes from there...

Please advice somebody :)

Update

I need to access HttpSession objects because of follwoing reason:

Sometimes user does some actions/requests that may impact the work of another concurrent user, for example admin should disable user account but this user currently working with the system, in this case I need to show a message to admin e.g. "user XXX is currently working with the system" hence I need to check if any HttpSession which holds credentials of user XXX already exists and active. So this is whay I need such possibility to get any http session or even all sessions.

My current implementation is: SessionManager which knows about all sessions (ConcurrentMap) and HttpSessionListener which put/remove session into SessionManager.

I was concerned about memory issues that may occure and I wanted to discusse this with someone, but currently I am clearly see that everything should works fine because all invalidated session will be removed from map when sessionDestroyed() method will be called...

Many thanks for your replays, but now I understood that problem was just imagination :)

like image 924
endryha Avatar asked Jul 13 '10 09:07

endryha


People also ask

How does HTTP session work in Java?

The Servlet HTTP session uses a cookie with the name JSESSIONID and a value that identifies the session. The Servlet container keeps a map (YMMV) of HttpSession objects and these identifiers. When a client first makes a request, the server creates an HttpSession object with a unique identifier and stores it in its map.

How do I find the HTTP session object?

How to get the HttpSession object ? The HttpServletRequest interface provides two methods to get the object of HttpSession: public HttpSession getSession():Returns the current session associated with this request, or if the request does not have a session, creates one.

Where is HTTP session stored?

httpSession contains the properties, and is stored on the Web client as a cookie.


2 Answers

As per your clarification:

Sometimes user does some actions/requests that may impact the work of another concurrent user, for example admin should disable user account but this user currently working with the system, in this case I need to show a message to admin e.g. "user XXX is currently working with the system" hence I need to check if any HttpSession which holds credentials of user XXX already exists and active. So this is whay I need such possibility to get any http session or even all sessions.

For this you actually don't need to know anything about the sessions. You just need to know which users are logged in. For that you can perfectly let the model object representing the logged in user implement HttpSessionBindingListener. I of course assume that you're following the normal idiom to login/logout user by setting/removing the User model as a session attribute.

public class User implements HttpSessionBindingListener {

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        Set<User> logins = (Set<User>) event.getSession().getServletContext().getAttribute("logins");
        logins.add(this);
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        Set<User> logins = (Set<User>) event.getSession().getServletContext().getAttribute("logins");
        logins.remove(this);
    }

    // @Override equals() and hashCode() as well!

}

Then somewhere in your admin app, just obtain the logins from ServletContext:

Set<User> logins = (Set<User>) servletContext.getAttribute("logins");
like image 170
BalusC Avatar answered Sep 30 '22 12:09

BalusC


Generally speaking, your servlet container will have its own session manager, which is responsible both for maintaining the lifecycle of the sessions, and associating incoming requests with the appropriate session (via cookies, anchor parameters, whatever strategy it wants).

The elegant way to do this would be to hook into this session manager in whatever way it allows. You could subclass the default one, for example, to allow you to get access to arbitrary sessions.

However, it sounds like what you're doing belies an underlying problem with your architecture. The data contained within a session should be specific to that session, so in general you shouldn't need to look up an arbitrary one in order to provide the standard logic of your web application. And administrative/housekeeping tasks are usually handled for you by the container - so again, you shouldn't need to interfere with this.

If you gave an indication of why you want access to arbitrary sessions, chances are that an alternative approach is more suited to your goals.

like image 21
Andrzej Doyle Avatar answered Sep 30 '22 10:09

Andrzej Doyle