Nova versão do JSF 2 não dispara o FORWARD na navegação das paginas XHTML [RESOLVIDO]

33 respostas
F

Ola galera

Na hora que vc faz um regra de navegação do faces-config, a especificação diz que o JSF navega via FORWARD de uma página para outra.
O teste disso pode fazer um filtro simples que intercepta tudo, usando todos os dispachers possiveis:

<filter>
		<filter-name>FiltroTeste</filter-name>
		<filter-class>controle.FiltrarRestricoes</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>FiltroTeste</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
		<dispatcher>ERROR</dispatcher>
	</filter-mapping>

Em qualquer versão do JSF 1.x, vc pode navegar de uma pagina para outra que o o filtro é disparado.
Segundo informações da especificação do JSF :

Estou a 1 semana ajudando um camarada aqui no forum a implementar um filtro de autenticação para aplicações JSF 2 e pude comprovar que na versão 2 do JSF, as navegações não estão invocando o FORWARD e assim o o filtro não é disparado.
Montei um ambiente de teste com MOJARRA e MyFaces para JSF 2 e realmente não esta invocando!! Montei um ambiente teste com Mojara 1.2 e o FORWARD é chamado e filtro funciona!
Não achei nada a web sobre isso, crie um post no JBOSS Forum e no JavaRanch até agora sem respostas…
Eu sei que o ciclo de vida da execução JSF foi alterada para facelets nativamente com as paginas XHTML.
Fiz o mesmo teste JSF 2 usando paginas JSP…dai funcionou!!!
A questão por que isso não funciona com XHTML? Como ficam os projetos JSF 2 com frameworks baseados em filtros com Spring Security, JPro-Guard e até alguns JAAS? uma vez que apresentaram brechas de segurança por causa desse motivo.
Alguem tem alguma informação?

33 Respostas

F

Bom gente esta ai a resposta…para container isso, os projetos antigos deverão colocar <REDIRECT/> nas navegações JSF 2 para usar regras de autenticação baseado em filtros.
O post fica aberto para qualquer outra pessoa encontrar outras soluções para isso…favor postar aqui.
T+

F

A solução que me parece ideal é usar autenticação baseada em PHASE-LISTENER -
http://rodrigolazoti.com.br/2008/09/01/filtrando-usuarios-logados-em-jsf-com-phaselistener/
http://ciromacedo.blogspot.com/2008/06/controle-de-acesso-no-jsf.html


Mas eu não testei…valido fazer um teste ai…

C

pois é FernandoFranzini, depois de pesquisar bastante e ler vários textos, os melhores q eu achei foram
http://java.dzone.com/articles/fluent-navigation-jsf-2
http://java.dzone.com/articles/fluent-navigation-jsf-2?page=0,1
http://blog.gilliard.eti.br/2009/05/implicit-navigation-jsf-2/
e infelizmente ainda não achei nenhuma maneira de recuperar o nomeDaPágina.xhtml requisitada e processada pelo facelets, como já faz vários dias q estou pesquisando sobre isso e ainda não encontrei nd, estou pensando em fazer o seguinte, e dar continuidade ao projeto…
não tava afim de ficar declarando regras de navegação no faces-config.xml, esse é um dos motivos que fizeram eu nao trabalhar com web por um bom tempo, eu detesto arquivos de configuração e quanto menos precisar mecher neles, mais feliz eu fico, levando em consideração a parada de navegação implicita, que se o outcome informado na action do commandlink não for encontrado no faces-config, a navegação implicita assume que este é o nome da pagina a ser carregada, nas páginas que vou precisar usar o filter para autorização de usuario, vou concatenar o parametro ?faces-redirect=true na action do commandlink ± assim<h:form> <h:commandLink action="pagina1" value="pagina1" /> <br/> <h:commandLink action="pagina2?faces-redirect=true" value="pagina2" /> <br/> Hello from Facelets </h:form>isso ficou legal, nao preciso declarar regras de navegação e o parametro faces-redirect faz o trabalho da tag necessária na regra de navegação, por enquanto isso resolveu o meu problema de login no JSF 2.0, pra quem não viu o problema, tah aqui http://www.guj.com.br/java/247084-login-aplicacao-jsf dai é só usar a tag como o fernandofranzini sugeriu no faces-config.xml ou se preferir o parametro faces-redirect

