Tiempo de espera de la sesión y manejo de ViewExpiredException en la solicitud ajax de JSF / PrimeFaces


Encuentro que este artículo es útil para solicitudes no ajax ¿Cómo manejar la expiración de la sesión y la ViewExpiredException en JSF 2? pero no puedo hacer uso de esto cuando estoy enviando usando una llamada AJAX.

Supongamos que en un diálogo de primefaces, estoy haciendo una solicitud post usando AJAX y la sesión ya se ha agotado. Veo que mi página se atasca.

Cómo arreglar este tipo de escenario de tal manera que cuando publico usando AJAX, podría redirigirlo a mi página de vista expirada y luego adelante él a la página de inicio de sesión similar a la solución en el enlace de arriba?

JSF2/Primefaces / Glassfish

Author: Community, 2012-06-26

5 answers

Las excepciones que se lanzan durante las solicitudes ajax no tienen por defecto ningún feedback en el lado del cliente. Solo cuando ejecute Mojarra con project stage establecido en Development y use <f:ajax>, entonces obtendrá una alerta de JavaScript desnuda con el tipo de excepción y el mensaje. Pero aparte de eso, y en PrimeFaces, por defecto no hay retroalimentación en absoluto. Sin embargo, puede ver la excepción en el registro del servidor y en la respuesta ajax (en la sección "Red" del conjunto de herramientas para desarrolladores del webbrowser).

Usted necesidad de implementar una costumbre ExceptionHandler que hace básicamente el siguiente trabajo cuando hay un ViewExpiredException en la cola:

String errorPageLocation = "/WEB-INF/errorpages/expired.xhtml";
context.setViewRoot(context.getApplication().getViewHandler().createView(context, errorPageLocation));
context.getPartialViewContext().setRenderAll(true);
context.renderResponse();

Alternativamente, puede usar la biblioteca de utilidades JSF OmniFaces. Tiene un FullAjaxExceptionHandler para este propósito (código fuente aquí, escaparate demo aquí).

Véase también:

 44
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:37

Una fusión entre la respuesta de @BalusC y este post, he resuelto mi problema!

Mi ExceptionHandlerWrapper:

public class CustomExceptionHandler extends ExceptionHandlerWrapper {

    private ExceptionHandler wrapped;

    CustomExceptionHandler(ExceptionHandler exception) {
        this.wrapped = exception;
    }

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

    @Override
    public void handle() throws FacesException {
        final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();
        while (i.hasNext()) {
            ExceptionQueuedEvent event = i.next();
            ExceptionQueuedEventContext context
                    = (ExceptionQueuedEventContext) event.getSource();

            // get the exception from context
            Throwable t = context.getException();

            final FacesContext fc = FacesContext.getCurrentInstance();
            final Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
            final NavigationHandler nav = fc.getApplication().getNavigationHandler();

            //here you do what ever you want with exception
            try {

                //log error ?
                //log.log(Level.SEVERE, "Critical Exception!", t);
                if (t instanceof ViewExpiredException) {
                    requestMap.put("javax.servlet.error.message", "Session expired, try again!");
                    String errorPageLocation = "/erro.xhtml";
                    fc.setViewRoot(fc.getApplication().getViewHandler().createView(fc, errorPageLocation));
                    fc.getPartialViewContext().setRenderAll(true);
                    fc.renderResponse();
                } else {
                    //redirect error page
                    requestMap.put("javax.servlet.error.message", t.getMessage());
                    nav.handleNavigation(fc, null, "/erro.xhtml");
                }

                fc.renderResponse();
                // remove the comment below if you want to report the error in a jsf error message
                //JsfUtil.addErrorMessage(t.getMessage());
            } finally {
                //remove it from queue
                i.remove();
            }
        }
        //parent hanle
        getWrapped().handle();
    }
}

Mi ExceptionHandlerFactory:

public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {

    private ExceptionHandlerFactory parent;

    // this injection handles jsf
    public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {
        this.parent = parent;
    }

    @Override
    public ExceptionHandler getExceptionHandler() {
        ExceptionHandler handler = new CustomExceptionHandler(parent.getExceptionHandler());
        return handler;
    }

}

