Inicial > programação, programação JSF > Implementando converter e validator de CNPJ

Implementando converter e validator de CNPJ

Dando continuidade ao assunto anterior, vou agora mostrar como criar converter e validator de CNPJ. Lembrando que a lógica de validação/conversão vai estar completamente inserida dentro das classes que implementam javax.faces.convert.Converter e javax.faces.validator.Validator. Aqui no meu trabalho colocamos essa lógica em classes Java separadas. Geramos um jar com essas classes e então colocamos esse jar no classpath da aplicação, evitando replicação de código.

Se você deseja entender melhor o que é um converter ou um validator, ou como eles funcionam, consulte meu post anterior aqui.


Vamos aos exemplos práticos:

  • A Classe Java de Conversão de CNPJ:

package br.com.conversor;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

/**
* Conversor de CNPJ.
*
* @author Pablo Nóbrega
*/
public class CnpjConverter implements Converter {
     public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
         /*
          * Irá converter CNPJ formatado para um sem pontos, traço e barra.
          * Ex.: 07.374.998/0001-33 torna-se 07374998000133.
          */
          String cnpj = value;
          if (value!= null && !value.equals(""))
               cnpj = value.replaceAll("\\.", "").replaceAll("\\-", "").replaceAll("/", "");

          return cnpj;
     }

     public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException {
         /*
          * Irá converter CNPJ não formatado para um com pontos, traço e barra.
          * Ex.: 07374998000133 torna-se 07.374.998/0001-33.
          */
          String cnpj = value;
          if (cnpj != null && cnpj.length() == 14)
              cnpj = cnpj.substring(0, 2) + "." + cnpj.substring(2, 5) + "." + cnpj.substring(5, 8 ) + "/" + cnpj.substring(8, 12) + "-" + cnpj.substring(12, 14);

          return cnpj;
     }
}

  • Declarando o converter de CNPJ no faces-config:

<converter>
     <converter-id>converter.CnpjConverter</converter-id>
     <converter-class>br.com.converter.CnpjConverter</converter-class>
</converter>

  • Para fazer a chamada do converter de CNPJ em um campo texto:
<h:outputText value="CNPJ: " />
<h:outputText value="#{cliente.cnpj}">
     <converter converterId="converter.CnpjConverter" />
</h:outputText>

Com esse código, o trecho da página aparecerá da seguinte forma:

CPF: 05.371.845/0001-24

Vale ressaltar que estamos levando em conta que o valor original do CNPJ está com 14 dígitos e sem nenhum caractere delimitando grupos de números.


  • A Classe Java de Validação de CNPJ:

package br.com.validator;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import java.util.ResourceBundle;

/**
* Validação de CNPJ.
*
* @author Pablo Nóbrega
*/
public class CnpjValidator implements Validator {
     @Override
     public void validate(FacesContext arg0, UIComponent arg1, Object valorTela) throws ValidatorException {
          if (!validaCNPJ(String.valueOf(valorTela))) {
               FacesMessage message = new FacesMessage();
               message.setSeverity(FacesMessage.SEVERITY_ERROR);
               message.setSummary(ResourceBundle.getBundle(FacesContext.getCurrentInstance().getApplication().getMessageBundle()).getString("erro.validacao.cnpj"));
               throw new ValidatorException(message);
          }
     }

     /**
     * Valida CNPJ do usuário.
     *
     * @param cnpj String valor com 14 dígitos
    */
     public static boolean validaCNPJ(String cnpj) {
          if(cnpj == null || cnpj.length() != 14)
               return false;

          try {
               Long.parseLong(cnpj);
          } catch (NumberFormatException e) { // CNPJ não possui somente números
               return false;
          }

          int soma = 0;
          String cnpj_calc = cnpj.substring(0, 12);

          char chr_cnpj[] = cnpj.toCharArray();
          for(int i = 0; i < 4; i++)
               if(chr_cnpj[i] - 48 >= 0 && chr_cnpj[i] - 48 <= 9)
                    soma += (chr_cnpj[i] - 48) * (6 - (i + 1));

         for(int i = 0; i < 8; i++)
              if(chr_cnpj[i + 4] - 48 >= 0 && chr_cnpj[i + 4] - 48 <= 9)
                    soma += (chr_cnpj[i + 4] - 48) * (10 - (i + 1));

         int dig = 11 - soma % 11;
         cnpj_calc = (new StringBuilder(String.valueOf(cnpj_calc))).append(dig != 10 && dig != 11 ? Integer.toString(dig) : "0").toString();
         soma = 0;
         for(int i = 0; i < 5; i++)
              if(chr_cnpj[i] - 48 >= 0 && chr_cnpj[i] - 48 <= 9)
                   soma += (chr_cnpj[i] - 48) * (7 - (i + 1));

         for(int i = 0; i < 8; i++)
              if(chr_cnpj[i + 5] - 48 >= 0 && chr_cnpj[i + 5] - 48 <= 9)
                   soma += (chr_cnpj[i + 5] - 48) * (10 - (i + 1));

         dig = 11 - soma % 11;
         cnpj_calc = (new StringBuilder(String.valueOf(cnpj_calc))).append(dig != 10 && dig != 11 ? Integer.toString(dig) : "0").toString();

         return cnpj.equals(cnpj_calc);
     }
}

  • Declarando o validator de CNPJ no faces-config:

