DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
11 Monitoring and Observability Tools for 2023
Learn more

The Art of Gracefully Handling Session Timeouts with ExtJS

Jorge Ramon user avatar by
Jorge Ramon
·
Apr. 28, 11 · Interview
Like (1)
Save
Tweet
Share
13.74K Views

Join the DZone community and get the full member experience.

Join For Free

A very common solution to gracefully handling session timeouts consists of notifying your user that her session is about to time out, and asking her to take an action in order to prolong the session. In this article I will walk you through one implementation of this important usability and stability pattern utilizing the ExtJS JavaScript library.

The key to this approach is to divide the session duration into two distinct intervals, let’s call them t1 and t2, where t1 is the time the user has been inactive, until we alert her that her session is about to terminate, and t2 is a short grace period we will give the user to perform an action that will extend her session.

If we define Session Duration = t1 + t2, we’re looking at a logical sequence like so:

  • Start a “session timeout” timer
  • When the timer reaches t1, we alert the user and ask her if she wants to extend the session
  • If the user does not extend her session and t2 is reached, we terminate the session
  • If the user extends her session, we reset the session timer and jump back to step 2

As this approach relies on calculating the time the user has been inactive, the manner we define user inactivity in very important. In order to keep the sample code of this article simple, we will assume that the user is inactive if her interaction with the application is not generating requests to the server. For a more solid implementation you might want to consider additional events such as using the mouse, scrolling, etc. But this, of course, depends on the type of system you’re building.

Let’s now look at what it takes to implement this approach.

Starting a session timeout timer upon completing an AJAX request

As we’re assuming that the user is inactive if she is not generating requests to the server, the most important part of our implementaiton is a piece of code we will run upon completing every AJAX request:

 

Ext.Ajax.on('requestcomplete', function (conn, response, options) {

if (options.url !== App.SESSION_KILL_URL) {
// Reset the client-side session timeout timers.
// Note that you must not reset if the request was to kill the server-side session.
App.sessionAboutToTimeoutPromptTask.delay(App.toMilliseconds(App.SESSION_ABOUT_TO_TIMEOUT_PROMT_INTERVAL_IN_MIN));
App.killSessionTask.cancel();
} else {
// Notify user her session timed out.
Ext.Msg.alert(
'Session Expired',
'Your session expired. Please login to start a new session.',
function (btn, text) {

// TODO: Here you need to make sure you kill the server-side session state.

if (btn == App.BTN_OK) {

// TODO: Show logon form here.
}
}
);
}
});

This requestcomplete event handler consists of two branches. The first branch will run after we request any resource, except the page that will terminate the server-side session. Inside this branch we utilize a delayed task – App.sessionAboutToTimeoutPromptTask – to keep track of the duration of the session, and a delayed task – App.killSessionTask – that is responsible for triggering the request to terminate the server-side session. I will explain how these delayed tasks work in a minute.

The second branch of the event handler will run after we request the page that will take care of terminating the server-side session. What we need to do in this case, is notify the user that the session was terminated:

Ext.Msg.alert('Session Expired','Your session expired. Please login to start a new session.',function (btn, text) {
// TODO: Here you need to make sure you kill the server-side session state.
if (btn == App.BTN_OK) {
// TODO: Show logon form here.
}
});

I use an Ext.Msg.alert for this example, but you can modify this area to fit the needs of your application.

Let’s now look at the delayed tasks.

Notifying the user that her session is about to time out

In order to let the user know that her session is about to time out, we will use a delayed task like so:

App.sessionAboutToTimeoutPromptTask = new Ext.util.DelayedTask(function () {

Ext.Msg.confirm(
'Your Session is About to Expire',
String.format('Your session will expire in {0} minute(s). Would you like to continue your session?',
App.GRACE_PERIOD_BEFORE_EXPIRING_SESSION_IN_MIN),
function (btn, text) {

if (btn == App.BTN_YES) {
// Simulate resetting the server-side session timeout timer
// by sending an AJAX request.
App.simulateAjaxRequest();
} else {
// Send request to kill server-side session.
App.simulateAjaxRequestToKillServerSession();
}
}
);

App.killSessionTask.delay(App.toMilliseconds(
App.GRACE_PERIOD_BEFORE_EXPIRING_SESSION_IN_MIN));
});