FernandoFranzini, obrigado pelo empenho ai em descobrir alguma solução, vlw pela ajuda, mas como preciso colocar o site no ar até fim do mes, vou acelerar aqui, mas pretendo continuar tentando descobrir uma forma de recuperar a URL requisitada e processada pelo facelets assim que folgar um pouco aqui.

vlw t+

F
Achei outra forma com phase listener... Remova o filter e use:
public class AuthorizationListener2 implements PhaseListener {

	public void afterPhase(PhaseEvent event) {
		FacesContext facesContext = event.getFacesContext();
		String currentPage = facesContext.getViewRoot().getViewId();
		System.out.println("PHASE - " + currentPage);
	}

	public void beforePhase(PhaseEvent event) {
	}

	public PhaseId getPhaseId() {
		return PhaseId.RENDER_RESPONSE;
	}
}
Dai vc declara no faces config
&lt;lifecycle&gt;
		&lt;phase-listener&gt;controle.AuthorizationListener2&lt;/phase-listener&gt;
	&lt;/lifecycle&gt;
E faça o mesmo teste... Dai dentro do face vc verifica a pagina que o JSF esta renderizando e veja se o usuario tem a PERMISSÃO para acessa-la..caso contrario, rederecione para a pagina de login...veja outros exemplos nos links que eu passe de como fazer isso. T+
C

o phase listener apresenta o mesmo problema do filter, URL atrasada e usando a mesma solução acima, ou ?faces-redirect=true passa a funcionar

F

Pelo que eu testei o phase listener apresenta o mesmo problema se a fase interceptadas for RESTORE_VIEW…
Mas como vc pode ver eu estou falando da RENDER_RESPONSE que ja tem o novo endereço (nova visão)
Acho que fecho…

C

puts cara, finalmente deu certo, usando phase listener, veja só, eu tentei várias vezes com phase listener, mas olhando a sua classe e a minha, tinha algo diferente, alterei na minha e funcionou certinho com phase listener, inclusive sem utilizar ou ?faces-redirect=true. Vamos lá então, pra encerrar a história, kkkk ficou assim:

suponha que temos 4 paginas, index.xhtml, pagina1.xhtml, pagina2.xhtml e acessoNegado.xhtml

faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>

<!-- =========== FULL CONFIGURATION FILE ================================== -->

<faces-config version="2.0"
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

    <lifecycle>
        <phase-listener>controle.AuthorizationListener</phase-listener>
    </lifecycle>
</faces-config>
index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:commandLink  action="pagina1" value="pagina1" />
            <br/>
            <h:commandLink action="pagina2" value="pagina2" />
            <br/>
            Hello from Facelets
        </h:form>
    </h:body>
</html>
AuthorizationListener (se a pagina requisitada for pagina2.xhtml, redireciona para acessoNegado.xhtml)
public class AuthorizationListener implements PhaseListener {

    @Override
    public void afterPhase(PhaseEvent event) {
        FacesContext facesContext = event.getFacesContext();
        String currentPage = facesContext.getViewRoot().getViewId();

        System.out.println("currentPage: " + currentPage);
        if (currentPage.contains("pagina2.xhtml")) {
            NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
            nh.handleNavigation(facesContext, null, "acessoNegado.xhtml");
        }
    }

    @Override
    public void beforePhase(PhaseEvent event) {
    }

    @Override
    public PhaseId getPhaseId() {
        //return PhaseId.RESTORE_VIEW;
        return PhaseId.RENDER_RESPONSE;
    }
}
FernandoFranzini, repare no método getPhaseId() eu usava a linha comentada, mudando para RENDER_RESPONSE a URL não fica mais atrasada na lógica de autorização do método afterPhase(...). Bom, e assim tah legal, é só acrescentar a logica de validação do usuario e pronto....
F

Isso mesmo cleiton…acho que chegamos numa solução pratica, centralizada e reutilizavel.
Eu tb vou isso nos proximos projeto JSF 2…os antigos 1.2 ja estam rodando a muito tempo com filter funcionando ok com foward.
Uma coisa que eu vi no seu codigo q ta errado:

Vc não deve por o nome da pagina e sim o nome do alias da pagina declarado no faces config…quando vc mudar a pagina o alias fica o mesmo.

No resto parece ok.

C