<validator>
     <validator-id>validator.CnpjValidator</validator-id>
     <validator-class>br.com.validator.CnpjValidator</validator-class>
</validator>

  • Para fazer a chamada do validator de CNPJ em um campo do formulário:

<h:inputText value="#{cliente.cnpj}" required="true" maxlength="14">
     <f:validator validatorId="validator.CnpjValidator" />
</h:inputText>

  • Por fim, precisamos colocar no bundle a mensagem de erro de validação de CNPJ:

erro.validacao.cnpj=CNPJ inválido.

  • E uma chamada ao h:messages na página em que o validator está inserido, conforme exemplo abaixo, para que o erro seja exibido:

<h:messages />;

A imagem abaixo mostra o erro exibido ao usuário quando um CNPJ inválido é fornecido pelo usuário em um dos sistemas da nossa empresa.

CNPJ Inválido

CNPJ Inválido

Anúncios
  1. 01/09/2009 às 12:46

    Olá Pablo, muito bom tópico. Gostaria de deixar aqui a indicação de um framework brasileiro feito para resolver problemas de brasileiros. O Stella Framework desenvolvido pelo pessoal da Calum. Ele tem validação de CPF, IE, CNPJ, geração de boleto, e muito mais. Endereço: http://stella.caelum.com.br/; Ele já é integrado com jsf e possui esse validadores e conversores que você fez na mão. Abraços.

    • 01/09/2009 às 13:41

      Olá Paulo. Não tinha conhecimento. É muito bom saber disso. Obrigado pelo elogio e pela indicação.

  2. Cristiano
    01/11/2010 às 23:33

    onde eu coloco isso mesmo

    erro.validacao.cnpj=CNPJ inválido. ????

    • 03/11/2010 às 09:19

      Isso você tem que colocar no Resource Bundle, ou seja no arquivo .properties da sua aplicação.

  3. Lesliê Cardoso da Silva
    06/11/2010 às 22:43

    Olá Paulo. Obrigado por compartilhar!
    Gostaria de saber se já implementou no eclipse o Resource Bundle? Pois bati cabeça o maior tempão e descobrir que da erro se passar o nome do resource com pontos.
    Enfim quando pensei que havia solucionado o problema quando clico em inserir ocorre a seguinte mensagem:
    HTTP Status 500 –

    type Exception report

    message

    description The server encountered an internal error () that prevented it from fulfilling this request.

    exception

    javax.servlet.ServletException: javax.faces.validator.ValidatorException: O cpf informado é inválido! Por favor regularize e tente novamente.
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:321)

    root cause

    javax.faces.el.EvaluationException: javax.faces.validator.ValidatorException: O cpf informado é inválido! Por favor regularize e tente novamente.
    javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:98)
    com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:98)
    javax.faces.component.UICommand.broadcast(UICommand.java:311)
    javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:781)
    javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1246)
    com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:77)
    com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
    com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)

    Então resolvi mexer com o netbeans que com os pontos ele acha mas ocorre esse erro:

    HTTP Status 500 –

    type Exception report

    message

    descriptionThe server encountered an internal error () that prevented it from fulfilling this request.

    exception

    javax.servlet.ServletException: [Ljava.lang.Object; cannot be cast to com.sun.faces.application.view.StateHolderSaver
    root cause

    java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.sun.faces.application.view.StateHolderSaver
    note The full stack traces of the exception and its root causes are available in the GlassFish Server Open Source Edition 3.0.1 logs.

    • 07/11/2010 às 11:49

      Oi Lesliê. Pelo que você postou no código do Eclipse foi encontrado o erro no bundle. Tanto é que o texto com o erro foi mostrado. O que talvez tenha faltado foi o componente que exibe o erro. Você colocou h:messages na página que valida o CPF? Se quiser saber como criar Resource Bundle, veja esse link. Abraço.

  4. lucas
    29/11/2010 às 10:25

    soma += (chr_cnpj[i + 5] – 48) * (10 – (i + 1));

    Alguem pode me explicar porque subtrair 48 nesse algoritimo.. sei que é por causa do tochararray mas gostaria de uma explicação do porque dessa gambi

  5. Ricardo Johannsen
    20/09/2012 às 19:03

    Olá Pablo.Tenho um CNPJValidator na minha aplicação que verifica se o cnpj é valido e verifica se o cnpj já consta na base de dados caso sim é disparado o erro.Funciona perfeitamente para salvar ,mas não consigo alterar o registro pois na hora de fazer a validação o cnpj do cliente já está no banco e ele acusa o erro de duplicidade de cnpj,como proceder nesses casos?

    • 20/09/2012 às 19:15

      Ricardo, uma saída é utilizar dois inputs. Um para ser exibido quando o objeto não tiver ainda sido salvo (com o validator) e outro na atualização. Nesse caso você usa o atributo rendered.

  6. 07/12/2012 às 15:56

    Olá Pablo, parabéns pelo blog tem ajudado muito. Nessa sua classe de validação de CNPJ você não mostrou a implementação da classe FormatoCNPJException, poderia me enviar ou comentá-la se possível?

    • 07/12/2012 às 17:31

      Olá Jader.

      Na verdade essa classe não é mais necessária. Tinha apenas que corrigir uma parte do código no post. Verifica lá. Abraço.

  7. Leonardo
    23/01/2013 às 10:28

    Ricardo Johannsen :
    Olá Pablo.Tenho um CNPJValidator na minha aplicação que verifica se o cnpj é valido e verifica se o cnpj já consta na base de dados caso sim é disparado o erro.Funciona perfeitamente para salvar ,mas não consigo alterar o registro pois na hora de fazer a validação o cnpj do cliente já está no banco e ele acusa o erro de duplicidade de cnpj,como proceder nesses casos?

    Olá Ricardo, bom dia!
    Estou precisando exatamente disso que você comentou que tem. Verificar se é válido e verificar se já existe na base.
    Poderia me mostrar como você implementou isso? Estou utilizando JSF 2.0 com Primefaces e Hibernate no desenvolvimento do sistema!

    Desde já agradeço pela atenção.

    • 23/01/2013 às 11:12

      Ricardo,

      Não recomendo que você utilize essa lógica de acesso ao banco para verificar se um CNPJ já existe ou não dentro de um Validator. Um dos problemas pode ser exatamente esse. Se mesmo assim você quiser deixar o sistema dessa forma, tem algumas soluções para esse caso: 1. Se estiver usando o JSF 2, utilize o atributo disabled para desabilitar a validação se for um update. Vc vai colocar algo como disabled=”#{clienteBean.cliente.idClientes != null}”. 2. Usar dois Inputs. Um com o validator dentro e o atributo rendered=”#{clienteBean.cliente.idClientes == null}” e o outro sem validação com o rendered=”#{clienteBean.cliente.idClientes != null}”. 3. Usar <f:param /> ou <f:attribute /> dentro do <f:validator /> e recuperar esse valor para verificar se vai testar se o CNPJ já existe ou não no banco.

      Estou à disposição.

      Pablo.

    • Ricardo
      23/01/2013 às 13:36

      oi Leandro, estou no trabalho tenho essa implementação no pc em casa vou procurar e posto aqui, fws!!

      • Leonardo
        23/01/2013 às 14:08

        Muito obrigado…

        fico no aguardo!!

  8. Ricardo Johannsen
    31/01/2013 às 22:22

    Leonardo o código em JSF eu não achei,mas tenho um aqui no zk, alógica é a mesma,primeiramente defini no banco e no mapeamento que o atributo cnpj seja unique(nos 2 lugares apenas pra garantir), qdo clico no link na pagina de listar e vou para a página de alterar eu carrego o cliente e seto o cpf do cliente em alguma variavel auxiliar,no momento de fazer o update eu verifico se o cpf que está no textbox/managed bean é o mesmo que está na variavel auxiliar,se for ele pula a validação se não ele vai pra verificação se o cpf é valido, se for valido ai sim ele verificase o cpf existe já existe na base, então com uma simples variavel string e 3 ifs vc resolve o problema.

    • leonardo
      01/02/2013 às 00:42

      Olá Ricardo, bom dia…poderia me enviar esse código que vc tem?…seria de muita ajuda!!…estou deste o dia do post tentando resolver isso….essa semana quase joguei a toalha…vou ver se consigo implemetar essa solução e passar por mais esse desafio…muito obrigado pela atenção!!!

  1. No trackbacks yet.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

%d blogueiros gostam disto: