Problema no cadastro de novo usuario. JSF 2 JPA 2

17 respostas
F

Boa Tarde gente,

Fiz um cadatros simples de Usuarios no JSF 2.

Depois de testar um pouco, vi que depois que eu cadastro um usuario novo se eu atualizar a pagina aparece aquela janela que pede para reenviar os dados e assim acaba duplicando meu usuario na base…

Vocês podem me falar um jeito de contornar essa situação?

Valeuu…Abraços

17 Respostas

Ace

Fala, Felipe Moraes
Faça uma requisição via ajax, assim vc resolve este problema…!

vlw

FernandoFranzini

Felipe Moraes:
Boa Tarde gente,

Fiz um cadatros simples de Usuarios no JSF 2.

Depois de testar um pouco, vi que depois que eu cadastro um usuario novo se eu atualizar a pagina aparece aquela janela que pede para reenviar os dados e assim acaba duplicando meu usuario na base…

Vocês podem me falar um jeito de contornar essa situação?

Valeuu…Abraços


Normal amigo…“atualizar a pagina” para o navegador nada mais é que enviar o mesmo pedido anterior enviado!! Se o ultimo foi um cadastro, transação bancaria…JA ERA!!
bem vindo a WEB! kkkkk
Para contornar isso em processos transacionais use o pattern velho de guerra - SINCRONIZED TOKEN
http://www.refactoring.com/catalog/introduceSynchronizerToken.html

F

[quote=FernandoFranzini]

Felipe Moraes:
Boa Tarde gente,

Fiz um cadatros simples de Usuarios no JSF 2.

Depois de testar um pouco, vi que depois que eu cadastro um usuario novo se eu atualizar a pagina aparece aquela janela que pede para reenviar os dados e assim acaba duplicando meu usuario na base…

Vocês podem me falar um jeito de contornar essa situação?

Valeuu…Abraços


Normal amigo…“atualizar a pagina” para o navegador nada mais é que enviar o mesmo pedido anterior enviado!! Se o ultimo foi um cadastro, transação bancaria…JA ERA!!
bem vindo a WEB! kkkkk
Para contornar isso em processos transacionais use o pattern velho de guerra - SINCRONIZED TOKEN
http://www.refactoring.com/catalog/introduceSynchronizerToken.html

Fernando, eu li os links que você mandou e dei uma pesquisada também e vi que o JSF 2 implementa já esse pattern…você sabe como eu faço para usar ele…ou eu realmente preciso implementar ele?

valeu

F

Ace:
Fala, Felipe Moraes
Faça uma requisição via ajax, assim vc resolve este problema…!

vlw

Ace, eu testei como você falou…e realmente resolve…só que eu acho que não é o jeito mais certo de tratar do problema…vou ver se consigo usando o synchronizer pattern como o FernandoFranzini falou…

Vlw

FernandoFranzini

Ace:
Fala, Felipe Moraes
Faça uma requisição via ajax, assim vc resolve este problema…!
vlw

O Ajax foi feito para fazer interações assíncronas com o servidor…se seu caso couber dentro do contexto do AJAX…resolve sim…pq o navegador não armazena as chamadas AJAX…mas se seu processo não tem AJAX não vai ser isso q justificara o uso !
Usar AJAX em processos q não precisa de chamada assíncronas pode gerar outros complicadores aia no sistema.

FernandoFranzini

Aonde vc leu que JSF já faz isso? Acho que não…

F

Realmente Fernando, eu li errado…eu li que ele suporta…mas não diz que é nativo…erro meu…foi mal

FernandoFranzini

Pois é…seria é uma boa se tivesse especificação para isso…mas ainda não!
Bom, partindo do que os managed beans podem ficar na sessão, usar syncronized token é facil…vc pode usar String, Boolean ou até um objeto especifico para controlar isso…
Vc tem alguma duvida de como fazer?

F

FernandoFranzini:
Pois é…seria é uma boa se tivesse especificação para isso…mas ainda não!
Bom, partindo do que os managed beans podem ficar na sessão, usar syncronized token é facil…vc pode usar String, Boolean ou até um objeto especifico para controlar isso…
Vc tem alguma duvida de como fazer?

Pra falar a verdade tenho…rsrs

eu até procurei algum exemplo na internet…mas todos usavam JSF 1 que eu não entendo nada…eu tava querendo alguma coisa mais simples…

você poderia me passar um exemplo???

FernandoFranzini

Estamos aqui para ajudar felipe…não se acanhe kkkkk
A coisa é bem simples…
1)Antes de vc entrar na tela de cadastro ai, vc atribui true para um boolean…tipo dentro action da chamada do menu que antecede o processo, ou na GUI anterior.
2)Quando o usuário gravar o registro…vc verifica a variável é true dentro de if…se for ele pode gravar…
3)Depois de gravar, vc atribuí false para essa boolean ai.
4)Caso o usuário duplique o request…vai estar false na variável e o código vai se desviado…com isso vc pode enviar uma mensagem de erro para o usuario ou tomar suas devidas medidas de acordo com a filosofia do seu sistema.
OBS - managed bean tem que estar na sessão.

F

