Showing a “Session Expired” Notice in Seaside

When a Seaside session expires, many of its links become invalid. Sure, you can use the hooks to make certain URLs bookmarkable, but most URLs are session-specific out of necessity. When you click on one after the session expires, Seaside kicks you back to the starting point for the application with no explanation whatsoever. It’d be more polite to tell the user why this happened.

Hat tip to Boris Popov for the initial implementation.

In Seaside, the class WAApplication (via its superclass, WARegistry) knows when an expired session is being accessed, so in order to implement a notice like this, you first have to make your own custom WAApplication subclass.

WAApplication subclass: #MyApplication
  instanceVariableNames: ''
  classVariableNames: ''
  poolDictionaries: ''
  category: 'MySeasideStuff'

When a session expires, the core handling happens in WARegistry. But it gives us a chance to specify the URL path we want to use when something expires. In this case, we’ll tack the keyword “expired” onto the end:

MyApplication>>expiryPathFor: aRequest
  ^aRequest url , '/expired'

Once this is done, you have to register your Seaside application as an instance of MyApplication instead of WAApplication. This is how I did it:

MyRootClass class>>applicationNamed: aString
  | application |
  application := MyApplication named: aString.
  application configuration addAncestor: WARenderLoopConfiguration new.
  application preferenceAt: #rootComponent put: self.
  ^application

Then it’s just a matter of implementing the proper handling in your root component or one of its initial presenters. In my case, my root component holds a task, and the task calls a login component to prompt for username and password. The login component is already set up to display error messages, so we’ll use that here:

MyTask>>initialRequest: aRequest
  super initialRequest: aRequest.
  (aRequest url last: 7) = 'expired'
    ifTrue:
      [loginDialog error: 'Your session has expired. Please sign in again.']

This works the way we intend, but it has a side effect. Since we are using [self session expire] when a user clicks a “logout” link, even legitimate logouts look like a session expiration. We end up showing our expiration message every time somebody logs out, which is not what we want.

Instead, we need to force a redirect after a legitimate logout:

MySession>>logout
  self expire.
  self redirectTo: self currentRequest url.

Now we change our logout callbacks, and we’re done!

MyComponent>>renderContentOn: html
  (html anchor)
    callback: [self session logout];
    with: 'Logout'.

We can test this by logging into the application, clicking the logout link, and then using the back button to get back to an application screen. Clicking any link on the page takes us to the back to the initial screen with the new notice shown.

Dialog showing expired session message

3 Comments

Filed under Seaside

3 responses to “Showing a “Session Expired” Notice in Seaside

  1. Michael Davies

    Thanks for taking the time to write this up so fully, Ken. I’ve not had to implement such a solution yet, but I was always been aware that when the day comes, it was going to take a bit of puzzling out – well not any more!

  2. Sebastian Van Lacke

    Very nice solution. I use it in my apps and works perfectly!
    Now I have other problem related. What should happens when a user goes back with the browser after logout? I have seen that some application like webmails doesn’t allow the user to see the previous pages, I don’t know how they do it. I need that for my application. It is possible to do it from Seaside?

    Thanks you!

  3. It feels like you skipped a few steps.. Where do you create a custom MySession and how do you tell your application to use it?

Leave a comment