SessionMap vs Map which is better for Session? - java

Is there any advantages of using SessionMap over Map for a session in web application ?
1 advantage I found was you can invalidate a SessionMap but not Map.

The SessionMap is specifically designed for the purposes if you want to have access to the servlet session attributes. So, the user is able to keep a synchronized collection of objects in session and use it instead of HttpSession directly.
This object is automatically injected by the servletConfig interceptor which is a part of the defaultStack if you implement SessionAware interface in the action class.
As soon as you don't need to work with servlet session directly and don't have access to it you can at least invalidate a session that finalizes the collection of objects in it.
A new session map required to action context if you want to continue to use a session.

Related

How to maintain user object throughout the application using session in java

I am writing one application, on that i am setting user object into a session and i cannot able to get that session into another controller. And i want to maintain that session throughout the application(Until the user logout). So how can i get the session object into another controller and throughout the application. And what are the steps that i need to follow to maintain the session throughout the application.
Setting into session:
public ResponseEntity<Object> getCustMenus(HttpSession session){
UserInformation userInformationSession = luser.getRolesData();
session.setAttribute("userInfo", userInformationSession);
}
Getting the session:
UserInformation userInformation=(UserInformation) session.getAttribute("userInfo");
System.out.println("-----"+userInformation.getUserName()+"----------username");
I came across your question, because I'm also facing the same problem.
I think we can rely on Tomcat's request handling mechanism - each request is running in a single thread.
So I can have
Static map where key is the request Thread object and value is the Httpsession or even HTTpRequest object. Map
Filter with url set to /* which means each request passes through this filter. The filter will add the current thread and request object to the static map.
map.put(Thread.currentThread(), httpRequest);
As the map is a static field of some class it will be accessible to all threads and if you need to share an object between different controllers though lifecycle of a request you can put it in this map, e.g. put in httpsession as an attribute and get it anywhere you want.
In filter remove the thread from map when request is done.
map.remove(Thread.currentThread());
In case we use WeakHashMap I suppose we can skip step 3.
I haven't tried this approach yet, but I think it should work. I will share results when I try it.
I found complete answers in another discussion. Get the HttpServletRequest (request) object from Java code
The most useful part of the discussion for me was posted by skaffman. Please find it below.
Spring provides the RequestContextFilter for just this purpose. It uses ThreadLocal, and allows the code to fetch the current request via RequestContextHolder. Note that this filter does not require you to use any other part of Spring:

Best way to store/retrieve frequently used data from the HttpSession

I have a standard GAE app with Java servlets. I want to implement user role functionality throughout the system. For this purpose I want to retrieve user role from the database and store it in the session, in such a way all servlets will have access to this data. I read some articles about it and the basic way to do it is to use Filters to populate HttpSession with necessary data. However, in this case I should retrieve data from the HttpSession in every servlet in the same way, which results in code duplicates. Evident solution for this problem is just to derive from HttpServlet class and create own Servlet with necessary methods for working with HttpSession (e.g. protected Role getUserRole()). This makes the usage of the Filters pointless.
Is there any reason to use Filters in this case?
You should have a top level filter, which maps to /*. This filter will do the fetching of role from database , if not present in session. Now you extend HttpServletRequest and create a wrapper overriding isUserInRole() method, so that role is fetched as you like. Create an object of this request object and use in chain.doFilter in Filter.
So all Servlets can just call request.isUserInRole() to check roles
You can have a main servlet that directly inherit from HttpServlet, this servlet knows how to get the user roles from the HttpSession via protected Role getUserRole(). All other servlets within your application should then subclass that main servlet to have the common functionality available to them.
Servlet filters get invoked prior to the invocation of any other servlet, the main purpose of filters is to decorate the requests/responses before handing them over to the servlets for further processing. You have the choice of accessing your database from within the filters and populate the HttpSession accordingly, then each servlet will know how to retrieve that information from the HttpSession later on.
The other option that I recommend here is to populate the HttpSession with the user roles from within the first servlet that process the request (you could have another common method of the main servlet to do that, e.g. protected void populateUserRole(HttpSession httpSession)).
Cheers;

Get Hibernate Session from Interceptor

I'm writing a hibernate interceptor and I need to access the hibernate session object. Is their a direct way to access the hibernate session using the interceptor?
What I'm trying to do is to find out what database hibernate has connected to. For various reasons, this is going to be impractical to store as thread local data.
Yes, there is a way... just pass session to Interceptor after creation:
Session session = factory.openSession(interceptor);
interceptor.setSession(session);
And you have session inside interceptor! Just remember that:
Interceptor can't access session it's running in, so don't use it directly to change / add objects.
You can open temporary session on the same JDBC connection
Transaction will be the same for both sessions
try {
Connection connection = mySession.connection();
Session tempSession = HibernateUtil.getSessionFactory().openSession(connection);
// do something
tempSession.flush();
}
finally {
tempSession.close();
}
There seems no "official" way of getting hold of the session object neither through o.h.Interceptor neither through o.h.EmptyInterceptor. Moreover, Interceptor's Javadoc says:
There might be a single instance of Interceptor for a SessionFactory,
or a new instance might be specified for each Session. Whichever
approach is used, the interceptor must be serializable if the Session
is to be serializable. This means that SessionFactory-scoped
interceptors should implement readResolve().
The Session may not be invoked from a callback (nor may a callback
cause a collection or proxy to be lazily initialized).
The only way to get this information seems to be by using reflection and has been answered here.

Is Spring session scoped bean saved in HttpSession?

Since I don't have in depth knowledge of spring session scope implementation.
Can anyone please tell me if it is wise to use Spring Session scoped beans, where HttpSession object is very crucial. Like a web application where thousands of users access the site simultaneously.
Is spring session scoped bean saved in HttpSession object?
Or even if HttpSession object only refers to the spring session scoped bean, are we not making session object heavy?
How is it different form storing any bean directly in HttpSession object (making HttpSession object heavy point of view)?
The object is not really stored in HTTP session. It is linked with session id and actually stored inside of the Spring context. A session listener is used to clean instances once session is closed. See SessionScope JavaDoc.
Here's what the Spring docs say:
Scopes a single bean definition to the lifecycle of a HTTP Session.
Only valid in the context of a web-aware Spring ApplicationContext.
"Heavy"? No heavier than the object you're putting in it. Sessions should have a finite lifetime. A few kbytes per session won't be the end of your application. A simple calculation for the number of simultaneous sessions and object memory requirements should reassure you about your app server memory settings. You can always increase min and max memory if needed.
Storing things in HTTP session happens the same whether you're a Spring bean or not. The bean factory just does some extra things to help manage the object lifecycle for you.
Is spring session scoped bean saved in HttpSession object?
If the HttpSession object you mentioned here is actually provided by spring-session (spring-session wraps the httpSession object in original httpRequest), the answer would be YES -> indeed, all the spring session scoped beans are saved in the httpSession provided by spring-session as attributes.
Or even if HttpSession object only refers to the spring session scoped bean, are we not making session object heavy?
No. The "heaviness" of the httpSession very much depends on the objects you put in. In addtion, session beans are meant to be ephemeral. Last but not least, the session object in micro-services world is usually offload to a stand-alone store, like Redis or HazelCast. So, it won't be considered as "heavy" in terms of memory consumption.
How is it different form storing any bean directly in HttpSession object (making HttpSession object heavy point of view)?
No difference at all (assuming you are using spring-sesion), as all the all the spring session scoped beans are saved in the httpSession provided by spring-session as attributes.

httpservletrequest - create new session / change session Id

I'm maintaining a Java web application.
Looking into the login code it gets an HttpSession out of HttpServletRequest via the getSession() method of HttpServletRequest. (It uses some values in the session for authentication purposes)
However I'm worried about session fixation attacks so after I have used the initial session I want to either start a new session or change the session id. Is this possible?
The Servlet 3.0 API doesn't allow you to change the session id on an existing session. Typically, to protect against session fixation, you'll want to just create a new one and invalidate the old one as well.
You can invalidate a session like this
request.getSession(false).invalidate();
and then create a new session with
getSession(true) (getSession() should work too)
Obviously, if you have an data in the session that you want to persist, you'll need to copy it from the first session to the second session.
Note, for session fixation protection, it's commonly considered okay to just do this on the authentication request. But a higher level of security involves a tossing the old session and making a new session for each and every request.
Since Java EE 7 and Servlet API 3.1 (Tomcat 8) you can use HttpServletRequest.changeSessionId() to achieve such behaviour. There is also a listener HttpSessionIdListener which will be invoked after each change.

Categories

Resources