Board index JavaServer Faces General Partial AJAX calls don't handle container session timeouts

Partial AJAX calls don't handle container session timeouts

Components, Ajax Framework, Utilities and More.


Posts: 5945
Okay. This is the last thing on my to-do list for the JSF/Primefaces web app that I'm developing. I've done some research and reading of topics on this forum and stackoverflow.com. I'm keeping my eyes and ears open for this topic, because I want a working solution which handles session timeouts, invalidate session, and login. Personally, I don't like Java EE j_security_check. I want a Primefaces form as login page, programmatic security/login (starting/opening a session), users and user groups (in DB/DAO), java EE 6 security, allowing certain user groups access to certain modules and/or menu options, xhtml pages, etc...
Howard

PrimeFaces 5.1, Extensions 2.1.0, Push (Atmosphere 2.2.3)
TomEE+ 1.7.1 (Tomcat 7.0.55), MyFaces Core 2.2.5, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

tandraschko PrimeFaces Core Developer

Posts: 2230
Location: Bavaria, DE

The only solution that i know, is to write an own ExceptionHandler. It's really easy and you can also for example redirect to an ErrorPage etc. within an AJAX request.
Always Bet On Prime (+ Extensions)!

PrimeFaces Extensions: https://github.com/primefaces-extensions
OpenWebBeans: http://openwebbeans.apache.org/
DeltaSpike: http://deltaspike.apache.org/
Personal Blog: http://tandraschko.blogspot.de/


Posts: 5945
Okay, thanks. I know this topic is discussing AJAX calls, but I will need to address non-AJAX calls too. majority of calls in JSF app i'm developing are AJAX, but there are some non-AJAX, too.
Howard

PrimeFaces 5.1, Extensions 2.1.0, Push (Atmosphere 2.2.3)
TomEE+ 1.7.1 (Tomcat 7.0.55), MyFaces Core 2.2.5, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

tandraschko PrimeFaces Core Developer

Posts: 2230
Location: Bavaria, DE

Doesn't matter :) ExceptionHandler is for all requests - not only for AJAX.
Always Bet On Prime (+ Extensions)!

PrimeFaces Extensions: https://github.com/primefaces-extensions
OpenWebBeans: http://openwebbeans.apache.org/
DeltaSpike: http://deltaspike.apache.org/
Personal Blog: http://tandraschko.blogspot.de/


Posts: 5945
Okay, I added NullRestoreViewViewHandler and ViewExpiredExceptionExceptionHandler (package = com.sun.faces) that I found, which was provided by one of guys on website where mojarra is downloaded, but I didn't like how it behaved with the web app, so all I have, at the present is the following in web.xml, but web app not in production yet, so I'm not testing or seeing this exception occur much or xhtml page displayed.

    <error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/viewExpired.xhtml</location>
    </error-page>
Howard

PrimeFaces 5.1, Extensions 2.1.0, Push (Atmosphere 2.2.3)
TomEE+ 1.7.1 (Tomcat 7.0.55), MyFaces Core 2.2.5, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

tandraschko PrimeFaces Core Developer

Posts: 2230
Location: Bavaria, DE

First off all, create your own ExceptionHandler for your app.
Here is a good post in Oleg's blog: http://ovaraksin.blogspot.com/2010/10/g ... ecked.html

AFAIK the web.xml entry will not work for AJAX request but please share it after your tests.

Also it is easy to test a view expiration.
Just configure server side state saving, open a page, restart your servlet container, do a post on this -> View Expired should occur.
Always Bet On Prime (+ Extensions)!

PrimeFaces Extensions: https://github.com/primefaces-extensions
OpenWebBeans: http://openwebbeans.apache.org/
DeltaSpike: http://deltaspike.apache.org/
Personal Blog: http://tandraschko.blogspot.de/


Posts: 5945
Okay. I think I saw Oleg's blog before, and will use it as a reference. Thanks.

I tested the ViewExpiredException per your last response here in this topic, and the following is the result:

1. Glassfish returned the following to web client (internet browser):
HTTP Status 500 -

type Exception report

message

descriptionThe server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: null source
root cause

java.lang.IllegalArgumentException: null source
note The full stack traces of the exception and its root causes are available in the GlassFish Server Open Source Edition 3.1.1 logs.

GlassFish Server Open Source Edition 3.1.1


Glassfish server log had the following:
WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
java.lang.IllegalArgumentException: null source
   at java.util.EventObject.<init>(EventObject.java:38)
   at javax.faces.event.SystemEvent.<init>(SystemEvent.java:71)
   at javax.faces.event.ComponentSystemEvent.<init>(ComponentSystemEvent.java:73)
   at javax.faces.event.PostRestoreStateEvent.<init>(PostRestoreStateEvent.java:73)
   at com.sun.faces.lifecycle.RestoreViewPhase.deliverPostRestoreStateEvent(RestoreViewPhase.java:271)
   at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:257)
   at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
   at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116)
   at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
   at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
   at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
   at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
   at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
   at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
   at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
   at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
   at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174)
   at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
   at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
   at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
   at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
   at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
   at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
   at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
   at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
   at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
   at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
   at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
   at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
   at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
   at java.lang.Thread.run(Thread.java:662)
Howard

PrimeFaces 5.1, Extensions 2.1.0, Push (Atmosphere 2.2.3)
TomEE+ 1.7.1 (Tomcat 7.0.55), MyFaces Core 2.2.5, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache


Posts: 315
Location: Brazil
Hi smithh032772,

I have implemented this in a couple of projects and will summarize it, here is the files/code you will need:

1 - ViewExpiredExceptionExceptionHandlerFactory: https://bitbucket.org/rmpestano/wikifaces-cdi/src/770a710ed03b/wikifaces-cdi/src/main/java/br/com/wikifaces/util/ViewExpiredExceptionExceptionHandlerFactory.java

2 - ViewExpiredExceptionExceptionHandler: https://bitbucket.org/rmpestano/wikifaces-cdi/src/770a710ed03b/wikifaces-cdi/src/main/java/br/com/wikifaces/util/ViewExpiredExceptionExceptionHandler.java

3 - declare the exception handler factory in faces-config:https://bitbucket.org/rmpestano/wikifaces-cdi/src/770a710ed03b/wikifaces-cdi/src/main/webapp/WEB-INF/faces-config.xml

4 - hook the ajax calls with this javascript (place it in a template):
   <script type="text/javascript">
                 jQuery('body').bind('ajaxError', function(event,xhr){
                 if(xhr.status == 666) {
                       alert('Sessao expirada - Entre novamente no sistema.');
                       window.location.replace(xhr.getResponseHeader('redirect'));
                       
                 }
                 });   
           
            </script>


i hope it helps.
Att,

--

Rafael Mauricio Pestano
Graduando em Ciência da Computação - UFRGS


Primefaces 4.x, PF-Ext 1.x, Glassfish 4.x, JBossAS 7.1.2, Tomee, Mojarra: 2.1.x, CODI 1.0.5 on Ubuntu 12.04
Conventions Framework
Blog
@realpestano


Posts: 15076
Location: Cybertron

Here is my example I've just applied to showcase to handle session timeouts and viewexpired exceptions;

ShowcaseExceptionHandlerFactory
package org.primefaces.examples.application;

import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;

public class ShowcaseExceptionHandlerFactory extends ExceptionHandlerFactory {

    private ExceptionHandlerFactory base;
   
    public ShowcaseExceptionHandlerFactory(ExceptionHandlerFactory base) {
        this.base = base;
    }
   
    @Override
    public ExceptionHandler getExceptionHandler() {
        return new ShowcaseExceptionHandler(base.getExceptionHandler());
    }
   
}


ShowcaseExceptionHandler
package org.primefaces.examples.application;

import java.util.Iterator;
import javax.faces.FacesException;
import javax.faces.application.NavigationHandler;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;

public class ShowcaseExceptionHandler extends ExceptionHandlerWrapper {

    private ExceptionHandler wrapped;

    public ShowcaseExceptionHandler(ExceptionHandler wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public ExceptionHandler getWrapped() {
        return this.wrapped;
    }

    @Override
    public void handle() throws FacesException {
        Iterable<ExceptionQueuedEvent> events = this.wrapped.getUnhandledExceptionQueuedEvents();
        for(Iterator<ExceptionQueuedEvent> it = events.iterator(); it.hasNext();) {
            ExceptionQueuedEvent event = it.next();
            ExceptionQueuedEventContext eqec = event.getContext();
           
            if(eqec.getException() instanceof ViewExpiredException) {
                FacesContext context = eqec.getContext();
                NavigationHandler navHandler = context.getApplication().getNavigationHandler();
 
                try {
                    navHandler.handleNavigation(context, null, "home?faces-redirect=true&expired=true");
                }
                finally {
                    it.remove();
                }
            }
        }

        this.wrapped.handle();;
    }
}


faces-config.xml

    <factory>
        <exception-handler-factory>org.primefaces.examples.application.ShowcaseExceptionHandlerFactory</exception-handler-factory>
    </factory>


UI

User is redirected to home page when session timeouts or view expires so following dialog popups at home.xhtml;

<p:confirmDialog header="Oooops!!!" severity="alert"
                         visible="#{not empty param['expired']}"
                         message="View has expired." widgetVar="confirmDlg">
            <p:commandButton type="button" value="Whatever" onclick="confirmDlg.hide()" />
        </p:confirmDialog>


Image
PrimeFaces Lead


Posts: 125

Don`t know if it has been mentioned before, but an elegant solution with phase-listener exists since 2006 -> [1].
Basically you check in phaseListener if in your sessionBean user is logged in.

   @Override
   public void beforePhase(PhaseEvent event) {
      FacesContext fc = event.getFacesContext();
      [...]  // null check for fc, loggin status of your sessionBean, etc..
      //user not logged in:
      NavigationHandler nh = fc.getApplication().getNavigationHandler();
      nh.handleNavigation(fc, null, "login"); // assuming you have "login" as Naviagtion-case in faces-config
}


Had to mention this, because its good to see, when code works for so many years ;)

[1] http://mowyourlawn.com/blog/?p=6
Last edited by ltune on 27 Jan 2012, 14:25, edited 1 time in total.
Busy applying primefaces patches to my local repo at /dev/null

PreviousNext

Return to General