Mis caras-config.xml

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
              xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">

    <factory>
        <exception-handler-factory>
            your.package.here.CustomExceptionHandlerFactory
        </exception-handler-factory>
    </factory>
</faces-config>
 17
Author: Douglas Nassif Roma Junior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-19 18:23:52

Estoy usando Mojarra 2.1.7 en modo de producción con JBoss 7. Después de que la sesión caduque, las llamadas AJAX devuelven un documento XML de error. Puede detectar fácilmente este error utilizando el controlador onerror habitual de f: ajax.

<script type="text/javascript">
    function showError(data) {
        alert("An error happened");
        console.log(data);
    }
</script>

<h:commandLink action="...">
    <f:ajax execute="..." render="..." onerror="showError"/>
</h:commandLink>
 3
Author: RajV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-06 00:55:46

He incluido esto en mi clase ViewExpiredExceptionHandler y funcionó bien para mí en FUE

    public void handle() throws FacesException {
    FacesContext facesContext = FacesContext.getCurrentInstance();
                 for (Iterator<ExceptionQueuedEvent> iter = getUnhandledExceptionQueuedEvents()
            .iterator(); iter.hasNext();) {
        Throwable exception = iter.next().getContext().getException();

        if (exception instanceof ViewExpiredException) {


            final ExternalContext externalContext = facesContext
                    .getExternalContext();

            try {


                facesContext.setViewRoot(facesContext.getApplication()
                        .getViewHandler()
                        .createView(facesContext, "/Login.xhtml"));     //Login.xhtml is the page to to be viewed. Better not to give /WEB-INF/Login.xhtml
                externalContext.redirect("ibm_security_logout?logoutExitPage=/Login.xhtml");    //  when browser back button is pressed after session timeout, I used this.         
                facesContext.getPartialViewContext().setRenderAll(true);
                facesContext.renderResponse();

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                iter.remove();
            }
        }

    }

    getWrapped().handle();
}

Espero que esto ayude

 1
Author: Ramya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-12 13:19:06

Me enfrenté a este problema, la necesidad de mostrar una ventana emergente de confirmación cuando el usuario realice cualquier acción después de que se agote el tiempo de espera de la sesión, mi solución propuesta fue:

<security:http use-expressions="true" auto-config="true" entry-point-ref="authenticationEntryPoint">
            <security:intercept-url pattern="/common/auth/**" access="permitAll" />
            <security:intercept-url pattern="/javax.faces.resource/**" access="permitAll" />
            <security:intercept-url pattern="/**/   *.*" access="hasRole('ROLE_ADMIN')" />
            <security:form-login login-page="/common/auth/login.jsf" />
            <!-- <security:remember-me key="secret" services-ref="rememberMeServices" /> -->
            <security:logout invalidate-session="true" logout-success-url="/common/auth/login.jsf" />
        </security:http>
        <bean id="authenticationEntryPoint" class="com.x.y.MyRedirectEntryPoint" >
           <property name="loginFormUrl" value="/common/auth/login.jsf"/>
        </bean>

El MyRedirectEntryPoint debe extender AuthenticationProcessingFilterEntryPoint y anular el método commence

public void commence(HttpServletRequest request, HttpServletResponse response,   AuthenticationException authException)
        throws IOException, ServletException {
    boolean ajaxRedirect = request.getHeader("faces-request") != null
            && request.getHeader("faces-request").toLowerCase().indexOf("ajax") > -1;
    if (ajaxRedirect) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            response.sendError(403);

        }
    } else {

        super.commence(request, response, authException);
    }
}

Ahora simplemente puede enlazar una función de javascript de devolución de llamada para atrapar el error 403 lanzado y hacer lo que quiera:

$(document).bind('ajaxError',
                    function(event, request, settings, exception){
                          if (request.status==403){
                             //do whatever you wanted may be show a popup or just redirect
                             window.location = '#{request.contextPath}/';
                             }
                             });
 1
Author: Rami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-24 07:52:42