Validação de CNPJ

149 views
Skip to first unread message

ricardo johannsen

unread,
Sep 19, 2012, 5:40:40 PM9/19/12
to jav...@googlegroups.com
Olá a todos!!!
Tenho na minha página de cadastro de clientes um campo cnpj  e ao submeter o for eu tenho um validator chamado CNPJValidator que verifica se o referido cnpj já se encontra cadastrado na base de dados,até ai tudo certo, o problema é na alteração de registro pois qdo ele passa pelo CNPJValidator  obvio que o cnpj já vai estar lá,ai ele disparta o erro de validação e não deixa atualizar.Como posso proceder para contornar este problema?

<h:inputText value="#{clienteBean.cliente.cnpj}" required="true"
requiredMessage="Campo CNPJ Obrigatorio">
<f:validator validatorId="br.com.ponto42.sgil.validators.CNPJValidator" />
</h:inputText>



Clayton Rocha

unread,
Sep 20, 2012, 10:57:17 AM9/20/12
to jav...@googlegroups.com
Acredito que seja muito melhor criar um CnpjValidator e colocar nesse xhtml algo do tipo

<h:inputText value="#{clienteBean.cliente.cnpj}" required="true" requiredMessage="Campo CNPJ Obrigatorio" validator="cnpjValidator"/>

vou te mostrar a minha classe:

@FacesValidator(value = "cnpjValidator")
public class CnpjValidator implements Validator {
    
    private static final Logger logger = Logger.getLogger(CnpjValidator.class);
    
    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        try {
            logger.info("entrando no método");
            logger.debug("paramenro: " + value);
            
         // aqui a regra do negócio para a validação do cnpj caso não seja valido lança uma exceção
            logger.info("Cnpj Válido");            
        } catch (Exception e) {
            logger.error(e, e);
            throw new ValidatorException(Mensageiro.getMessage(FacesMessage.SEVERITY_ERROR, "Cnpj Inválido", "Erro na validação"));
        }
    }
}

OBS: esse mensageiro e uma classe responsável de estregar as mensagens no lado do cliente

Em 20 de setembro de 2012 10:55, Savius <lsavio...@gmail.com> escreveu:
Oi Ricardo, não sou nenhum especialista mas se entendi seu problema, deve estar ocorrendo uma inversão nas responsabilidades. O ideal seria você utilizar o Validator apenas para REALMENTE validar o cnpj (se é um cnpj válido). E em outro lugar fazer a verificação da violação de unique para o cnpj.
--
Você recebeu esta mensagem por que é membro do Javasf
http://groups.google.com/group/javasf
 
Conheça também o Java Brazil: http://groups.google.com/group/thejavabrazil

ricardo johannsen

unread,
Sep 20, 2012, 12:02:37 PM9/20/12
to jav...@googlegroups.com
justo Clayton, eu tenho o meu CNPJValidator ,o problema é só na hora de alterar pois antes de salvar ou alterar ele faz uma busca na base pra verificar se o cnpj já está inserido,como ele vai estar alterando o cnpj já está lá ai dispara o erro.Savius vou tentar utilizar a abordagem sujerida. Obrigado pelas respostas.

ricardo johannsen

unread,
Sep 21, 2012, 8:40:19 AM9/21/12
to jav...@googlegroups.com
Savius anotei o cnpj na entidade cliente como unique:

@Column(name="cnpj",unique=true)
private String cnpj;

e deixei meu validator tratar apenas se o cnpj é válido,isso solucionou o problema do salvar e do alterar, o problema agora é que quando tento salvar um cnpj duplicado ele não deixa salvar mas dá um erro, o ideal é que apareça a mensagem de erro em uma
f:message e a pagina seja reexibida,como tratar esse tipo de erro?

Thiago Vulcão

unread,
Sep 21, 2012, 9:38:25 AM9/21/12
to jav...@googlegroups.com
Try Catch com SqlException ... se tiver usando Hibernate ou algo parecido acho que o erro que dispara é de SqlException.

--
 
 Thiago Vulcão
  Desenvolvedor de Sistemas Pleno - EBI Informática
  Contato: (91) 8120-1949
  MSN: thiago...@hotmail.com
  Skype: vulcaodeveloper

Thiago Vulcão

unread,
Sep 21, 2012, 10:14:21 AM9/21/12
to jav...@googlegroups.com
Opa ... sim sim ... isso é uma solução perfeita. Se deixar isso do lado do cliente é melhor ainda.

