Partial AJAX calls don't handle container session timeouts

UI Components for JSF
smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

26 Jan 2012, 22:20

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 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

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

tandraschko
PrimeFaces Core Developer
Posts: 3979
Joined: 03 Dec 2010, 14:11
Location: Bavaria, DE
Contact:

26 Jan 2012, 23:31

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.
Thomas Andraschko

PrimeFaces | PrimeFaces Extensions

Apache Member | OpenWebBeans, DeltaSpike, MyFaces, BVal, TomEE

Sponsor me: https://github.com/sponsors/tandraschko
Blog: http://tandraschko.blogspot.de/
Twitter: https://twitter.com/TAndraschko

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

26 Jan 2012, 23:47

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 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

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

tandraschko
PrimeFaces Core Developer
Posts: 3979
Joined: 03 Dec 2010, 14:11
Location: Bavaria, DE
Contact:

26 Jan 2012, 23:48

Doesn't matter :) ExceptionHandler is for all requests - not only for AJAX.
Thomas Andraschko

PrimeFaces | PrimeFaces Extensions

Apache Member | OpenWebBeans, DeltaSpike, MyFaces, BVal, TomEE

Sponsor me: https://github.com/sponsors/tandraschko
Blog: http://tandraschko.blogspot.de/
Twitter: https://twitter.com/TAndraschko

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

27 Jan 2012, 00:04

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.

Code: Select all

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

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

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

tandraschko
PrimeFaces Core Developer
Posts: 3979
Joined: 03 Dec 2010, 14:11
Location: Bavaria, DE
Contact:

27 Jan 2012, 00:07

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.
Thomas Andraschko

PrimeFaces | PrimeFaces Extensions

Apache Member | OpenWebBeans, DeltaSpike, MyFaces, BVal, TomEE

Sponsor me: https://github.com/sponsors/tandraschko
Blog: http://tandraschko.blogspot.de/
Twitter: https://twitter.com/TAndraschko

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

27 Jan 2012, 02:14

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):

Code: Select all

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:

Code: Select all

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 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

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

User avatar
kwintesencja
Posts: 316
Joined: 08 Feb 2010, 20:33
Location: Brazil

27 Jan 2012, 12:34

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/wikifac ... ctory.java

2 - ViewExpiredExceptionExceptionHandler: https://bitbucket.org/rmpestano/wikifac ... ndler.java

3 - declare the exception handler factory in faces-config:https://bitbucket.org/rmpestano/wikifac ... config.xml

4 - hook the ajax calls with this javascript (place it in a template):

Code: Select all

   <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


Primefaces 5.x + JavaEE7(Glassfish 4.x and Wildfly 8)
Conventions Framework
Blog
@realpestano

cagatay.civici
Prime
Posts: 18616
Joined: 05 Jan 2009, 00:21
Location: Cybertron
Contact:

27 Jan 2012, 13:56

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

ShowcaseExceptionHandlerFactory

Code: Select all

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

Code: Select all

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

Code: Select all

    <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;

Code: Select all

<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

ltune
Posts: 125
Joined: 20 Jul 2011, 20:25
Contact:

27 Jan 2012, 14:23

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.

Code: Select all

	@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

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 15 guests