PhaseListener + erro quando sessão expira [RESOLVIDO]

Tenho um PhaseListener que verifica se o usuário está logado, isso funciona tranquilo.
O problema é quando a sessão expira, ele não consegue redirecionar para a página de login

Alguém pode dar uma ajuda?

PhaseListener

@SuppressWarnings("serial")
public class Autorizador implements PhaseListener {

	public static final String loginPage = "/login.jsp";
	
	public void afterPhase(PhaseEvent event) {
		FacesContext fc = event.getFacesContext();
		if(fc.getViewRoot().getViewId().equals(loginPage)){
			return;
		}
		
		ELResolver elr = fc.getApplication().getELResolver();
		LoginHandler login = (LoginHandler) elr.getValue(fc.getELContext(), null, "loginHandler");
		
		if(login == null || !login.isLogado()){
			NavigationHandler nav = fc.getApplication().getNavigationHandler();
			nav.handleNavigation(fc, null, "login");
		}
	}

	public void beforePhase(PhaseEvent arg0) {
		
	}

	public PhaseId getPhaseId() {
		return PhaseId.RESTORE_VIEW;
	}
}

faces-config.xml

<lifecycle>
	<phase-listener>br.com.aplicacao.utils.Autorizador</phase-listener>
</lifecycle>

Erro quando a sessão expira

11:12:21,947 ERROR BaseXMLFilter:157 - Exception in the filter chain
javax.servlet.ServletException: viewId:/jsp/home.jsp - View /jsp/home.jsp could not be restored.
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:270)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:154)
	at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:260)
	at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:366)
	at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:493)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Unknown Source)
Caused by: javax.faces.application.ViewExpiredException: viewId:/jsp/home.jsp - View /jsp/home.jsp could not be restored.
	at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:186)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
	at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:104)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
	... 18 more

ninguém tem uma solução …
Já procurei em váários lugares e ainda não consegui resolver

Resolvido parcialmente.
Fiz um Filter para verificar quando a sessão expirou, ele consegue redirecionar para o login, e mantive este PhaseListener acima (agora AutorizadorPhaseListener) para verificar usuários.
O problema agora é que quando a sessão expira e é clicado em um botao com a tag <a4j: … o Filter não é chamado, sómente o PhaseListener, continuando com o mesmo problema descrito acima também.

Aguma ajuda desta vez?

Filter

public class Autorizador implements Filter {

	public static final String loginPage = "faces/login.jsp";

	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filterChain) throws IOException, ServletException {
		if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) {

			HttpServletRequest httpServletRequest = (HttpServletRequest) request;
			HttpServletResponse httpServletResponse = (HttpServletResponse) response;

			if (isSessionControlRequiredForThisResource(httpServletRequest)) {
				if (isSessionInvalid(httpServletRequest)) {
					String timeoutUrl = httpServletRequest.getContextPath() + "/" + loginPage;
					httpServletResponse.sendRedirect(timeoutUrl);
					return;
				}
			}
		}
		filterChain.doFilter(request, response);
		
	}
	private boolean isSessionControlRequiredForThisResource(
			HttpServletRequest httpServletRequest) {

		String requestPath = httpServletRequest.getRequestURI();
		boolean controlRequired = !org.apache.commons.lang.StringUtils.contains(requestPath, loginPage);

		return controlRequired;

	}

	private boolean isSessionInvalid(HttpServletRequest httpServletRequest) {

		boolean sessionInValid = (httpServletRequest.getRequestedSessionId() != null)
				&& !httpServletRequest.isRequestedSessionIdValid();
		return sessionInValid;

	}

	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}
	
	
}

Talvez ajude :lol:

http://www.guj.com.br/posts/list/85145.java#454878

Palpite forte.

O problema é o momento em que o PhaseListener é chamado, depois de RESTORE_VIEW. Minha sugestão é chamar o seu código antes dessa fase. Isso porque a exceção ocorre dentro dela.

Troque o método beforePhase para afterPhase e vice-versa e veja o que acontece.

Valeu pela ajuda, consegui resolver com a dica do Leonardo3001. Agora em qualquer ação ele verifica a sessão e retorna para o login caso esteja expirada ou usuário não logado.

Segue o código:

@SuppressWarnings("serial")
public class AutorizadorPhaseListener implements PhaseListener {

	public static final String loginPage = "/login.jsp";
	
	public void afterPhase(PhaseEvent event) {
		try {
			FacesContext fc = event.getFacesContext();
			if(fc.getViewRoot().getViewId().equals(loginPage)){
				return;
			}
			
			ELResolver elr = fc.getApplication().getELResolver();
			LoginHandler login = (LoginHandler) elr.getValue(fc.getELContext(), null, "loginHandler");
			
			if(login == null || !login.isLogado()){
				NavigationHandler nav = fc.getApplication().getNavigationHandler();
				nav.handleNavigation(fc, null, "login");
			}
			
		} catch (Exception e) {
			// Não há necessidade de informar erro
		}
	}

	public void beforePhase(PhaseEvent arg0) {
		ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
		HttpServletRequest request = (HttpServletRequest) context.getRequest();
		if(!request.getRequestURL().toString().endsWith(loginPage) && context.getSession(false) == null){
			try {
				context.redirect(request.getContextPath() + "/faces" + loginPage);
			} catch (IOException e) {
				// Não há necessidade de informar erro
			}
		}
	}

	public PhaseId getPhaseId() {
		return PhaseId.RESTORE_VIEW;
	}
}