In this task we utilize an Ext.Msg.confirm to notify the user about the timeout and ask her to push the Yes button in order to extend her session. Upon clicking the Yes button, our code will execute an AJAX request that will restart the server-side session. Clicking the No button will execute an AJAX request that will terminate the server-side session immediately.

Notice how while we wait for the user’s response, we also run the App.killSessionTask delayed task, which will terminate the server-side session after the grace period if the user did not respond to our prompt.

It is important that we restart or terminate the session on the server side. As session state includes both client and server variables, we need to make sure that when the session terminates or is extended, these variables are correctly handled on both sides of our system.

The last piece of our timeout engine is App.killSessionTask , the delayed task that will trigger a request to terminate the server-side session after the grace period:

App.killSessionTask = new Ext.util.DelayedTask(function () {
App.simulateAjaxRequestToKillServerSession();
});

Now that we have the main pieces in place, let’s take a look at the complete solution:

Ext.onReady(function () {

Ext.ns('App');

App.BTN_OK = 'ok';
App.BTN_YES = 'yes';
// 1 min. before notifying the user her session will expire. Change this to a reasonable interval.
App.SESSION_ABOUT_TO_TIMEOUT_PROMT_INTERVAL_IN_MIN = .25;
// 1 min. to kill the session after the user is notified.
App.GRACE_PERIOD_BEFORE_EXPIRING_SESSION_IN_MIN = 1;
// The page that kills the server-side session variables.
App.SESSION_KILL_URL = 'kill-session.html';

// Helper that converts minutes to milliseconds.
App.toMilliseconds = function (minutes) {
return minutes * 60 * 1000;
}

// Helper that simulates AJAX request.
App.simulateAjaxRequest = function () {

Ext.Ajax.request({
url: 'foo.html',
success: Ext.emptyFn,
failure: Ext.emptyFn
});
}

// Helper that simulates request to kill server-side session variables.
App.simulateAjaxRequestToKillServerSession = function () {

Ext.Ajax.request({
url: App.SESSION_KILL_URL,
success: Ext.emptyFn,
failure: Ext.emptyFn
});
}

// Notifies user that her session is about to time out.
App.sessionAboutToTimeoutPromptTask = new Ext.util.DelayedTask(function () {

console.log('sessionAboutToTimeoutPromptTask');

Ext.Msg.confirm(
'Your Session is About to Expire',
String.format('Your session will expire in {0} minute(s). Would you like to continue your session?',
App.GRACE_PERIOD_BEFORE_EXPIRING_SESSION_IN_MIN),
function (btn, text) {

if (btn == App.BTN_YES) {
// Simulate resetting the server-side session timeout timer
// by sending an AJAX request.
App.simulateAjaxRequest();
} else {
// Send request to kill server-side session.
App.simulateAjaxRequestToKillServerSession();
}
}
);

App.killSessionTask.delay(App.toMilliseconds(
App.GRACE_PERIOD_BEFORE_EXPIRING_SESSION_IN_MIN));
});

// Schedules a request to kill server-side session.
App.killSessionTask = new Ext.util.DelayedTask(function () {
console.log('killSessionTask');
App.simulateAjaxRequestToKillServerSession();
});

// Starts the session timeout workflow after an AJAX request completes.
Ext.Ajax.on('requestcomplete', function (conn, response, options) {

if (options.url !== App.SESSION_KILL_URL) {
// Reset the client-side session timeout timers.
// Note that you must not reset if the request was to kill the server-side session.
App.sessionAboutToTimeoutPromptTask.delay(App.toMilliseconds(App.SESSION_ABOUT_TO_TIMEOUT_PROMT_INTERVAL_IN_MIN));
App.killSessionTask.cancel();
} else {
// Notify user her session timed out.
Ext.Msg.alert(
'Session Expired',
'Your session expired. Please login to start a new session.',
function (btn, text) {

if (btn == App.BTN_OK) {

// TODO: Show logon form here.
}
}
);
}
});

// The rest of your app's code would go here. I will just simulate
// an AJAX request so the session timeout workflow gets started.
App.simulateAjaxRequest();
});

What do you think? Want to give it a try?

From http://miamicoder.com/2011/the-art-of-gracefully-handling-session-timeouts-with-extjs

Session (web analytics) Timeout (computing) Requests Task (computing)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Understanding and Solving the AWS Lambda Cold Start Problem
  • Important Data Structures and Algorithms for Data Engineers
  • Java Code Review Solution
  • Java REST API Frameworks

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: