JSP Continuos Scrolling Storing page variables in a session - java

I am have a currently working continuous scrolling pagination,since Http is stateless and there's no way to get back the previous data set from the HttpRequest , is it a good practice to store page variables into a user session? (like adding the id of the last content loaded so that on the next load or next request it would load the next element to it)(Assuming the page are loaded via AJAX) I have implemented it like this.
So for example, if the user search a certain name it would go to a certain action that would perform this.
paginationHelperBean = new PaginationHelper();
if(page == 0 && name != null){
paginationHelperBean.setCurrent_page(0);
} else {
paginationHelperBean.setCurrent_page(page);
}
//Set the paginationBean for display references in JSP later
paginationHelperBean.setPer_page(RESULTS_PER_PAGE);
paginationHelperBean.setTotal_count(profileService.countSearchProfiles(name, paginationHelperBean.getCurrent_page(), RESULTS_PER_PAGE));
paginationHelperBean.setNumber_of_pages();
session.put("profileSearchKey", this.name);
session.put("profileSearchPage", page);
and when the user request for another fragment or data set it would the next item from the previously loaded content it would execute action that does this.
String key = (String)session.get("profileSearchKey");
int page = (Integer)session.get("profileSearchPage")+1;
profiles = profileService.searchProfiles(key, page, RESULTS_PER_PAGE);
session.put("profileSearchPage", page);
So my question is, is it a bad practice to store page related variables in a Session for pagination(eg Search pagination with continuous scrolling?)

In my opinion doing infinite scrolling should be no different than using any ajax call to fetch additional content, you have something that triggers the fetch of additional data (the user scrolling to the bottom of the page) and when it arrives you display it. Also, you can update a JavaScript variable with the last page number fetched so that when the user scrolls to the bottom of the page again, you fetch the next page (no need to store this information in a session variable, e.g. ajax call to /nextPage.jsp?page_number=[valueFromJavaSript]).
Contrast this with storing the last page fetched in a session variable. Imagine your user navigates away from the infinite scrolling page and comes back, what do you expect should happen? Have the jsp page reset the session variable for page number when you navigate back to it, so that subsequent ajax calls fetch the right page number.
Also, if you add more than one infinite scrolling page you'll have several "current pages" stored in session.
I wanted to check how other people are doing it before I submitted my answer, I'm pretty sure that Slashdot used to have infinite scrolling, unfortunately it has a next button now. But I found an article "30+ Great Examples of Infinite Scrolling Websites" here. I used fiddler (http://www.fiddler2.com/fiddler2/) to check if they were passing the page number in the request (i.e. not storing it in session), and the ones I checked are (either page number, offset, or something similar, but the information is clearly going in the request).

is it a good practice to store page variables into a user session:No.As session attributes is not thread safe .AS it is accessible to only those with access to specific HttpSession.For better see Request and session in Servlet
The code you have written can pass through sychnonization issue.In the case when one thread is getting the value that it has set previously there will be chance that another thread has modified and set different value .So when first thread tries to get value though it may get value but it might not be right value.
The code
session.put("profileSearchKey", this.name);
session.put("profileSearchPage", page);
suppose thread A put value for profileSearchKey and profileSearchPage.When thread A tries to get value for attribute name profileSearchKey and profileSearchPage the value of this.name and page may be modified by another thread.So,on getting value there synchronization issue will arrive.

Related

I want my old data even I refresh the webpage

First Question:
Consider, I am filling any form then I refresh that page,what I want is what ever I fill in that page should not clear not only refresh page even if network problem occurred during filling the form.
Second Question:
If I login with any username and password then I fill in form and if network problem occurrs during filling the form then I go to another machine and login with same username password, I want whatever I entered In previous system should be show in this machine.
Sorry for my poor english, please tell any idea.
You should try and leverage client side storage. This will allow you to store the user data on the local browser. Here is an article on this http://www.html5rocks.com/en/tutorials/offline/storage/
I hope it helps
Fixing the following requires:
1 - Background worker on the client side that posts the data to the server .
Worker;
//or
window.setInterval();
2 - A banner or a status div showing the user that he is connected or disconnected.
var isOnline = window.navigator.onLine;
3 - Notify the user about reloading the page.
window.addEventListener("beforeunload", function (e) { alert('Your leaving...') });
Your first question has a pretty simple and straightforward solution: you'd want to save the data on the local machine, using something like cookies or localStorage.
For your second question, you'd need a much more complicated solution. Basically, you need to constantly persist the view data (input values, etc.) to the server for "safekeeping", since you assume the machine might crash at any given moment.
So your backend should support saving "temp form data", and whenever a user enters the relevant screen, you need to check for such temp form data on the backend, and populate the form accordingly. This will probably cause lots of edge cases and isn't trivial IMO.

playframework form inputs with array names