FernandoFranzini:
Estamos aqui para ajudar felipe…não se acanhe kkkkk
A coisa é bem simples…
1)Antes de vc entrar na tela de cadastro ai, vc atribui true para um boolean…tipo dentro action da chamada do menu que antecede o processo, ou na GUI anterior.
2)Quando o usuário gravar o registro…vc verifica a variável é true dentro de if…se for ele pode gravar…
3)Depois de gravar, vc atribuí false para essa boolean ai.
4)Caso o usuário duplique o request…vai estar false na variável e o código vai se desviado…com isso vc pode enviar uma mensagem de erro para o usuario ou tomar suas devidas medidas de acordo com a filosofia do seu sistema.
OBS - managed bean tem que estar na sessão.

Vamos por partes então…por enquanto, minha aplicação só tem a tela de cadastro…então eu teria que colocar um filtro para setar uma variavel com um boolean na seção?

e depois no managed bean recuperar esse boolean e na hora de adicionar…eu checaria se a variavel era true e adicionava?..é isso??

FernandoFranzini

Vamos por partes então...por enquanto, minha aplicação só tem a tela de cadastro...então eu teria que colocar um filtro para setar uma variavel com um boolean na seção?
Sim....mas fazer um filtro só para isso é pura bobeira....na verdade vc tem que setar true quando o usuario entrar no cadastro!!! Normalmente via menu....

e depois no managed bean recuperar esse boolean e na hora de adicionar...eu checaria se a variável era true e adicionava?...é isso??
A variável boolean deve ESTAR no managed bean que ele tb deve estar na sessão.

Outra coisa que eu esqueci...o método da action do managed bean deve ser sinchronized evitando múltiplos http request entrar ao mesmo tempo....

public class ManagedBeanTal {

private boolean emGracavao;

public synchronized void gravar() {
    if (emGracavao) {
         //chamar sua gravação....
         emGracavao = false;
    } else {
        // enviar mensagem de erro para o usuario
    }
}

E por ai vai....

F

FernandoFranzini:
Vamos por partes então…por enquanto, minha aplicação só tem a tela de cadastro…então eu teria que colocar um filtro para setar uma variavel com um boolean na seção?
Sim…mas fazer um filtro só para isso é pura bobeira…na verdade vc tem que setar true quando o usuario entrar no cadastro!!! Normalmente via menu…

Não entendi essa parte…por exemplo logo que o usuario acessar a tela de cadastro, o ManagedBean de cadastro vai ser instanciado certo?..então eu colocaria

token = true;

dentro do construtor do Managed Bean???

e como assim via menu???

FernandoFranzini

Construtir nãoooooo!! Dai o pattern nao funciona!
vc vai atribuir TRUE nela quando o usuário indicar que esta entrando para fazer a operação gravar!! Normalmente é de um menu!
pensa assim…como sua aplicação vai saber que é para mostrar a tela de cadastro?
Quando o usuario click no menu “CADASTRO TAL”…dai vc faz um action

F

FernandoFranzini:
Construtir nãoooooo!! Dai o pattern nao funciona!
vc vai atribuir TRUE nela quando o usuário indicar que esta entrando para fazer a operação gravar!! Normalmente é de um menu!
pensa assim…como sua aplicação vai saber que é para mostrar a tela de cadastro?
Quando o usuario click no menu “CADASTRO TAL”…dai vc faz um action

Então…a única hora que eu sei que é para cadastrar…é quando o usuario clica no botão “Adiciona”…pq eu realmente só fiz o cadastro até agora…bem básico…

Vou colocar aqui o que eu fiz até agora…

cadastro.xhtml:

<!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:ui="http://java.sun.com/jsf/facelets" 
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:f="http://java.sun.com/jsf/core">

<h:head>
</h:head>
<h:body>
	<h:form>
		<h:panelGrid columns="2">
			<h:outputLabel value="Usuario" />
			<h:inputText value="#{cadastroMB.usuario.nome}" />
			<h:outputLabel value="Senha" />
			<h:inputSecret value="#{cadastroMB.usuario.senha}" />
			<h:outputLabel value="Email" />
			<h:inputText value="#{cadastroMB.usuario.email}" />
			<h:commandButton value="Adiciona" action="#{cadastroMB.adiciona}" />
		</h:panelGrid>
	</h:form>
</h:body>
</html>

CadastroMB.java

package managedbeans;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.persistence.EntityManager;

import model.Usuario;

@ManagedBean
public class CadastroMB {
	@ManagedProperty(value="#{entityManager}")
	private EntityManager manager;
	
	private Usuario usuario;
	
	public CadastroMB() {
		this.usuario = new Usuario();
	}
	
	public void adiciona() {
		manager.persist(this.usuario);
		manager.flush();
		this.usuario = new Usuario();
	}

	public void setManager(EntityManager manager) {
		this.manager = manager;
	}

	public Usuario getUsuario() {
		return usuario;
	}

	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}
}

FiltroJPA.java

package filtros;

import java.io.IOException;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FiltroJPA implements Filter {

	private EntityManagerFactory factory;
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		this.factory = Persistence.createEntityManagerFactory("cadastro");	
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		EntityManager manager = this.factory.createEntityManager();
		request.setAttribute("entityManager", manager);
		manager.getTransaction().begin();
		
		chain.doFilter(request, response);
		
		try {
			manager.getTransaction().commit();
		} catch (Exception e) {
			manager.getTransaction().rollback();
		} finally {
			manager.close();
		}
	}
	
	@Override
	public void destroy() {
		this.factory.close();	
	}
}
FernandoFranzini

Sim…ta faltando o menu…
Quando vc fizer, faça o controle do booelan.

F

Agora entendi Fernando…

Valeu pela ajuda…

Criado 13 de setembro de 2011
Ultima resposta 14 de set. de 2011
Respostas 17
Participantes 3