então fernando, eu tava pensando em utilizar esse novo recurso de navegação implicita da versão 2.0, nem tava querendo declarar navegações no faces-config.xml, até se vc ver ali no meu faces-config de teste, nem declarei nd, masssss, como vc tem mais experiencia… o que vc me diz sobre esse novo recurso e sobre não declarar regras de navegação no faces-config ?

F

Pelo pouco que eu sei dos novos recursos do JSF 2 é para evitar ter que escrever no XML…
Acredito que não tenha problema em usar…fica mais complicadinho fazer o codigo, mas vc fica isento de xml.

F

Então cleiton

Acabei de achar um problema nessa segurança kkkk…calma…relaxa… :lol:

*) Phase listerner de RENDER_RESPONSE é executado somente depois da ação do bean…#{bean.acao}!!!
Se caso o usuario não estiver logado ou expirar a sessão dele…se ele clickar no botão da GUI o sistema vai executar a ação do botão e depois disso de sera enviado a pagina de login. E nós não queremos isso né…

Por isso, para precisar usar 2 listener…

  1. Listener de RESTORE_VIEW que não deixa o usuário executar a ação se não estiver logado
  2. Outro listener de RENDER_RESPONSE que não deixa o usuário ver a pagina se ele não possuir permissão.
    Dai vc pode centralizar essas regras em objetos do seu sistema de SEGURANÇA e invoca-los nestes listeners…
    Veja que na solução anterior ao filtro…estas 2 validações estavam juntos…
C

legal, mais um problema que provavelmente eu ia identificar na hora de implementar a logica de validação do usuario, hahahha e vc ja solucionou…

então blz, vou implementar os dois phaselisteners aqui e ver no q da

F

Estava pensando aqui com meu botões…seria melhor se agente mantivesse o filtro como esta e acrescentássemos uma validação similar ao do filtro no fase RENDER_RESPONSE para validar somente os casos de navegações internas do facelets…Por que pensa comigo:
Por experiência própria eu não consigo ver um cenário onde barrar via forward seja necessário. Pois normalmente você barra uma URI (isto é, uma requisição GET na URI ou redirect) ou um evento de uma página (origem) previamente renderizada pro usuário…seria casos excepcionais…tipos casos em que vc esquecesse de retirar um botão da GUI no qual o usuário não teria permissão de invocar…(conhecido como permissão por função)
Esse código de validação do fase RENDER_RESPONSE serie apenas de segurança extra mesmo…algo assim questionável.

C

então eu tbem estava analisando aqui, e mesmo com duas que implementam phase listener, uma pra RESTORE_VIEW e outra pra RENDER_RESPONSE, na RENDER_VIEW por exemplo, eu nao posso redirecionar o usuario direto pra pagina de login simplesmente por ele não estar logado, levando em consideração que existem páginas que não é necessário estar logado para navegar, então eu continuaria precisando saber o nome da pagina requisitada, e isso só se consegue na RENDER_RESPONSE

no meu caso, o certo é verificar usuario e permissão juntos, senão nao da… pelo menos eu nao consegui visualizar isso até agora…

F

cleiton herrmann:
então eu tbem estava analisando aqui, e mesmo com duas que implementam phase listener, uma pra RESTORE_VIEW e outra pra RENDER_RESPONSE, na RENDER_VIEW por exemplo, eu nao posso redirecionar o usuario direto pra pagina de login simplesmente por ele não estar logado, levando em consideração que existem páginas que não é necessário estar logado para navegar, então eu continuaria precisando saber o nome da pagina requisitada, e isso só se consegue na RENDER_RESPONSE
no meu caso, o certo é verificar usuario e permissão juntos, senão nao da… pelo menos eu nao consegui visualizar isso até agora…

Mas um motivo para usar o filtro…

  1. usa o filtro mesmo.
  2. reutiliza a validação no RENDER_RESPONSE

Pensa…
1)Quando chegar uma URL solicitada via navegador o filtro vai aplicar a validação antes de chegar no facesServlet e vai mandar para o login sem passar pelo JSF. Então não executa o fase.
2) Quando vc navegador da pagina 1 para pagina 2, o filtro não vai ser executado e fase RENDER_RESPONSE sera executado garantido as validações.
3) Quando chegar uma URL solicitada via navegador o filtro vai aplicar a validação antes de chegar no facesServlet, se a permisão bater…o fase vai refazer a validação e liberar o acesso. Unico ponto negativo que vai valida 2 vezes para esses casos…

Na verdade tem fazer testes em um estudo de caso simples para pegar todas os casos…

