[Resolvido] NullPointerException no validator.checking

30 respostas
Guevara

E ai pessoal!
Fiz uma busca aqui e coloquei no validator.checking todas as possibilidades dos parâmetros virem nulos, a idéia é que se o usuário apertar o botão “enviar” sem digitar nada, retorne a mensagem de “busca vazia, insira algum parâmetro para efetuar a busca”.
Porém, estou tomando NullPointerException ao testar o enviar sem digitar nada, o validator não está funcionando:

public void resultado(final Imovel imovel, final BigDecimal valorMin, final BigDecimal valorMax) {	
		validator.checking(new Validations() {
			{
				that(!(imovel.equals(null) &&	
					imovel.getEndereco().equals(null) &&
					imovel.getQuartos() == null &&
					imovel.getEndereco().getBairro().isEmpty() || imovel.getEndereco().getBairro().equals("")  &&
					imovel.getEndereco().getCidade().isEmpty() || imovel.getEndereco().getCidade().equals("")  &&
					imovel.getEndereco().getEstado().isEmpty() || imovel.getEndereco().getEstado().equals("") &&
					valorMin == null &&
					valorMax == null), "imovel.vazio","buscaVazia.obrigatorio");					
			}
		});
		validator.onErrorRedirectTo(this).busca();			
		result.include("imoveis", imovelDAO.busca(imovel, valorMin, valorMax));
	}

Alguém consegue visualizar onde está o erro?
Abraço!

30 Respostas

Lucas_Cavalcanti

xxxx.equals(null) dá nullpointer se xxxx for null

troque por xxxx == null

Lucas_Cavalcanti

outra coisa:

imovel.getEndereco().getBairro().isEmpty()

é a mesma coisa que

imovel.getEndereco().getBairro().equals("")

vc não precisa fazer os dois

Guevara

Valeu Lucas!
Fiz as alterações:

@SuppressWarnings("null")
	public void resultado(final Imovel imovel, final BigDecimal valorMin, final BigDecimal valorMax) {	
		validator.checking(new Validations() {
			{
				that((imovel == null &&	
					imovel.getEndereco().equals("") &&
					imovel.getQuartos() == null &&
					imovel.getEndereco().getBairro().equals("")  &&
					imovel.getEndereco().getCidade().equals("")  &&
				    imovel.getEndereco().getEstado().equals("") &&
					valorMin == null &&
					valorMax == null), "imovel.vazio","buscaVazia.obrigatorio");					
			}
		});
		validator.onErrorRedirectTo(this).busca();			
		result.include("imoveis", imovelDAO.busca(imovel, valorMin, valorMax));
	}

O lance agora é que sem a negação no that a busca não é efetuada preenchendo ou não o form, e com a negação o validator deixa passar a busca mesmo sem preencher nenhum parâmetro, retorna tudo que está no banco. =/
[]s

Lucas_Cavalcanti

no that vc coloca o que vc quer que seja verdade, ou seja, o que vc quer garantir antes de fazer qqer coisa no método.

vc pode chamar o that várias vezes

Guevara

Consultei a apostila FJ-28 e fiz como está lá, mas não adiantou, eu preciso que a mensagem seja mostrada apenas se o usuário não preencher nada no form e apertar o enviar.

public void resultado(final Imovel imovel, final BigDecimal valorMin, final BigDecimal valorMax) {	
		
		if ((imovel.getQuartos() == null &&
				imovel.getEndereco().getBairro() == null &&
				imovel.getEndereco().getCidade() == null &&
			    imovel.getEndereco().getEstado() == null &&
				valorMin == null &&
				valorMax == null)) {
		    validator.add(new ValidationMessage(
		            "Informe algum parâmetro para efetuar a busca", "busca.vazia"));
		}

		
		/*validator.checking(new Validations() {{
            that((imovel.getQuartos() != null &&
                    !imovel.getEndereco().getBairro().isEmpty() &&
                    !imovel.getEndereco().getCidade().isEmpty()) &&
                    !imovel.getEndereco().getEstado().isEmpty() &&
                    valorMin != null &&
                    valorMax != null, "imovel.vazio","buscaVazia.obrigatorio");                    
            }
        });*/
		validator.onErrorRedirectTo(this).busca();			
		result.include("imoveis", imovelDAO.busca(imovel, valorMin, valorMax));
	}

Tentei da maneira clássica e da maneira fluente, ou ele bloqueia tudo, preenchendo ou não, ou ele deixa passar tudo.
[]s

Guevara

Esta validação não funciona, retorna tudo que está no banco:

if (imovelDAO.busca(imovel, valorMin, valorMax).isEmpty()) {
		    validator.add(new ValidationMessage(
		            "Informe algum parâmetro para efetuar a busca", "busca.vazia"));
		}

O.o

Lucas_Cavalcanti

o que é string vai vir como “”, não como null

cria esse método:

private boolean checkaParametros(final Imovel imovel, final BigDecimal valorMin, final BigDecimal valorMax) {

   if (valorMin != null || valorMax != null) return true;

   if (imovel == null) return false;

   if (imovel.getQuartos() != null) return true; //se for string vê por vazio tb

   if (imovel.getEndereco() == null) return false;

   Endereco endereco = imovel.getEndereco();
   return !StringUtils.isBlank(endereco.getBairro()) 
           || !StringUtils.isBlank(endereco.getCidade()) 
           || !StringUtils.isBlank(endereco.getBairro());
}

e ve se esse checka retorna true

Guevara

Descobri o que está causando o problema, só não entendi o motivo. Se eu remover o estado e cidade que são comboxes eu não tenho problemas, se eu colocar na validação dá erro, deixei assim:

if((imovel.getQuartos() == null && imovel.getEndereco().getBairro().equals("") && imovel.getEndereco().getBairro().equals("") &&
		imovel.getEndereco().getCidade().equals("") && imovel.getEndereco().getEstado().equals("") &&	
		valorMin == null && valorMax == null)) { validator.add(new ValidationMessage(
	            "Informe algum parâmetro para efetuar a busca", "busca.vazia"));				
		}

Se der o enviar sem digitar nenhum parâmetro, o erro é:

root cause

java.lang.NullPointerException
	br.com.imobiliaria.controller.IndexController.resultado(IndexController.java:134)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	java.lang.reflect.Method.invoke(Method.java:597)

Eu preciso validar imovel e imovel.getEndereco() tb ?

Lucas_Cavalcanti

se vc não mandar nenhum parametro q começa com “imovel.” imóvel vai ser null, e se não tiver nenhum que começa com imovel.endereco, o endereço vai ser nulll

Guevara

Aí é que está, tenho imovel.endereco.bairro que é um input, e imovel.endereco.cidade e imovel.endereco.estado que são combos, se eu remover cidade e estado da validação, a validação funciona, se eu colocar os dois na validação, dá nullPointerException,se imovel está indo null, o imovel.endereco.bairro deveria provocar o nullPointerExeception tb. Ou seja, a zica está com a cidade e estado.
Se eu deixar como postei acima e preencher algo a busca funciona perfeitamente, o problema está sendo apenas ao clicar em enviar sem preencher nada, ai a exceção é lançada. Sabe o que pode ser Lucas?
Só lembrando que esta validação está funcionando, só dá que dá nullPointerException ao enviar sem preencher nada:

if((imovel.getQuartos() == null && imovel.getEndereco().getBairro().equals("") && imovel.getEndereco().getBairro().equals("") &&
		imovel.getEndereco().getCidade().equals("") && imovel.getEndereco().getEstado().equals("") &&	
		valorMin == null && valorMax == null)) { validator.add(new ValidationMessage(
	            "Informe algum parâmetro para efetuar a busca", "busca.vazia"));				
		}

Valeu!!

Lucas_Cavalcanti

separa esse if gigantesco no método que eu te mandei, daí fica fácil saber qual é o problema

Guevara

Mas como eu uso aquele método boolean com o que eu tenho aqui? Não entendi sua idéia… =/

Lucas_Cavalcanti

ao inves de fazer:

if (quantidade gigantesca de condições) {
    validator.xxx
}

faça

if (checkaParametros(imovel, valorMin, valorMax)) {
    validator.xxx
}

tendeu?

Guevara

Entendi. =)

if(this.checkaParametros(imovel, valorMin, valorMax)) { validator.add(new ValidationMessage(
	            "Informe algum parâmetro para efetuar a busca", "busca.vazia"));				
		}

Fiz isso, cliquei em enviar sem digitar nenhum parâmetro e trouxe td que está no banco e mostrou na jsp. =/

Guevara
// falhou a conexão e repetiu o meu post
Lucas_Cavalcanti

mas agora q o método está extraído, vc consegue debugar e ver o que está acontecendo :wink:

Guevara

Mas o que esse método me mostra é o mesmo que se eu colocar o breakpoint direto no if().
Apertei o enviar sem digitar nada, está td null, mas os dados são carregados na jsp. Isso não deveria acontecer.

Lucas_Cavalcanti

em qual if de dentro daquele metodo ele tá retornando?
é a resposta certa?

Guevara

