Como reiniciar ViewRoot do JSF 1.2

Boa tarde srs,

Tenho um sistema JSF + Richfaces que não permite sessões duplicadas de um usuário, este controle é feito por um número randômico que é gerado a cada acesso do usuário, tenho um servlet inicial que além de autenticar o usuário, ele verifica se o id deste já está em uma lista em um bean de aplicação, se já estiver por meio do out do servlet coloco uma mensagem para o usuário. Porém se o id do usuário ainda não está nesta lista ele pode acessar normalmente. E criei um sessionlistener para que ao encerrar a sessão o id do usuário seja removido da lista.

Meu problema é que em algumas situações quando o usuário acessa está dando “duplicate Id” nos componentes da minha tela jsf. Por meio de um phase listener eu vi que em algumas situações o faces está recuperando a view e renderizando-a (pulando da fase 1 para a 6). Tentei criar uma nova viewroot, porém quando passa pela 1ª fase do JSF ele recupera os componentes antigos e lasca tudo de novo!

Alguém sabe como forçar o JSF a “zerar o cache” (se é este o termo), ou forçá-lo a reconstruir a view, passando por todas as fases normalmente?

O código que utilizo para limpar a viewroot está abaixo, acesso ele pelo meu servlet de login.

[code]protected FacesContext getFacesContext(HttpServletRequest request, HttpServletResponse response) {
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext == null) {

        FacesContextFactory contextFactory  = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
        LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); 
        Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);

        facesContext = contextFactory.getFacesContext(request.getSession().getServletContext(), request, response, lifecycle);
    }

    if(facesContext.getViewRoot() != null){
        // set a new viewRoot, otherwise context.getViewRoot returns null
        UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, 
        		"/inicio.xhtml");
        facesContext.setViewRoot(view);        
    }
    return facesContext;
}[/code]

Galera consegui!

Após muita batalha, descubri algo interessante. Estou utilizando o RichFaces, sendo assim o estado dos componentes da view ficam armazenados na sessão do usuário.

Primeiro vamos a solução pouco efetiva:

Reiniciei a instância do FacesContext conforme trecho de código abaixo:

	protected void limparFacesContext(HttpServletRequest request, HttpServletResponse response) {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		if (facesContext == null) {
			FacesContextFactory contextFactory  = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
			LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); 
			Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);

			facesContext = contextFactory.getFacesContext(request.getSession().getServletContext(), request, response, lifecycle);
		}

		facesContext.release();
		InnerFacesContext.setFacesContextAsCurrentInstance(null);
	}

    private abstract static class InnerFacesContext extends FacesContext{
        protected static void setFacesContextAsCurrentInstance(final FacesContext facesContext){
            FacesContext.setCurrentInstance(facesContext);
        }
    }

Isso não foi muito efetivo visto que novamente ao passar pela RESTORE_VIEW a VIEWROOT era criada e "pegava" os componentes antigos.

A solução foi a seguinte:

	/**
	 * Método utilizado para remover as referências dos objetos que estão na sessão
	 * tomando cuidado para não remover os objetos de segurança do Spring
	 * @param session - sessão ativa do usuário
	 */
	@SuppressWarnings("unchecked")
	public void limpaSessaoParaInicio(HttpSession session) {
		try{	
			if(session != null){
			    Enumeration atributeNames = session.getAttributeNames();
			    StringBuilder strBuilder = new StringBuilder();
			    while(atributeNames.hasMoreElements()){
			    	String keyObjeto = (String) atributeNames.nextElement();
			    	if(!keyObjeto.contains("SPRING")){
			    		strBuilder.append(keyObjeto + "\n\t");
			    		session.removeAttribute(keyObjeto);
			    	}
			    }
			    if(strBuilder.length() > 1){
			    	LOGGER.info("Objetos excluídos da sessão("+session.getId()+") para início da aplicação: \n\t"+strBuilder.toString());
			    }
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

Ao acessar o servlet de login os objetos da sessão são limpos.
Apenas tomo cuidado para não limpar os objetos de segurança e autenticação do Spring, por isso o if:

if(!keyObjeto.contains("SPRING"))

Descubri que o RichFaces mantém os estados dos componentes atrelados a sessão do usuário por meio de 2 objetos (org.ajax4jsf.application.AjaxStateManager.view_sequence e org.ajax4jsf.application.AjaxStateHolder). Com a limpeza da sessão estes objetos não existem mais e a árvore de componentes é recriada (pelo que percebi).

Assim, não tomei mais o "duplicate Id" e de fato a VIEWROOT criou novos componentes.

Obrigado a todos!