Handle ViewExireException/ajax and display a Prime

2019-04-02 05:45发布

I don't redirect or forward my user to another page. So when the my SessionExpiredExceptionHandler (extends ExceptionHandlerWrapper) handles the ViewExireException. I want the user to stay on the same page and display a PrimeFaces Dialog. For notifying that the session has expired and that the user needs to login again (dialog based). I am use Servlet 3.1 functions to login/logout user and Basic/file for auth-method to map the users to different system roles.

What is happening now is that the View/page get refreshed after 2 min, but the session doesn't get invalidated. That only happens the second time when the page refreshes, after 4 min.

    <session-config>
        <session-timeout>2</session-timeout>
    </session-config>

Edit: Which is refreshed by the meta tag:

<meta http-equiv="refresh" content="#{session.maxInactiveInterval}" />

How can I make SessionExpiredExceptionHandlerinvalidate the session object (Servlet logout) when the Exceptions occur the first time, and how can I invoke a JavaScript (expireDlg.show()) on the client to display a PrimeFaces dialog ?

I have looked at some other threads but not found a viable solution. Session time-out

SessionExpiredExceptionHandler

    @Override
    public void handle() throws FacesException {
    for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
        ExceptionQueuedEvent event = i.next();
        ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
        Throwable t = context.getException();
        if (t instanceof ViewExpiredException) {
        ViewExpiredException vee = (ViewExpiredException) t;
        FacesContext fc = FacesContext.getCurrentInstance();
        Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
        NavigationHandler nav = fc.getApplication().getNavigationHandler();                

        try {
            requestMap.put("currentViewId", vee.getViewId());

            nav.handleNavigation(fc, null, "Home");
            fc.renderResponse();

        } finally {
            i.remove();
        }                                
        }
    }
    // At this point, the queue will not contain any ViewExpiredEvents.
    // Therefore, let the parent handle them.
    getWrapped().handle();
    }

web.xml

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

2条回答
劫难
2楼-- · 2019-04-02 05:56

This solution worked for my case. It seams that Primefaces (3.3) is swallowing the ExceptionQueuedEvent. There are no Exception to handle when my ViewExceptionHandler gets called. So instead I used the p:idleMonitor component with event listner. I also removed the meta refresh tag.

<p:idleMonitor timeout="#{(session.maxInactiveInterval-60)*1000}">
        <p:ajax event="idle" process="@this" update="sessionMsg" listener="#{userController.userIdleSession()}" />
        <p:ajax event="active" process="@this" update="sessionMsg" listener="#{userController.userActiveSession()}"/>
</p:idleMonitor>

One weird thing is if the timeoutis excatly the same as the web.xmlsession time-out parameter, the listener won't be invoked.

Bean functions

public void userIdleSession() {
    if (!userIdleMsgVisable) {
        userIdleMsgVisable = true;
        JsfUtil.addWarningMessage(JsfUtil.getResourceMessage("session_expire_title"), JsfUtil.getResourceMessage("session_expire_content"));            
    }
}

public void userActiveSession() {
        if (!userSessionDlgVisable) {
            userSessionDlgVisable = true;                     
            RequestContext.getCurrentInstance().execute("sessionExipreDlg.show()");            
        }
    }

The dialog (sessionExipreDlg) called the redirect instead of using navigation handler to get new scope and refresh the page.

public void userInactiveRedirect() {
        FacesContext fc = FacesContext.getCurrentInstance();
        userIdleMsgVisable = false;
        userSessionDlgVisable = false;
        sessionUser = null;         
        HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();
        JsfUtil.findBean("homeController", HomeController.class).clearCurrentValues();        
        try {
            fc.getExternalContext().redirect(JsfUtil.getApplicationPath(request, false, null));            
        } catch (IOException ex) {
            BeanUtil.severe(ex.getLocalizedMessage());
        }
    }
查看更多
贪生不怕死
3楼-- · 2019-04-02 06:00

How can I make SessionExpiredExceptionHandler invalidate the session object (Servlet logout) when the Exceptions occur the first time

The session is supposedly to be already invalidated/expired (otherwise a ViewExpiredException wouldn't be thrown at all), so I don't see how it's useful to manually invalidate/expire it yourself. But for the case that, you can invalidate it as follows:

externalContext.invalidateSession();

and how can I invoke a JavaScript (expireDlg.show()) on the client to display a PrimeFaces dialog ?

You can use the PrimeFaces RequestContext API to programmatically instruct PrimeFaces to execute some JS code on complete of ajax response.

RequestContext.getCurrentInstance().execute("expireDlg.show()");

Don't forget to remove the navigation handler block from the exception handler if you actually don't want to navigate.

查看更多
登录 后发表回答