F

Cleiton
O que vc acha que fica melhor?
1) Usa redirect e fazer só o filtro?
ou
2) Executar as validação 2 vezes no filtro e na fase RENDER_RESPONSE? (que tem a probabilidade de ser 90% das paginas…o cara autenticado com as permissões ok)

Pros e contras?

F

Acho que resolvi…

  1. Chama a regra de autenticação no filtro
    O filtro fica melhor que pode haver no seus sistema outros endereços para coisas não faces, como arquivos, imagens, relatório etc que tb estão dentro da validação de URL…se agente usar o fhase de Restore VIEW ele naõ vai pegar esses outros endereços…dai não vai dar…

  2. Chama a regra de autenticação no phase de RENDER_RESPONSE:
    Mas para não perder tempo/recursos da segunda validação desnecessária é só verificar a URI do fhase é igual a URI do filtro…se forem iguais não precisa aplicar a segunda validação, podemos pular via if…se forem diferentes…dai vc valida toda a regra de segurança de novo…pq pensa bem…só vai ser diferente quando vc navegar da paginaA para a paginaB.
    Para comparar as duas…é só colocar o URI do filtro numa variável ThreadLocal e acessar dentro do fhase listener…

Dai fica lindooooo e não perdemos tempo validando as regras de autenticação duplicadamente se caso ele chamou uma ação e não navegou…

C

Cleiton
O que vc acha que fica melhor?

  1. Usa redirect e fazer só o filtro?
    ou
  2. Executar as validação 2 vezes no filtro e na fase RENDER_RESPONSE? (que tem a probabilidade de ser 90% das paginas…o cara autenticado com as permissões ok)

Pros e contras?


pois é fernando, o jeito mais simples na minha opinião é usar filter e concatenar o parametro ?faces-redirect=true na action do commandlink, nas paginas q eu quero validar e autorizar acesso

EDIT
Então cara, gastei mais meia horinha agora aqui, acho q nao captei a idéia de usar o filtro e o phase em conjunto, não entendi o pq…
eu implementei aqui usando só o filtro, fiz desse jeito q falei, nao declarei regra nenhuma de navegação no faces-config, e nos commandlink das paginas que requerem autorização eu concatenei o ?faces-redirect=true, e dai na classe filter, eu verifico atraves de if, se a pagina corrente é uma das que precisam de usuario logado, e se sim, eu verifico se tem um usuario logado, se sim, continua normal, senão volto pra index, que é onde eu coloquei meus campos de usuario e senha… fico legal assim eu achei, nao achei necessário usar o phase tbem, na verdade nao entendi sua ideia de usar os dois em conjunto

F

Então cleiton eu acho que vc fez sua decisão e realmente assim tb funciona e fica bom.
Eu particularmente não escolheria esta opção pois esse esquema de redirect tanto na url como no xml afeta diretamente a performance da aplicação, uma vez que o container vai mandar um HTTP 301 e o navegador vai ter que fazer sempre + 3 viagens HTTP. Se vc ja diagnosticou que isso não sera um gargalo, então ok.
Estarei documentando tudo isso no meu blog colocando os pros e contras das 3 opções que levantamos…
Existe uma terceira opção que ja bolei aqui q tb ta certo usando somente filter e anotações de segurança JEE 6 @Role.

C

estou terminando a parte de orçamentos no site, assim q terminar isso, vou dar uma olhada com mais calma na sua sugestão de usar filter + phase, não é q eu fiz a minha opção, eu acho q ontem meio na preça perto das 6 da tarde, eu não consegui compreender direito, assim q eu folgar aqui vou dar uma lida novamente, e volto a testar e postar os resultados aqui

R

Olá amigos,

Vou postar minha dúvida aqui apesar de não ter relação específica. É um caso de redirect no JSF 2.

Tenho uma formulário de registro (com escopo view pois tenho combos aninhadas nele) e ao aplicar a ação Save, mostro uma janela de diálogo com a informação de sucesso.

Começa aí o meu problema. Se fosse somente para mostrar na tela eu utilizaria o h:messages ou p:messages ou p:growl mas eu preciso, a finalizar a gravação do usuário, redirecionar para a página de login. Neste caso, se eu utilizar o recurso do jsf 2 para mostrar as mensagens e renderizar automaticamente o p:dialog (not empty facescontext.maximumSeverity), mostra normal a menos que eu redirecione a página. Se eu inserir no managedBean o redirecionamento, a mensagem “é engolida”. Eu li alguns posts em que o pessoal comenta sobre recuperar as mensagens por meio de phaselistener mas confesso que tou perdido nesse assunto. Não entendi direito e gostaria de saber se há outra solução senão esta.

O que eu fiz e que não gostaria de ter feito (pois é um retrabalho em cima do que já é feito pelo JSF) é implementar um controle por meio de atributo, por exemplo, atributo exibeDialog. Neste caso eu abro o p:dialog de acordo com o valor do atributo boolean. Só que este controle que fiz já identifiquei que, se estiver em um escopo de sessão, a todo momento teria que “limpar” o atributo exibeDialog para não ficar mostrando a janela de diálogo entre a navegação das páginas.

Olha, pesquisei muito sobre este esquema de mostrar uma janela de diálogo. Mostrar é muito tranquilo. O problema é mostrar e poder redirecionar para outra página sem que o JSF “engula” a mensagem.

Ah, outro detalhe, o meu redirecionamento no managedBean eu estou realizando pelo .redirect(pagina) do próprio faces mesmo. Também se utilizar o return "paginaX.jsf?redirect=true, ocorre o mesmo. A mensagem é “engolida”.

Sds,
Rodrig Bortolon

F

rbortolon:
Olá amigos,

Vou postar minha dúvida aqui apesar de não ter relação específica. É um caso de redirect no JSF 2.

Tenho uma formulário de registro (com escopo view pois tenho combos aninhadas nele) e ao aplicar a ação Save, mostro uma janela de diálogo com a informação de sucesso.

Começa aí o meu problema. Se fosse somente para mostrar na tela eu utilizaria o h:messages ou p:messages ou p:growl mas eu preciso, a finalizar a gravação do usuário, redirecionar para a página de login. Neste caso, se eu utilizar o recurso do jsf 2 para mostrar as mensagens e renderizar automaticamente o p:dialog (not empty facescontext.maximumSeverity), mostra normal a menos que eu redirecione a página. Se eu inserir no managedBean o redirecionamento, a mensagem “é engolida”. Eu li alguns posts em que o pessoal comenta sobre recuperar as mensagens por meio de phaselistener mas confesso que tou perdido nesse assunto. Não entendi direito e gostaria de saber se há outra solução senão esta.

O que eu fiz e que não gostaria de ter feito (pois é um retrabalho em cima do que já é feito pelo JSF) é implementar um controle por meio de atributo, por exemplo, atributo exibeDialog. Neste caso eu abro o p:dialog de acordo com o valor do atributo boolean. Só que este controle que fiz já identifiquei que, se estiver em um escopo de sessão, a todo momento teria que “limpar” o atributo exibeDialog para não ficar mostrando a janela de diálogo entre a navegação das páginas.

Olha, pesquisei muito sobre este esquema de mostrar uma janela de diálogo. Mostrar é muito tranquilo. O problema é mostrar e poder redirecionar para outra página sem que o JSF “engula” a mensagem.

Ah, outro detalhe, o meu redirecionamento no managedBean eu estou realizando pelo .redirect(pagina) do próprio faces mesmo. Também se utilizar o return "paginaX.jsf?redirect=true, ocorre o mesmo. A mensagem é “engolida”.

Sds,
Rodrig Bortolon

As mensagens não são engolidas não…elas simplesmente ficam no escopo request e por isso são perdidas quando ha um redirecionamento(é criado outro request). Por isso que, conceitualmente vc não pode fazer essa operação.

R

Olá Fernando,

Pois é, lembro que li um post aqui que o Rafael Ponte comentou justamente isso. Sobre o escopo de request e mensagens. Mas e no meu caso e em outros em que o managedBean tem que estar com escopo de view ou session ?

Não há outra solução ?

Outro detalhe sobre CRUD e escopo do jsf. Na internet vejo vários exemplos de como utilizar CRUD no JSF onde é demonstrado tudo num só xhtml. Ou seja, nele há o datatable e um p:dialog. Até ai tudo bem pois no mesmo bean é tranquilo de tratar os dados e com poucos atributos. Entendo que é só um exemplo para demonstração. Mas e um exemplo como vou citar abaixo ?

No meu formulário de Estabelecimento (cadastro) tenho que ter vários atributos inclusive outra aba para fotos. Ou seja, não posso manter tudo isso num p:dialog. Neste caso vou separar em outra página. Uma é a página de pesquisa e outra é a página de cadastro de estabelecimentos. Portanto, cabe aí o uso de um escopo de session (me corriga se estiver errado). E é justamente neste ponto que quero chegar. Não vi sequer um exemplo em forums e na internet sobre este caso de CRUD com separação por páginas. Você já viu algum exemplo ou pode me passar algum link sobre ? Eu já realizei essa implementação no meu sistema(como citei com escopo de sessão) porém gostaria de visualizar exemplos de outras pessoas e trocar idéias sobre esse ponto específico.

Sds,
Rodrigo

F

Pois é, lembro que li um post aqui que o Rafael Ponte comentou justamente isso. Sobre o escopo de request e mensagens. Mas e no meu caso e em outros em que o managedBean tem que estar com escopo de view ou session ?
Não há outra solução ?

Não…as mensagens não tem nenhuma relação com o managedBeans…no jsf não tem como declarar escopo das mensagens!!
Conceitualmente elas estão no request…pq não faz sentido estar na sessão.
Vc pode manualmente colocar suas mensagens na sessão e imprimi-las na paginas…mas dai vc acaba refazendo o controle.
O mais indicado é não usa redirect…
Pq vc ta usando redirect?

R

FernandoFranzini:
Pois é, lembro que li um post aqui que o Rafael Ponte comentou justamente isso. Sobre o escopo de request e mensagens. Mas e no meu caso e em outros em que o managedBean tem que estar com escopo de view ou session ?
Não há outra solução ?

Não…as mensagens não tem nenhuma relação com o managedBeans…no jsf não tem como declarar escopo das mensagens!!
Conceitualmente elas estão no request…pq não faz sentido estar na sessão.
Vc pode manualmente colocar suas mensagens na sessão e imprimi-las na paginas…mas dai vc acaba refazendo o controle.
O mais indicado é não usa redirect…
Pq vc ta usando redirect?

Fernando, não quis dizer que mensagens tem relação com o escopo. Eu quis mencionar o que vc justamente comentou. Que se o escopo do managedBean está diferente de request (que no meu caso é session), ocorre este problema.

Não estamos falando aqui de escopo de mensagens e sim do escopo dos managedBean’s. Até ai ok.

O caso de implementar mensagens customizadas é justamente o que eu fiz e que acho uma “invenção da roda” sendo que o jsf deveria fazer isso.

Imagine só no que citei onde há um crud com tela de pesquisa (onde há o datatable com a lista de estabelecimentos) e quando o usuário clica em um registro, o sistema redireciona (olha só o redirect aqui) para outra página. Na página de alteração de dados do estabelecimento, eu quero que o sistema salve os dados e após, redirecione para a página de pesquisa novamente. Só que caímos no problema que citei. Se eu mostrar a mensagem em um p:messages e existir o redirect, o usuário não vai nem ver. Ou seja, para isso preciso de uma janela modal (p:dialog) onde o usuário receba a mensagem “Estab. cadastrado com sucesso” e depois de clicado no botão ok, ocorra o redirect. Só que se eu fizer via facesmessage mostrando nesta janela modal e com o redirect no managedbean, essa mensagem não é mostrada pelo motivo que comentamos (escopo request).

Hoje a noite vou realizar 2 tentativas.

  1. Uma é realizar a utilização do facesMessage para mostrar a mensagem porém o redirect vou tentar inserir direto no evento do botão ok do p:dialog;
  2. Utilizar a exibição personalizada de mensagens de acordo com o atributo que criei exibeDialog (o porém desta alternativa é o controle que é muito trabalhoso).

Sds,
Rodrigo

F

Vou perguntar de novo…
Pq vc ta usando redirect ou invés de usar o padrão forward?

C

rbortolon, pelo q to entendendo do seu problema, simplesmente nao tem como fazer, (exibir uma mensagem em uma pagina, e em seguida mudar de pagina), é normal a mensagem sumir, vc saiu da pagina que ela foi exibida… e usar esse atributo de controle (q diz se foi salvo com sucesso ou não) para exibir a mensagem na pagina de pesquisa invés de exibir na pagina de cadastro, na minha opinião nao tem nd de mais, e é correto, é uma lógica de programação q vc usou pra resolver um problema… eu acho q teria feito dessa forma tbem se precisasse de algo assim…