Pelo print, o bairro e estado estão com a setinha, e cidade não, parece que cidade não está chegando no controlador, seria isso? Cidade está indo null pro controller.
Estou usando este form, igual ao form de cadastro de imóveis:

Estado: <select id="estadoDropdown" name="imovel.endereco.estado">
			<option value="">--Selecione o Estado--</option>
			<option value="AC">Acre</option>
			<option value="AL">Alagoas</option>
			<option value="AM">Amazonas</option>
			<option value="AP">Amap&aacute;</option>			
			<option value="BA">Bahia</option>
			<option value="CE">Cear&aacute;</option>
			<option value="DF">Distrito Federal</option>
			<option value="ES">Espir&iacute;to Santo</option>
			<option value="GO">Goi&aacute;s</option>
			<option value="MA">Maranh&atilde;o</option>
			<option value="MG">Minas Gerais</option>
			<option value="MS">Mato Grosso do Sul</option>			
			<option value="MT">Mato Grosso</option>			
			<option value="PA">Par&aacute;</option>
			<option value="PB">Para&iacute;ba</option>
			<option value="PR">Paran&aacute;</option>
			<option value="PE">Pernambuco</option>
			<option value="PI">Piau&iacute;</option>
			<option value="RJ">Rio de Janeiro</option>
			<option value="RN">Rio Grande do Norte</option>
			<option value="RS">Rio Grande do Sul</option>
			<option value="RO">Rond&ocirc;nia</option>
			<option value="RR">Roraima</option>
			<option value="SC">Santa Catarina</option>
			<option value="SP">S&atilde;o Paulo</option>
			<option value="SE">Sergipe</option>
			<option value="TO">Tocantins</option>
		
			</select><br/><br />	
			
	Cidade: <select id="municipioDropdown" name="imovel.endereco.cidade" disabled="disabled"></select>

Será que precisa fazer algo ai?
Valeu!!!

Lucas_Cavalcanti

vc não respondeu à minha pergunta: em qual if de dentro do checkaParametros ele retorna?

Guevara

Coloquei o breakpoint nesta linha:

return !StringUtils.isBlank(endereco.getBairro())

Ai tirei aquele print…
E coloquei na linha do if():

if(this.checkaParametros(imovel, valorMin, valorMax)) { validator.add(new ValidationMessage(

Ambos retornam o mesmo print que mandei.

Lucas_Cavalcanti

ah tah…

o checkaParametros tá retornando true se algum dos parâmetros foi preenchido, então o certo seria:

if (!this.checkaParametros(imovel, valorMin, valorMax)) { 
     validator.add(new ValidationMessage( ....))
}
Guevara

Agora sim Lucas, com a negação lá o método checkaParametros funciona OK, se eu enviar sem digitar nada a mensagem aparece e se digitar qualquer parâmetro ele busca certo. Mas o meu if ficaria como ? Com negação antes de todos os parâmetros?

Lucas_Cavalcanti

fica exatamente como eu mandei, só negar o retorno do método

Guevara

Tá brabo, não deu boa:

if(!(imovel.getQuartos() != null &&
			imovel.getEndereco() == null &&	
			imovel.getEndereco().getBairro().equals("") &&
		    imovel.getEndereco().getCidade().equals("") && 
		    imovel.getEndereco().getEstado().equals("") &&	
		    valorMin != null && valorMax != null)) { validator.add(new ValidationMessage(
	            "Informe algum parâmetro para efetuar a busca", "busca.vazia"));				
		}

Tá bloqueando tudo.

Lucas_Cavalcanti

pq vc tirou o método?
não faça if’s gigantescos, fica horrivel de saber o que está acontecendo…

Guevara

Pensei que aquele método era só pra testar onde estava o problema. Ainda não descobri ao certo o que está causando o nullPointerException, desconfio que seja o atributo cidade. Pior que tenho essa mesma busca em outro Controller, acho que vou criar um Component e passar a busca pra lá, assim não fica código repetido…
Valeu Lucas!

Guevara

Lucas, qual a função daqueles “return” em cada parâmetro? Aquele método isBlank da classe StringUtils é mais eficaz do que usar .isEmpty ou .equals("") para testar um parâmetro?

Lucas_Cavalcanti

é pra separar aquele if gigante em ifs menores…

se o valorMin ou o valorMax foi preenchido, eu sei que posso fazer a busca, por isso já retorno true
senão tenho que ver as outras condições…

o isBlank significa string == null || string.isEmpty()

Guevara

Saquei, value pela ajuda Lucas!
Abraço!

Criado 21 de outubro de 2010
Ultima resposta 22 de out. de 2010
Respostas 30
Participantes 2