Session Destroyed; Print Message in JSP and Servlets - java

When a session has been destroyed, how do I print a message on a JSP that notifies the user? I'm using a class that implements HttpSessionListener.

When the session is destroyed, you can't do anything from the server side on anyway. At the point of session destroy there is no guarantee that you have valid request/response objects at your hands. Your best bet is to handle it fully at the client side, using for example JS. You can get the remaining lifetime of the current session by HttpSession#getMaxInactiveInterval() and you can use JavaScript's setTimeout() to run a function after some time.
<script>
setTimeout(function() {
document.getElementById('message').innerHTML = 'Session has timed out!';
}, ${pageContext.session.maxInactiveInterval} * 1000); // It returns seconds, but setTimeout expects milliseconds.
</script>
<div id="message"></div>

Related

Start performing an action every minute after getting to a web page

I am developing a Java web application using Spring.
What I would like to do is that after the user gets to a page, the code starts running a function every 10 seconds, keeping track on the time the last action was performed.
I tried to do so with a Scheduler but it starts running immediately - and not only after the user gets to a page.
#Scheduled(fixedRate = 60000)
public void run(String param) {
//just an example of action to be performed repeatedly
System.out.println("Previously performed action was " + new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(previousActionTime)) + " with " + param);
//update previousActionTime
previousActionTime.setSeconds(previousActionTime.getSeconds() + 10);
}
Moreover I don't know what it is a convenient way to store the time when the last action automated action was performed.
The scheduler should be somehow activated when browsing to the page:
#RequestMapping(value = "/hellopage", method = { RequestMethod.POST, RequestMethod.GET })
public String hellopage(HttpServletRequest request, HttpServletResponse response) {
// Activate scheduler
run(request.getParameter("param1"))
...
}
The scheduler (or whatever performs the automated actions) should stop as soon as the user gets again to the same web page triggering the automated actions and should run in background not blocking any other code from execution (to be precise, I cannot simply put a while loop with Sys.sleep in the function mapped to the page URL request why the page should do other things)
Any help?
Consider using ScheduledExecutorService.scheduleAtFixedRate for this as the Spring scheduler are independent of any users' request (which you have already observed and noted in question).
You may use shutdownNow to terminate the scheduler once the users' session is no longer valid / a new request is received. To achieve this you could maintain cache of previous executor(s) with user id (or any relevant information) to identify the instance which should be invalidated.
As an alternative you could use Timer and TimerTask if more fine grained control is required (however not recommended as noted here)
There are two common ways of achieving this.
The first is to run your timer client-side, in JavaScript, and then runs an AJAX/websocket/whatever call. This has many advantages - once the user navigates away from your site, the timer will stop, and you're not tying up server-side resources so your application will scale much more cleanly. This is by far the cleanest solution if your timer is linked to a single user.
The second is to use a message queue; pop a message on the queue and have an asynchronous process checking those messages, ideally aggregating multiple client sessions in a single database request. You need to figure out how to detect sessions timing out and remove the message from the message queue.
This approach is best when your timer is looking at information that's not tightly connected to the current user.

How do I renew a spring session?

I have a web application running spring MVC on Websphere, and I am trying to implement a session expiration confirm. I now where to redirect if they choose to log out but I don't know how to renew a session if the choose to do that.
So far I understand I am using jQuery and ajax to send a request somewhere to the server but do not know where (the url), nor the arguments or the expected response. Does anyone know have a general idea how I find this out? Is it a standard function of spring session or am I going to have to write a custom function to fix this?
I was able to figure it out by combining information from multiple sources out on there. I came up with the following code:
function timeoutMessage(){
var popupdate = new Date();
var renewSession = confirm('Your Session is about to expire!\n\nYou will be logged out in 2 minute.\nDo you want to stay signed in?');
if(renewSession){
var response = new Date();
if(response - popupdate > 120000){
alert("Response took too long, current session has ended. \nRedirecting to login.");
}else{
pingServer();
resetTimeout();
}
}else{
window.location.href = "{app logout url}";
}
}
function pingServer(){
jQuery.ajax({url: "{valid server page url}",type: "HEAD",complete: function (XMLHttpRequest, textStatus) {}});
}
function resetTimeout(){
window.setTimeout(function(){timeoutMessage();},1080000);
}
$(document).ready(function()
resetTimeout();
});
The function sets a timer that coincides with two minutes before the session timeout. Most sites will offer most of the above code but what that in the pingServer() function; in order to extend the session on the server you can send a simple ajax call of type 'HEAD' to the server without interrupting the applications primary flow. It is seen as an action by the server toward the session and thus resets/renews the session's timeout. You don't need to do anything with the server response as seen in the code; just as long as you send the request the session timeout will be reset/renewed.
I hope this helps. It took me a while to completely piece together.
Why not set a bigger number for max_inactive_interval so the session will last longer?
Spring Session automatically renews if the user is active. Take a look at the table created by Spring Session for storing the session data: there is a column max_inactive_interval which basically means that the session will only expire if the user is not active for that interval of time.

How to prevent data loss when user session expired?

I have a web app, which session expired in 30 minutes. At client side, when the user tries to interact with server and server detects user session is expired, the client will simply redirects to log in page.
The problem is, user may not know his session is expired, and keep working on client side(say, writing a note, or edit something), when he tries to send the changes to server, bad thing occurs, the browser redirects to log in page and user data is lost.
Any idea on how to prevent data loss when user session expired? Thanks.
If the user is writing a note or editing anything on his session the session should not expire.
You can easily send a keep-alive message to the server for every 5th (or even more) character he presses keeping the session alive.
Have you considered raising the session timeout? 30 minutes is pretty low. It might take some users longer than that to fill in one Web form, even if they are working continuously. My session timeouts are 8-10 hours. The only reason to make them shorter is to save space at the server. Is that a problem that you really have?
You will need to provide some sort of support in the server. A good implementation would be a servlet called every 31 minutes of user "iddleness" (to avoid revalidating session which would cause it to never expire) from the client via an AJAX call.
If the session id changes in the server it would reply so and the client could show some sort of message.
An easier implementation would be firing some kind of reload every 31 minutes of inactivity, so that the user is redirected to the login page. That wouldn't need any extra support in the server, but would be less user-friendly.
There are reasons to have short session time out.
Security
Data Theft
If you don't need those, just extend the session time out.
OR,
Insert AJAX calls every where to renew the session.
In the HTML you can have an alert after 29 minutes (JS setTimeout), and after 30min - 10s (meta refresh) do a jump to a "session expired" page.
Session only expire if user will not done any action till 30 minutes.
If user did not do anything till 30 mins, then there should not be any data lost by idel session expired coz there is nothing to retain.
Please don't forget to add {{ csrf_field() }} in your form.
I had the same problem. Then, I put crsf token here! And, it works fine now. Here is my code:
<form method="post" action="{{route('customer.store')}}" class="form-horizontal" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="row">
//Your code here
</div>
</form

tracking Httpsession user session timeout

I am trying to monitor user session and alert user that the session is about to expire.
Anysolution either client side or server side will work for me , i just need to inform to the client that his session would be expired before session expires
Session timeout counter starts as soon as it gets idle. if there is a request from user [even if its ajax] then it won't time out. So you can maintain a counter on client side making sure that user is left idle for your webpage.
Update:
Add a Filter that will intercept each request and will update lastAccessedTime pass it to client in the form of some hidden parameter or cookies or something.. and use javascript to detect the timeout
Also See
detecting-idle-time-in-javascript-elegantly
The timeout should definitely be handled using a Javascript type of timer. Now, when you have a request on the server you should reset the timeout on client (the session timeout on the server will be automatically updated using the session tracking option of the server).
Now in another case that you perform actions on the client (but with no server interaction) then you should reset the timeout on the client using javascript, and use a dummy hidden internal frame posting some dummy form on a dummy page on the server. This would update the session timeout of the user on the server side.
You can also implement the last dummy thing functionality also with an ajax call on a dummy page. This might be a better solution.
Hope this helps you

Browser timeout and page cannot be displayed

