Posts filed under 'Uncategorized'

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

1 comment Setembro 29, 2008

“A ordem das cláusulas altera o resultado”

Sempre acreditei que a ordem das cláusulas numa consulta comum não interfere em nada no resultado. Porém, passei um dia investigando uma consulta que estava dando erro. A correção veio como de uma simples alteração na ordem das cláusulas. Difícil acreditar, né?
Esse erro aconteceu no Oracle, ao chegar em casa fui testar em outro e banco e pimba, aconteceu novamente. No SqlServer aconteceu o erro, já no mysql não consegui retratar.

Chega de embromação e vamos ao erro.
Vamos criar um simples tabela.

CREATE TABLE [tabela] (
[TIPO] [varchar](1),
[valor] [varchar] (3)
)

Na primeira coluna armazenaremos o tipo de dado que tem na seguda.

insert into tabela1 (tipo, valor) values (‘N’, ‘1′);
insert into tabela1 (tipo, valor) values (‘N’, ‘2′);
insert into tabela1 (tipo, valor) values (‘A’, ‘A’);
insert into tabela1 (tipo, valor) values (‘A’, ‘B’);

Agora uma simples consulta do tipo:

select * from tabela1
where 1=1
and convert(numeric, valor) > 0
and tipo = ‘N’

Gera o seguinte resultado:

Server: Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.

Mas mudando a ordem para :

select * from tabela1
where 1=1
and tipo = ‘N’
and convert(numeric, valor) > 0

Obtemos:

TIPO valor
—- —–
N 1
N 2
(2 row(s) affected)

Ou no Oracle:

select * from tabela
where 1=1
and to_number(valor) > 0
and tipo = ‘N’

Detalhes: Isso aconteceu na versão do Oracle do trabalho e não na versão da minha casa.

Qual a possível explicação?
O mais perto que conseguimos acreditar, é no famoso curto circuito que estudamos em PD1. Ou seja, as cláusulas são avaliadas em algum sentido (no sqlserver de cima para baixo e no oracle de baixo para cima) e quando encontram alguma expressão que é falsa, ele já descarta o registro que está sendo avaliado. No nosso caso ele corre o risco de gerar um erro antes da primeira cláusula falsa, o que corre o risco de parar todo um processamento envolvido.

Soluções?

Fazer subconsultas para que não corra o risco de encontrar um erro, causa overhead mas não causa erro.

Outra coisa que aprendi sobre esse assunto, é que a ordem das tabelas no FROM da consulta também interfere em algumas consultas. Pelo menos no oracle ele olha as tabelas de trás para frente, então o ideal é colocar as tabelas com menos registros no final da lista, para que ele possa diminuir o trabalho de juntar tudo.

Estou a espera de melhores explicações e melhores soluções.

[]’s

1 comment Agosto 27, 2008

Hello Blog!

Agora tenho um blog. Grande merda. Pretendo colocar dicas e descobertas do mundo da programação (leia-se java) e outras coisas da computação.

[]’s

1 comment Agosto 27, 2008


Calendar

Novembro 2009
S T Q Q S S D
« Set    
 1
2345678
9101112131415
16171819202122
23242526272829
30  

Posts by Month

Posts by Category