F

Eu ja acho que vc não optou pela melhor opção, uma vez que não existe justificativa arquitetural que viabilize seu uso de redirect!
Coloque redirect é use o mecanismo de mensagem do JSF.
redirect é ruim é todos os sentidos como ja descritos aqui…

R

Ola amigos,

Fernando, o uso do redirect eu preciso utilizar pois minha url não pode continuar a mesma.

Exemplo:

  1. page1?faces-redirect=true" value="Page1" />

Ou o que eu utilizei com um método de navegação onde eu redireciono para pagina especifica

  1. FacesContext.getCurrentInstance().getExternalContext().redirect(pageName.toString());

Se eu usar o forward, ok, eu entendo o que quis dizer mas no caso por exemplo de minha lista de estabelecimentos onde eu clico em um registro e eu quero q apareça na URL a injeção dos parâmetros, eu utilizeo o redirect como no exemplo 1. No managed Bean eu recebo os dados da classe converter e a url ficará com o parametro que preciso.

Mas o que realmente estava com problemas era na questão de mostrar a mensagem e logo após redirecionar ao clicar no botão da mensagem. Como informei anteriormente, tive que criar uma lógica no mb seguindo o exemplo contido no link abaixo. Está funcionando ok.

Se alguém precisar, taí !

Obrigado a todos,
Rodrigo Bortolon

T

Parabens pela discussão rica em detalhes quanto a implementação do filtro + phaseListeners. Muito bom!

T

Cara eu testei aqui e o Filtro é disparado SEMPRE. O JSF faz as requisicoes do tipo post normalmente e no forward para uma outra pagina o filtro é acionado.

K

Excelente discussão. Como o ThiagoInGuj já mencionou, muito rica. Parabéns ao “FernandoFranzini” e ao “cleiton herrmann”. Só voltando aos pormenores referentes à configuração de regras de navegação com o faces-config, existe possibilidade de se definir essas regras sem ter a necessidade de se criar este arquivo de configuração (nem mesmo para definir o lifecycle do phaselistener)?

B
Phase listerner de RENDER_RESPONSE é executado somente depois da ação do bean...#{bean.acao}!!!!!! Se caso o usuario não estiver logado ou expirar a sessão dele....se ele clickar no botão da GUI o sistema vai executar a ação do botão e depois disso de sera enviado a pagina de login. E nós não queremos isso né...
Não precisa implementar dois PhaseListener, basta invocar o método
FacesContext.getCurrentInstance().responseComplete()
na chamada do método
beforePhase(PhaseEvent event)
, deste modo a execução da ação é aborta e o método não é executado.

Segue abaixo o exemplo:

abstract class Authorization {

	/**
	 * Paginas que nao necessitam que o usuario esteja autenticado para
	 * exibicao.
	 */
	private static final String[] pages = new String[] { "accessdenied.xhtml" };

	protected void checkBeforePhase() {
		FacesContext fc = FacesContext.getCurrentInstance();
		HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
		HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();

		if (requireAuthorization(request.getPathInfo())) {
			return;
		}

		LoginMB loginMB = (LoginMB) request.getSession(true).getAttribute("loginMB");
		if (ParamUtil.isNull(loginMB)) {
			try {
				request.getSession(true);
				response.sendRedirect(request.getContextPath() + "/faces/pages/error/accessdenied.xhtml");
				/*
				 * Aborta a requisicao.
				 */
				fc.responseComplete();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Verifica se a pagina solicitada necessida que o usuario esteja
	 * autenticado na aplicacao.
	 * 
	 * @param path
	 *            Url da pagina solicitada.
	 * @return <code>true</code> necessida de autenticacao, <code>false</code>
	 *         caso contrario.
	 */
	private boolean requireAuthorization(String path) {
		for (String s : pages) {
			if (path.contains(s)) {
				return false;
			}
		}
		return true;
	}
}

public class RestoreViewPhase extends Authorization implements PhaseListener {

	@Override
	public void afterPhase(PhaseEvent event) {
		
	}

	@Override
	public void beforePhase(PhaseEvent event) {
		checkBeforePhase();
	}

	@Override
	public PhaseId getPhaseId() {
		return PhaseId.RESTORE_VIEW;
	}
}
Criado 19 de julho de 2011
Ultima resposta 6 de jun. de 2013
Respostas 33
Participantes 6