I'm trying to submit a form with a few textareas like this:
<textarea name="criticism[]" rows="3" cols="5"></textarea>
The textarea needs to have an array as the name because there can be an unlimited number of them on the page, added by the user with js.
The values are passed to the controller correctly.
In the controller I do params.flash() which seems to add the values to the seession, since if I do ${flash} in the template they are printed to the screen. However, I can't access them in any way. ${flash.criticism} returns null, and ${flash.criticism[x]} will return an out of bounds error.
Am I missing anything syntax wise?
Cheers :)
The flash scope is only available to the current request and the next one. To put something in the session use session.
However flash and session are not intended to store values. They are cookie limited to 4kb. To store something use the db and/or the cache
If you want to re-render your values in the next page, just pass the string array as a 'criticism' parameter to the next render method and use it in your template with ${criticism[x]}

Preventing back button clicks in browser

I understand that this question is asked over and over again, but I want a way to handle back button clicks on the server side (like banking applications).
When the user clicks on the back button, the page should be invalid and the user should be asked to start all over again.
Can you direct me to some tutorials on this?
The simplest way I've seen this solved is as follows.
Every page is served up with a unique ID/token.
That unique ID is always submitted when submitting any forms, and tracked on the server as being "used".
If the user ever clicks "back" and re-submits the same form, the server checks the unique ID... notices that it is a duplicate and then ignores the submission.
Note this won't physically stop a user from going "back", but if the last action was "transfer $1,000,000 dollars!" - the user won't accidentally transmit 2 million.
Make pages not cachable
track the user route server side, if she is visiting the visited page which she isn't supposed to revisit by back, in a session data may be.
check to see if she is requesting the visited resource then handle accordingly
Filter is the best place to do
Instruct page to use no cache.
Add to the head element of the page
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
There are two problems you need to solve here.
The first is how browsers typically handle the back button. You should use a POST request to get to the page that the back button should not have access to. Most browsers will use a local cache for GET requests,, so if you do a GET, your server simply won't be accessed at all. A POST request will however typically perform a new request. Many browsers will also warn the user, and show a dialog box saying i.e. "Are you sure you want to send the form again?". So by using a POST, you increase the likelihood that every page load of that page will perform a new request to your server.
You may also be able to use a GET request where your server returns HTTP headers that makes browsers not load the page from the cache. Experiment with this.
The second problem is to make sure you invalidate duplicate requests server side. The first solution I can think of is to generate a token that you submit with the form and store in a database on every request. If a request is performed with a token that already is stored, you can invalidate the request. Perhaps there are better techniques, but I'll leave that as an exercise for the reader ;)
I also searched for this , and after all i found a little trick i think it may for your.
Every page your have an javaScript function that call to server with
ajax to check whether this page is available at that time.
In the server side you keep the availability (with the session).
If not redirect the page as you wish .

How to start a new session if a user click on the new tab in IE or mozilla on websphere portal?

