Archive for setembro, 2008

Refresh reenviando os dados

Imagine o seguinte cenário: Você termina de preencher os campos de uma página de inclusão. Ao clicar em OK, o sistema envia o formulário e executa um forward para a página de listagem do seu cadastro com a mensagem: “Registro incluído com sucesso.”

No JSF (e imagino que em várias outras soluções MVC) quando você dá um refresh (F5), o sistema reenvia os dados que você preencheu na tela de cadastro e acaba incluindo um novo registro (ou tentando incluir, caso tenha problema com algum campo que não pode se repetir), e na atual listagem aparece dois dados iguais.

Andei pesquisando a maneira mais simples de não dar um forward após a inclusão do dado. Acabei caindo numa boa explicação do Rafael Pontes sobre a diferença entre o forward e redirect.

Vamos a solução:

Na regra de navegação, agora foi usada uma tag (<redirect />)na passagem do cadastro para a listagem:

<navigation-rule>
<from-view-id>/empresa/cadastroEmpresa.jsp</from-view-id>
<navigation-case>
<from-outcome>listagem</from-outcome>
<to-view-id>/empresa/listagemEmpresa.jsp</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>

Com isso perdemos as nossas mensagens adicionadas ao messages através do método FacesContext.getCurrentInstance().addMessage(), já que essas mensagens são válidas só por requisição. A solução para contornar esse problema foi a utilização de alguma classe que tem o escopo de sessão. A escolhida no meu caso, foi a classe de login do usuário, que é a classe que ele carrega para “provar” que é um usuário cadastrado e logado no sistema. Dentro dessa classe incluí:

private List<String> mensagens;
public void showMensagens() {
if(this.mensagens==null)
this.mensagens = new ArrayList<String>();
for(String msg : this.mensagens)
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, msg, null));
this.mensagens = new ArrayList<String>();
}


public void addMensagens(String mensagem) {
if(this.mensagens==null)
this.mensagens = new ArrayList<String>();
this.mensagens.add(mensagem);
}

e na classe ancestral dos backbeans o seguinte método:

protected void addNewMessage(String msg) {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
HttpSession session = (HttpSession) externalContext.getSession(false);
LoginCodebehind login = (LoginCodebehind) session.getAttribute("login");
login.addMensagens(msg);
}


protected void showMessages() {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
HttpSession session = (HttpSession) externalContext.getSession(false);
LoginCodebehind login = (LoginCodebehind) session.getAttribute("login");
login.showMensagens();
}

O primeiro método busca no contexto o meu objeto de sessão login e adiciona a mensagem. Esse método será chamado após uma inclusão com sucesso como por exemplo:

public void actionGravar(ActionEvent event) {
try {
EmpresaBO.getInstance().create(empresaTO);
this.addNewMessage("Empresa cadastrada com sucesso.");
} catch (RegraNegocioException e) {
e.printStackTrace();
this.addErrorMessage(e);
throw new AbortProcessingException();
}

E o segundo método será chamado pelas telas de listagem, para exibirem as mensagem quando houverem.

public ListagemEmpresa() {
try {
this.showMessages();
empresaList = EmpresaBO.getInstance().findAll();
} catch (RegraNegocioException e) {
this.addErrorMessage(e);
}
}

Esse solução foi feito para exibir somente as mensagens de sucesso, já que teoricamente são as únicas que passam de uma página para a outra. Quando houver a necessidade de exibir mensagem de erro, não deverá mudar de tela, então vai exibir no mesmo request. Mas é possível adicionar um parâmetro nas chamadas para que seja acrescentada o tipo da mensagem.

[]‘s

setembro 29, 2008 at 3:34 am 1 comentário


Calendário

setembro 2008
S T Q Q S S D
« ago   ago »
1234567
891011121314
15161718192021
22232425262728
2930  

Postagens por Mês

Posts por Categoria


Seguir

Obtenha todo post novo entregue na sua caixa de entrada.