I have written within a JSP page to have Thread.sleep() for more than 1 hour. The JSP is deploayed on WebLogic server 9.2. I am trying to check the browser timeout and page cannot be displayed error.
As per the below documentation, the default timeout for IE6 is 60 seconds. However, I was testing the above JSP and did not get any timeout or page cannot be displayed even beyond 30 minutes. I am doing this to the user experience for a requirement that can take long time to execute. Thanks.
http://support.microsoft.com/kb/181050
If you want to run and control a long-running process, better let it run in its own Thread instead of the request's Thread. Store a reference to this Thread in the session scope so that the client can use ajaxical requests (using the same session!) to request the server side for the current progress (and automagically also to keep the session alive so that it doesn't timeout).
Here's a basic example of such a servlet:
package mypackage;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RunLongProcessServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
if ("XMLHttpRequest".equals(request.getHeader("x-requested-with"))) {
LongProcess longProcess = (LongProcess) request.getSession().getAttribute("longProcess");
response.setContentType("application/json");
response.getWriter().write(String.valueOf(longProcess.getProgress()));
} else {
request.getRequestDispatcher("runLongProcess.jsp").forward(request, response);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
LongProcess longProcess = new LongProcess();
longProcess.setDaemon(true);
longProcess.start();
request.getSession().setAttribute("longProcess", longProcess);
request.getRequestDispatcher("runLongProcess.jsp").forward(request, response);
}
}
class LongProcess extends Thread {
private int progress;
public void run() {
while (progress < 100) {
try { sleep(1000); } catch (InterruptedException ignore) {}
progress++;
}
}
public int getProgress() {
return progress;
}
}
..which is mapped as follows:
<servlet>
<servlet-name>runLongProcess</servlet-name>
<servlet-class>mypackage.RunLongProcessServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>runLongProcess</servlet-name>
<url-pattern>/runLongProcess</url-pattern>
</servlet-mapping>
And here's a basic example of the JSP (with a little shot jQuery, an ajaxical JS framework which I by the way greatly recommend):
<!doctype html>
<html lang="en">
<head>
<title>Show progress of long running process with help of Thread and Ajax.</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(init);
function init() {
if (${not empty longProcess}) {
$.progress = 0;
checkProgress();
}
}
function checkProgress() {
$.getJSON('runLongProcess', function(progress) {
$('#progress').text(progress);
$.progress = parseInt(progress);
});
if ($.progress < 100) {
setTimeout(checkProgress, 1000);
}
}
</script>
</head>
<body>
<form action="runLongProcess" method="post">
<p>Run long process: <input type="submit"></p>
<p>Current status: <span id="progress">0</span>%</p>
</form>
</body>
</html>
Open it at http://localhost:8080/yourcontext/runLongProcess and click the button.
If this is a really, really long running process, you may improve "efficiency" by increasing the ajax intervals to 5 seconds or so so that the server doesn't feel getting DDOS'ed ;)
Hope this helps.
Your page may have returned some amount of data (such as headers) which convinced IE to leave the socket open and wait for more data.
To see what's actually going on, try running Wireshark (or Fiddler) on the machine with IE. You could also telnet to port 80 on your server and request the page manually (type in GET /path/to/your.jsp HTTP/1.0 followed by 2 line breaks).
I think you need to use AJAX technology to solve this kind of long operation problem, ask Server to maintain a connection over an hour is not an efficient decision.
What if more than hundred users connect to your server?
The concept of a simple AJAX solution is like this:
you start a timer using Javascript's setTimeInterval().
in timer's invocation, you compose a URL and use a XmlHttpRequest to request your server.
this async request will trigger(or just ask) a progress of a server-side back-end service.
every time the JS timer ticks, server-side should respond the progress(or result) to give user a visual response.
I think this is a better way to do your job. you can build this mechanism by your own or use some existing AJAX Framework like GWT, DWR even ZK to accomplish it.
Typically the "this page cannot be displayed" message occurs when the browser fails to make a connection to the host. In the scenario you've presented, the browser manages to make a connection and holds that connection open until the connection finishes or the server side hangs up.
If you are trying to test the functionality of the browser, you'll need to play some tricks on the network to have the connection fail. For example, firewall port 80 on your server such that it doesn't respond to any packets sent its way. The browser should leave the socket open for 60 seconds waiting for a response. When the response doesn't arrive the "this page cannot be displayed" message should be displayed.
Thanks for all your answers. We have a requirement where the users can wait longer. We are limiting the number of parallel requests by configuration in server (using Work Manager in WebLogic). If the number of parallel requests is more than the max no of threads, the requests are placed in queue. My questions if if the browser times out after 60 seconds as specified in the link - http://support.microsoft.com/kb/181050. We have done few tests and observing that page cannot be displayed message is displayed after 1 hour. We also checked response headers and no response content or response headers are returned back. So, we are not sure if either the server is timing our or browser is timing out. And also would like to check if IE6 times out after an hour or after 60 seconds as per the documentation.
Thanks

Categories

Resources