Clayton Rocha

unread,
Sep 21, 2012, 10:50:27 AM9/21/12
to jav...@googlegroups.com
Bem ...Vamos la, para essa validação que vc ta falando é mais simples ainda é só colocar um  valueChangeListener="#{seuMB.ValidaSeExisteCNPJCadastrado}" no seu input e atribuir um ajax para o evente "change" d tipo

<h:inputText value="sdbisbusbdus.sdfsd" validator="cnpjValidator" 
valueChangeListener="#{seuMB.ValidaSeHaCnpjCadastrado }"  >
 <f:ajax execute="@this" event="change" immediate="true" rendered="idDaMenssagemReferenteAoInput"/>
 ou caso use o primefaces
<p:ajax process="@this" event="change" immediate="true" update="idDaMenssagemReferenteAoInput"/>
</h:inputText>

e cria esse método no beans do tipo

   public void ValidaSeHaCnpjCadastrado(ValueChangeEvent event) {
        try {
            LOGGER.info("entrado no metodo");
          // CHAMA A REGRA PARA VERIFICAR SE EXITE  CASO EXISTIR LANÇA UMA EXCESSÃO

        } catch (Exception e) {
            Mensageiro.Msg(e, "idDoInput"); // AQUI  envia a mensagem para a tela
        }
    }





Clayton Rocha

unread,
Sep 21, 2012, 10:53:06 AM9/21/12
to jav...@googlegroups.com
acredito que não é trabalho do hibernate garantir essa restrição e sim da regra de negócio, a papel do hibernate é garantir a integridade do banco caso não seja validado na camada de negócio 

Everton Fujimoto

unread,
Sep 21, 2012, 12:59:13 PM9/21/12
to jav...@googlegroups.com
Minha opinião.

1. CNPJ não deveria mudar para a mesma entidade já gravada no banco de dados.
2. ValueChangeListener não é bom para validações desse tipo, cada tela que vc colocar a edição de CNPJ vc vai precisar colocar esse valueChangeListener e se o usuário mudar o valor por alguma forma que não seja chamada o evento change do inputText, não vai ser chamado o listener. (então pode entrar valores diferentes na base de dados)
3. É responsabilidade do SGBD manter uma constraint (isso gera um índice que inclusive torna mais rápida a consulta que filtra esse campo)
4. É responsabilidade do hibernate "espelhar" essa constraint no modelo de classes.
5. Você pode verificar, no validator ou em algum @PreUpdate / @PrePersist ou qualquer coisa do gênero, se o CNPJ mudou (compare com um cache ou uma propriedade transient, por exemplo) antes de comparar na base de dados se já existe ou não.
6. Se ainda assim você quiser comparar se o CNPJ mudou em todos os casos, pode adicionar uma restrição para que não tenha o mesmo ID do seu objeto atual:

SELECT p FROM Pessoa p WHERE p.cnpj=:cnpj AND p.id != :id

Dessa forma ele não traz o objeto atual, mesmo que o CNPJ seja o mesmo.

Att.
Everton William Fujimoto
Hecate Systems
CIO
(47)3394-5516
(47)9947-5481

ricardo johannsen

unread,
Sep 21, 2012, 1:02:50 PM9/21/12
to jav...@googlegroups.com
verdade nem estava lembrando do ValueChangeListener,vou testar.

Em 21 de setembro de 2012 11:53, Clayton Rocha <clayton.r...@gmail.com> escreveu:

Clayton Rocha

unread,
Sep 24, 2012, 11:58:52 AM9/24/12
to jav...@googlegroups.com
Boa tarde meu caro amigo, como tinha falado acredito que a regra de negócio tem que validar isso não deixando apenas para o hibernate que tem de refletir e integridade do banco. se não fosse assim, para que a regra se quando for inserir no banco vai dar erro???

sacou ?? o hibernate quem segurar a restrição também mais a principal responsabilidade é do negocio e não da camada do repositório.



Em 22 de setembro de 2012 16:04, Savius <lsavio...@gmail.com> escreveu:
Bem, em relação a validação de constraint ser ou não responsabilidade do hibernate, acho que no mínimo ele deveria SIM poder fazer essa verificação (se tem como fazer de forma simples não sei). No Grails, alguém se deu a esse trabalho de validar as constraints (e o grails usa hibernatea além de spring e outros frameworks consagrados). Se defino no meu modelo que determinado atributo é unique, já era. ele se encarrega de fazer essa verificação e mostrar uma mensagem precisa do problema que está ocorrendo.


Em quarta-feira, 19 de setembro de 2012 18h40min40s UTC-3, Ricardo Johannsen escreveu:

Rodrigo Monteiro Ferreira

unread,
Sep 24, 2012, 1:04:14 PM9/24/12
to jav...@googlegroups.com
Tambem acho que é função da camada de negócio que tem que lançar a exceção...
--
Rodrigo Monteiro
Sistemas Web
rodrigom...@gmail.com
(11) 6267-9366

Enio Nunes

unread,
Sep 24, 2012, 1:25:29 PM9/24/12
to jav...@googlegroups.com
coloca como primeiro campo do formulário o CNPJ obrigando a ser a primeira informaçãoq ue o usuário vai digitar, apos essa digitação vc pesquisa para ver se exite um cadastro com aquele cnpj, se existir vc bloqueia o fluxo ou ate mesmo carrega os dados na tela do cadastro encontrado, quanto a tela de edição nao pre

ricardo johannsen

unread,
Sep 28, 2012, 11:38:34 PM9/28/12
to jav...@googlegroups.com
Olá,gostaria de agradecer a todos pelas respostas!!! consegui resolver o problema,segue a minha solução pra quem precise:

1- defini no sgbd a constraint unique para o cpf/cnpj

2-colooquei essa constaint no meu mapeamento

  @Column(name = "cpf_cnpj",unique=true)
    private String cpf;

3- como dito em uma das respostas deixei para a camada de negocio lançar a exception em caso de duplicidade,eu pego o cnpj antigo e comparo  com o novo, se forem diferentes eu mando buscar no banco para saber se já existe

    public void update(Cliente cliente) throws BusinessException,InfraException {

        Cliente clienteToCompare = clienteDAO.find(cliente.getId());
       
        long ocorrenciasCPFCNPJ = clienteDAO.checkUniqueCpfCnpj(cliente.getCpf());
        long ocorrenciasRG = clienteDAO.checkUniqueRg(cliente.getRg());
       
        if(!cliente.getCpf().equals(clienteToCompare.getCpf())){
            if(ocorrenciasCPFCNPJ !=0){
               
                throw new BusinessException("O CPF CNPJ já está cadastrado");
           
            }   
        }
       
        if(!cliente.getRg().equals(clienteToCompare.getRg())){
            if(ocorrenciasRG !=0){
               
                throw new BusinessException("RG já cadastrado");
               
            }   
        }
       
       
        clienteDAO.update(cliente);
       
    }
4- por fim acrescentei um validator para saber se o formato do cpf/cnpj(no caso cpf) é válido

<p:inputText value="#{clienteBean.cliente.cpf}" required="true"
                        requiredMessage="Campo CPF Obrigatorio" >
                        <f:validator
                            validatorId="validators.CpfValidator" /></p:inputText>

@FacesValidator("validators.CpfValidator")
public class CpfValidator implements Validator {


    private static final int[] pesoCPF = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2};


    private static int calcularDigito(String str, int[] peso) {
        int soma = 0;
        for (int indice=str.length()-1, digito; indice >= 0; indice-- ) {
            digito = Integer.parseInt(str.substring(indice,indice+1));
            soma += digito*peso[peso.length-str.length()+indice];
        }
        soma = 11 - soma % 11;
        return soma > 9 ? 0 : soma;
    }


    @Override
    public void validate(FacesContext arg0, UIComponent arg1, Object arg2)throws ValidatorException {

        String cpf = arg2.toString();


        if ((cpf==null) || (cpf.length()!=11)){

            FacesMessage msg = new FacesMessage("O CPF deve ser formado por 11 dígitos.", "O CPF deve ser formado por 11 dígitos.");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new ValidatorException(msg);

        }else{

            Integer digito1 = calcularDigito(cpf.substring(0,9), pesoCPF);
            Integer digito2 = calcularDigito(cpf.substring(0,9) + digito1, pesoCPF);
            boolean isValido = cpf.equals(cpf.substring(0,9) + digito1.toString() + digito2.toString());
            if(!isValido){

                FacesMessage msg = new FacesMessage("O CPF informado é inválido.", "O CPF informado é inválido.");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                throw new ValidatorException(msg);   
            }

        }


    }





}

Vlw pela força galera!
Reply all
Reply to author
Forward
0 new messages