I have one "user search" portlet on the home page of one application running on websphere portal server which displays the matching user records as per the search criteria filled in the search form. I have a requirement to have a "back to search input" link on the results page which on click should show the filled form on the input jsp.
The issue I am facing is if I open the application in two different tabs of same IE browser and start giving some search criteria and submit and at same time search for some other input from the other IE tab (in the same browser) and then go back to previous tab and click on "back to search input" link, instead of showing me the first input it will show me the input I entered in the next IE tab.
I am setting and getting the bean (form bean) through portlet session. But in the two diff tabs of the same IE it will be the same user session (and may be the same portlet session.)
How can I fix it so the two tabs save their search results independently?
The one thing to note here is I can access this "user search" application without logging in. So it must be taking the default portlet session in this case. What will happen once I login and then search; will it overwrite the portlet session and http session?
Basically your issue stems from the fact that your session is the same in both tabs so any data you store you can't expect to be different between tabs unless you store it as such. I would assign each search an id and store them in a collection in your session. Then when you draw your "back to search input" button add the search id such that you can pull the correct search out when building the input page.
Alternatively you could save server memory by posting the search as a query string on the return to search link rather than storing it in session.
What you describe is a fairly common problem faced by web app -- I think the official term is conversations -- which is the need to support something in-between the session scope and the request scope.
Some web framework support this concept, some not. The portlet specification does not support that out-of-the-box (Maybe there's something specific in websphere though).
I think one way to re-create the support for conversations, is to store a conversation id in the HTML generated. This way you can have an ID that is be per-tab / window. If suddenly a request receive an old ID, you know it comes from either an old page (if the user used the back button), or another tab.
That's ony a rough sketch. I'm pretty sure there a good resources on the web about this problem, otherwise spawn another question.

Do you always REDIRECT after POST? If yes, How do you manage it?

Say, you are submitting a form, which affects your database (adding records/ deleting them/ updating them) and this is how your request looks like:
POST /application/action=update
Now, say, you are done with your update, so you would like to take the user to the home page.
Response.sendRedirect /application/action=home
This works wonderfully well. User is sent a redirect after POST, so even if the user tries to refresh the page by hitting F5, you are good. However, this will not work if you did this:
requestDispatcher.forward(/application/action=home)
Given that there is a scenario where you have to display different kinds of error / success messages after you are done with your update, you are most likely doing a forward after POST. In such a scenario, how do you avoid update actions from happening twice?
I find it rather amusing that many secure sites (banks) / payment gateways tend to inform the user by placing text on screen, such as "Please don't press back / refresh buttons".
Is there no better way to handling this? Other than requesting the user not to press these buttons? When I last checked, there was something called the 'Vertical Response Cache'. A Filter that would identify uniqueness of your request in a session and tries to send a cached response if the request is duplicate. Are there any simpler ways to solving this classic problem?
Here is a link to the vertical response cache solution I was talking about: http://www.fingo.info/en/articles/_1.html. I am, However, not sure as to how well this really works.
Yes, I believe that you should redirect after a POST, with the exception of API requests. Without doing this not only do you have to worry about getting duplicate POSTs when the user uses the back button, but the browser will also give the user annoying dialogs when they try to use the back button.
Response.sendRedirect works in practice, but tecnically speaking this is sending the wrong HTTP response code for this purpose. sendRedirect sends a 302, but the correct code to use to transform a POST into a GET is 303. (most browsers will treat a 302 just like a 303 if they get it in response to a POST, however)
In general you want the redirect to send the user to whatever view will display the effect of their change. For example, if they edit a widget, they should be redirected to the view of that widget. If they delete a widget, they should be redirected to the view that the widget would have appeared in when it existed (perhaps the widget list).
Sometimes it's nice to have a status message to further drive home the fact that an action occurred. A simple way to do this is to have a common parameter to your views that, when set, will display an action completed message. eg:
/widget?id=12345&msg=Widget+modified.
Here the "msg" parameter contains the message "Widget modified". The one downside to this approach is that it may be possible for malicious sites to give your users confusing/misleading messages. eg:
/account?msg=Foo+Corp.+hates+you.
If you're really worried about this you could include an expiring signature for the message as an additional parameter. If the signature is invalid or has expired, simply don't display the message.
The best solution to solve the problem of showing status messages to the users after a POST to GET redirect is to use user sessions.
How
Add attributes to user session with value as set of messages to be displayed. for eg.
userSession.put("success_messages", new HashSet<String>(){"Success", "Check your account balance"});
userSession.put("warning_messages", new HashSet<String>(){"Your account balance is low. Recharge immediately"});
And have a filter which scans the user session for these particular attributes and outputs the messages. The filter should delete the attributes after reading once, as the status messages are generally displayed only once.
One thought that I've had is to embed a unique ID (probably a random string) as a hidden form field in the form that is being POST-submitted. The ID string can be put in the database as a "transaction ID". Now, when you go to update the database, first check whether there's an existing record with the submitted transaction ID, and if so, assume it's a duplicate and don't change the database.
Of course, as I said, this is just a thought. I don't know what methods are actually used in practice. (I suspect that a lot of less-critical sites just ignore the problem and hope their users will be smart... a losing proposition if I ever saw one ;-)
EDIT: as pointed out in the comments, storing transaction IDs in the database might take up a lot of space, but if that's an issue, you could keep an in-memory cache of all transaction IDs processed in the last 5 minutes/1 hour/1 day/whatever. That should work unless you're up against a determined hacker...
I find it rather amusing that many secure sites (banks) / payment gateways tend to inform the user by placing text on screen, such as "Please don't press back / refresh buttons".
some people find its better to "disable all Back, Refresh event on this critical pages";
I'm not sure if this is good or not.
But your addressed solution "vertical response cache" sounds nice
Its a little non-obvious but:
create a keyed-object in the user session.
the value is a Request + java Future for the result
return immediately with a client-side redirect.
while the client-side redirect is being handled, have a worker thread work on producing the answer.
So by the time the client browser completes the redirect, getting the new page's images, etc... the results are waiting for the user.
The alternative is to make the user painfully aware of how long the database is taking.
Security Update (2011 Jan 24 ) :
The key is vulnerable to attack since it is part of the response to the client, so
Generate a random key
Use user's session id as a salt to create a SHA-1
Store both the random key and the SHA-1 in the database with (, ) as the primary key. (no separate indexing on the RANDOMKEY.
Use both RANDOMKEY and the SHA-1 as the db lookup.
Do not store the Session Id (avoid privacy issues with being able to corollate many entries to the same user)
Expire the results after 2-3 days. ( Allows a daily batch job to do the clean up and avoids creating problems for user sessions that are semi-long lasting )
This method requires any hacker to know both the session id and the random key.
This approach may seem overkill, but a redirect-hardened mechanism can be used for situations like password resets.
If you are working with java server side scripting and also using struts 2 then you refer this link which talks about on using token .
http://www.xinotes.org/notes/note/369/
A token should be generated and kept in session for the initial page render, when the request is submitted along with the token for the first time , in struts action run a thread with thread name as the token id and run the logic whatever the client has requested for , when client submit again the same request, check whether the thread is still running(thread.getcurrentthread().interrupted) if still running then send a client redirect 503.
Please look at the ExecuteAndWaitInterceptor of struts 2code, the logic of this combined with token will help out fast click

Categories