In our web application (in JBoss using Struts) we use sessions largely for security as well as to cache some data for a User. Thus, every user logged into the application has a session and different data cached in it.
Based on some parameter change, i want to change the cache of the subset of users who are logged in (i.e. have session)
Can this be achieved? I have not been able to find anything so far from general search.
You can use a HttpAttributeListener
a basic example here
HttpSessionAttributeListener:
The HttpSessionAttributeListener interface enables an object to
monitor changes to the attribute lists of sessions within a given Web
application. The HttpSessionAttributeListener in turn extends
java.util.EventListener. The methods in it are
attributeAdded(HttpSessionBindingEvent se)- This is the notification that an attribute has been added to a session.
attributeRemoved(HttpSessionBindingEvent se)- This is the notification that an attribute has been removed from a session.
attributeReplaced(HttpSessionBindingEvent se)- This is the notification that an attribute has been replaced in a session.
You can do it by storing each session object in a static List<Session> in some holder object. You can put it by a HttpSessionListener#sessionCreated(..). Remember to remove it from the list on sessionDestroyed(..)
Then, whenever you want to do something, simply loop the previously stored list of sessions and do whatever you want with them.
You have basically 2 options:
Push the changes. Get hold of all HttpSession instances in an application wide map which you manage with help of a HttpSessionListener. This way you can just get them from the application scope and walk through them to make the necessary changes directly.
Poll the changes. Store a change instruction in the application scope. On every HTTP request, check with help of a Filter or ServletRequestListener if a change is required, then make the necessary change in the current session and remove/disable the change instruction.
A completely different alternative is to use an application wide shared cache, such as Terracotta or Ehcache, so that you don't need to duplicate the same data over all HTTP sessions. You'd just need to deal with the data on a per-request basis. When database access comes into picture with JPA, then read on about "2nd level cache", that's exactly what it does.
Related
I have a session attribute in my controller #SessionAttribute("sample_dto"). I need to work with the sample_dto even after session get timeout. What is the way to do this properly.
PS: When session get timeout, browser is redirected to login screen. How can I avoid it and bring it back to the place where I was before session get timeout.
Thanks
According to your question, I think you don't need a session attribute. Because you need to access the same data item in between
separate sessions. The simplest solution is to use a normal instance variable. Because your controller is singleton in default.
It is similar to application scope since you don't change the scope of your controller and don't restart your application.
If this task is user specific (your data item should persist per user basis), then you can use cookies for saving the temporary user status.
In order to set the cookies you can implement your own HttpSessionListener class and within the sessionDestroyed method you can do your cookie saving things.
Because you need to do this thing only when your session is get destroyed(timeout).
If your data is much bigger, then you can save the data in the database by referring to the relevant user. You can use the same sessionDestroyed method.
I have a login page which connects to a Database, the Database has only one client, when a user logs on he/she may make certain changes to his profile and then save. A large number of frames require the current user id in order to manipulate his data
Among the possible ways of storing the user currently logged in is
1) to save the data to a temporary text file and persist it before the user logs out
2) another option would be to use variables across all the frames ,however I'm not too confident about this
3) a third way would be to have a Boolean column in the database and to persist the the data of the field with true in it
Perhaps there are better ways of storing the current user Id could somebody elucidate other possible methods and highlight the pros and cons of each implementation with reference to an "optimal" method of doing this
Edit: This is a desktop application
I would suggest not to share this information in any static context for the reason it will render your project as very hard to test once it gets big enough. See this link for more info: When to use singletons, or What is so bad about singletons?
What I would do is store session objects in some map, identifying the appropriate session by an ID that will be given and sent back to you via client cookie. This is how the web has been doing it for years, and it is still doing it this way. Simply pass the session object around to any class that requires access to that data when it needs it.
If you are using a J2EE implementation, then you may already have support for sessions within that implementation, you should check out "How to Use Sessions"
This is more of a software design question, and covering the basis to complete the patterns used to support what I just suggested is unfortunately beyond the scope of the question
The logged user is an instance of the class Person or LoggedUser.
You have to instantiate it and share its reference between Views via a Model.
We have an web application which involves creating some heavy Utility Objects (in terms of memory performance). Its usage can be on any application tier. These utility objects are specific to user. So ideally what should have been happening is create these objects when the user logs in, cache them 'somewhere' and reuse them wherever needed.
The available options right now are Session,Application. But these are not available to all the tiers. One way is to pass these to subsequent tiers. But this will violate the Separation of Concerns approach and other tier will need to know about web tier.
Another approach is t use a static utility class to cache these objects. Something like
MyUtilObject myObject = MyUtilCache.getMyUtilObject(userName);
Internally, backed up by something like a HashMap (and possibly a soft reference). These objects would be cleaned on user logout or session expiry.
Here is what we are using
JBoss, Struts1.2, Spring. All the tiers on on the same machine (in single runtime).
Please share your thoughts/approaches on this.
All you need is an interface that is common to all tiers. The implementation can be backed by the Session and injected wherever it is required.
creating some heavy Utility Objects
Explain in details when user logs in , what kind of heavy objects are stored over a period of time?
It is always good to have smaller datain HttpSession.Typical web application session lasts for seconds or minutes for an user. Mostly it should contain authorization, user preferences, connection infos and states .it should not contain data , that is useful from current page to next. Of course you can store too much data , for session heap is the limit. But there could be race condition if you store for long time. If the data is required for this request, then keep in HttpRequest. Otherwise you have 2nd level caches such as EHCACHE,*MEMCACHE* or TerraCotta,apply policies such as till the session expires , make this cache available for all the pages. Also between each pages pass a unique id , that determines cache info.
Another approach is t use a static utility class to cache these
objects
Static class is common to all users. How can you have static class specific to user.
Why not Serialize/De-serialize the objects as and when required. When the Objects are required at that point De-serialize them and at session close serialize them again
I've been always trying to avoid using Sessions. I've used spring security or other ways of having user logged in the application, which is I suppose the major use case for using Sessions.
But what are the other use cases ? Could you please make a list of those most important ones ? How come that I've been able to develop even complicated applications without using Sessions?
Is it because I'm using spring-mvc and using Sessions is practically not needed except the login stuff ?
EDIT: Guys this question was asking for use cases... Most of the answers explains what are sessions for. If we summarize some usecases, we can say for sure, when to use database or sessions for maintaining conversation state...
Don't you remember any concrete scenarios you needed sessions for? For past years :)
for instance some conversational state may become persistent after some point / event. In this case I'm using database from the beginning.
I think you can do anything you want without storing anything on a sessions.
I usually use the sessions to avoid having to pass state between the client and server (used id as an example) and when I don't want to send sensitive information to the client (even in encrypted form) as it might be a security problem.
Other ways of avoiding using the session are:
store some state on a database, e.g. shopping carts, instead of in the session, even if the cart is discarded after a certain amount of time.
store state in cookies e.g. for user customization
One use case when it's really useful to use the session is for conversations, although usually frameworks manage that behind scenes, and store the conversation in the session.
edit
Converstions (in my understanding) are something like wizards, in which you complete several forms in different pages and at the end you perform the action. e.g. in a checkout process, the user enters his name, shipping address and credit card details in different pages, but you want to submit the order just at the end, without storing any intermediate state in your DB.
By sensitive information I mean, imagine in the previous example, once the user sent his credit card details, you shouldn't return that information in any format (even encrypted) to the user. I know it's a bit paranoid, but that's security :).
In the ecommerce system i'm working on, there is an external system at the back-end which stores users' saved shipping and billing addresses. Our web app talks to it by making web service calls to retrieve those addresses. When we get the addresses, we store them in the session. That way, we only have to call the service once, when the user firsts looks at their addresses, and not every time we serve a page which needs address information. We have a time-to-live on the addresses, so if the addresses change (eg if the user telephones the customer service desk to change an address), we will eventually pick up the fresh ones.
It would be possible to store the addresses in our database, rather than in the session. But why would we? It's transient information which is already stored permanently somewhere else. The session is the ideal place for it.
Well in one sense your question is deep (what's SPECIAL about a session is worth knowing) and in another sense it's shallow (what can't I do if I don't use them turns out to be a somewhat odd question)
In the end a Session is merely (or could be) a ConcurrentHashMap (in fact it usually isn't that threadsafe) with a a key of unique session id passing as the cookie. You know why it's useful, but to answer you for use cases
clustering (this is how state gets distributed across nodes)
caching general state of the user and their objects (as opposed to reloading from db each time)
built in methods for sessionlisteners to watch when someone is timed out, or attributes change.
= used for by a lot of localization utilities
Can you do all this with a database or your own hashmap implementation/filter? Of course, there's nothing magical about Sessions. They are merely a convenient standard for having some objects follow a logged in user and be tied to the lifetime of that user's use of the application.
Why do you use Servlets? You could also implement your own socket level standard? The answer to that is using standard apis/implementations provides convenience and other libraries build upon them.
The cons are
you are reinventing the wheel and some code that has been time tested
you won't be able to use a lot of built in facilities for monitoring/managing/clustering/localizing etc.
Sessions are one way of maintaining conversational state across multiple requests (e.g. multiple stateless HTTP requests.)
There are other ways of implementing conversational state, for example, storing an authentication token or some suitable conversation id as a cookie and maintaining a store of conversation id to session state. (In essence, duplicating what the app server is doing when it provides sessions.)
That you haven't needed to use sessions means that your application either doesn't need conversational state or you've implemented it in a different way. For example, perhaps your application uses an authentication token (say a cookie) and persists all state changes to the database. With that kind of arrangement, there is no need for a conversation state.
Hi you can take an example of shopping cart because since Http is stateless protocol it does not maintain the status of the user who sends the request.
For e.g.
If one user sends a request to buy camera from say eBay and after some minutes another user sends a request to buy laptop.
But since http is stateless protocol so server is not able to separate the request send by the users and may it happen that the bill of the laptop may be given to first user.
So through session we can maintain a particular entity over the server side for a particular user.
Describe please a typical lifecycle of a Hibernate object (that maps to a db table) in a web app.
Suppose, you create a new instance of an object and persist in the db.
But during the app lifetime you'll be working on a detached object and finally
you need to update it in the database, for example on exit.
How does it look like with hibernate and spring?
p.s. Can transactions and sessions live between servlet transitions? So that we opened 1 session and use it in all servlets without a need to reopen it?
I'll try to give a descriptive example.
Suppose, when the app starts, the log record is created. this can be done at once,
Log log = new Log(...) and then something like save(log) -- log corresponds to a table LOG.
then, as the application processes user inputs and keeps going, new data is being accumulated.
and after the second step we could add something to a log object, a collection for example:
// now we have a tracking of what user chosen: Set thisUserChoice,
// so we can update the persistent object, we have new data now !
// log.userChoices = thisUserChoice.
Here occurs the nature of my question. How are we supposed to deal with it, if we want to
update the database whenever new data is gotten from a user?
In a relational model we can work with a row id, so we could get this record and update some other data of the row.
In Hibernate we are also able to load a object by its id.
But is IT THE WAY TO GO? IS ANYTHING BETTER?
You could do everything in a single session. But that's like doing everything in a single class. It could make sense from a beginner's point of view, but nobody does it like that in practice.
In a web app, you can normally expect to have several threads running at once, each dealing with a different user. Each thread would typically have a separate session, and the session would only have managed instances of the objects that were actually needed by that user. It's not that you can completely ignore concurrency in your own code, but it's useful to have hibernate's help. If you were to do everything with one session, you would have to do all the concurrency management yourself.
Hibernate can also manage the concurrency if you have multiple application servers talking to a single database. The separate JVMs can't possibly share the same session in this case...
The lifecycle is described in the hibernate documentation (which I'm sure you've seen).
Whenever a request comes from the web client to the server, the first thing you should do is load the relevant objects (see section 10.3) so that you have persistent, not detached entities to deal with. Then, you do whatever operations are required. When the session closes (ie. when the server returns the response to the client), it will write any updates to the database. Or, if your operation involves creating new entities, you'll have to create transient ones (with new) and then call persist() or save() (see section 10.2). That will result in a managed entity -- you can make more changes to it, and hibernate will record those changes when the session closes.
I try to avoid using detached objects. But if I have to (perhaps they're stored in the user's session), then whenever they might need to be saved to the database, you'll have to use update() (see section 10.6). This converts it into a managed object, and so the session will save any changes to the database when it's closed.
Spring makes it very easy to generate a new session for each request. You would normally tell Spring to create a sessionFactory, and then every request will be given its own session. Search for "spring hibernate tutorial" and you'll find several examples.
http://scbcd.blogspot.com/2007/01/hibernate-persistence-lifecycle.html This explains transient, persistent objects.
Also have a look at the Lifecycle interface to know what hibernate does (and it provides hooks at all stages for user to do something)