[RESOLVIDO] Erro ao consumir API usando o Resttemplate

14 respostas Resolvido
restjavaspring
Silas_Fernandes

Boa tarde pessoal, sou iniciante na programação java e estou tentando consumir uma api simples que eu mesmo criei utilizando o resttemplate do spring, a api em questão seria só um serviço para buscar no banco de dados um campo de ano_nascimento, caso a busca retorne algum ano de nascimento igual ao que for passado eu quero que seja retornado apenas a idade calculada com base no ano encontrado, caso não ache nada retornar apenas um 0.

Esse é o código do controller

@GetMapping("/ano/{anoNascimento}")
    	public String buscaAno(@PathVariable String anoNascimento) {
    		
    		clienteRepository.findByAnoNascimento(anoNascimento);
    		
    		if(clienteRepository.findByAnoNascimento(anoNascimento).isEmpty()==true) {
    			return "0";
    		} else {
    			return anoNascimento ;
    		}		
    	}

Esse é o código do serviço:

public static void buscaPeloAno() {
    		Map<String, String> param = new HashMap<>();
    		param.put("anoNascimento", "2005");
    		System.out.println(param.put("anoNascimento", "1995"));

    		Cliente cliente = restTemplate.getForObject(BUSCA_PELO_ANO, Cliente.class, param);
    		System.out.println(cliente);
    		
    		if(cliente.getAnoNascimento()=="0") {
    			System.out.println("Ano não encontrado no banco de dados");
    		} else {
    			Integer ano = Integer.parseInt(cliente.getAnoNascimento());
    			Integer anoAtual = LocalDate.now().getYear();
    			Integer resultado = anoAtual - ano;
    			String resultadoString = resultado.toString();
    			System.out.println("A idade é: "+resultadoString);
    			
    		}
    	}

E esse é o erro que me retorna

Error while extracting response for type [class br.com.santarosa.clinica.model.Cliente] and content type [application/json]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `br.com.santarosa.clinica.model.Cliente` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1995); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `br.com.santarosa.clinica.model.Cliente` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1995)

14 Respostas

Lucas_Camara

Como é o json que o serviço retorna? E posta tb a classe Cliente.

Silas_Fernandes

Essa é a classe Cliente

package br.com.santarosa.clinica.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "cliente_silas")
public class Cliente {
	@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	
	@Column(name = "nome")
	private String nome;
	
	@Column(name = "cpf")
	private String cpf;
	
	@Column(name = "cnpj")
	private String cnpj;
	
	@Column(name = "ano_nascimento")
	private String anoNascimento;
	
	@Column(name = "telefone")
	private String telefone;

	public Cliente() {

	}
	
	public Cliente(String nome, String cpf, String cnpj, String anoNascimento, String telefone) {
		this.nome = nome;
		this.cpf = cpf;
		this.cnpj = cnpj;
		this.anoNascimento = anoNascimento;
		this.telefone = telefone;
	}

	

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getCpf() {
		return cpf;
	}

	public void setCpf(String cpf) {
		this.cpf = cpf;
	}

	public String getCnpj() {
		return cnpj;
	}

	public void setCnpj(String cnpj) {
		this.cnpj = cnpj;
	}

	public String getAnoNascimento() {
		return anoNascimento;
	}

	public void setAnoNascimento(String anoNascimento) {
		this.anoNascimento = anoNascimento;
	}

	public String getTelefone() {
		return telefone;
	}

	public void setTelefone(String telefone) {
		this.telefone = telefone;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((anoNascimento == null) ? 0 : anoNascimento.hashCode());
		result = prime * result + ((cnpj == null) ? 0 : cnpj.hashCode());
		result = prime * result + ((cpf == null) ? 0 : cpf.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((nome == null) ? 0 : nome.hashCode());
		result = prime * result + ((telefone == null) ? 0 : telefone.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Cliente other = (Cliente) obj;
		if (anoNascimento == null) {
			if (other.anoNascimento != null)
				return false;
		} else if (!anoNascimento.equals(other.anoNascimento))
			return false;
		if (cnpj == null) {
			if (other.cnpj != null)
				return false;
		} else if (!cnpj.equals(other.cnpj))
			return false;
		if (cpf == null) {
			if (other.cpf != null)
				return false;
		} else if (!cpf.equals(other.cpf))
			return false;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (nome == null) {
			if (other.nome != null)
				return false;
		} else if (!nome.equals(other.nome))
			return false;
		if (telefone == null) {
			if (other.telefone != null)
				return false;
		} else if (!telefone.equals(other.telefone))
			return false;
		return true;
	}
}

Sobre o retorno é que eu tenho duvida, se daria pra retornar só um json com esse valor calculado da idade, se tiver como eu faço isso?

Lucas_Camara

Soh para entender melhor. Essa linha:

Cliente cliente = restTemplate.getForObject(BUSCA_PELO_ANO, Cliente.class, param);

Está chamando esse endpoint:

@GetMapping("/ano/{anoNascimento}")
	public String buscaAno(@PathVariable String anoNascimento) {

É isso?

Silas_Fernandes

Isso mesmo, defini o end point assim

private static final String BUSCA_PELO_ANO = "http://localhost:8080/clientes/ano/{anoNascimento}";

Silas_Fernandes

E esse é o ClienteRepository que eu esqueci de mandar também

package br.com.santarosa.clinica.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import br.com.santarosa.clinica.model.Cliente;

@Repository
public interface ClienteRepository extends JpaRepository<Cliente, Integer>{

	List<Cliente> findByAnoNascimento(String anoNascimento);
	
}
Lucas_Camara
Solucao aceita

Entendi. Então o erro é pq o endpoint retorna o “anoNascimento” e vc está tentando recuperar como se fosse um “Cliente”.

Silas_Fernandes

Então tava querendo pegar o “Cliente” para poder pegar o anoNascimento dele. Como eu deveria fazer para pegar so o anoNascimento que trouxer do banco?

Lucas_Camara

Mas o endpoint “/clientes/ano/{anoNascimento}” está retornando somente uma string com a data de nascimento, e não cliente completo:

@GetMapping("/ano/{anoNascimento}")
	public String buscaAno(@PathVariable String anoNascimento) {
		
		clienteRepository.findByAnoNascimento(anoNascimento);
		
		if(clienteRepository.findByAnoNascimento(anoNascimento).isEmpty()==true) {
			return "0";
		} else {
			return anoNascimento ;
		}		
	}
Silas_Fernandes

Entendi, tenho que mudar o retorno do meu endpoint para um Cliente completo então certo.

Lucas_Camara

Isso mesmo!

No erro, a parte:

Cannot construct instance of `br.com.santarosa.clinica.model.Cliente` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1995);

Diz que não foi possível encontrar uma forma de construir a classe Cliente para o número de valor 1995.

Silas_Fernandes

Entendi mano, inclusive fiz aqui e deu certo quando ele encontra o ano no banco de dados ele me retorna o calculo da idade certo, mas quando eu passo um ano que não existe no banco de dados ele me da um erro, como eu faço esse tratamento pra ele me retornar 0 ao inves de erro?

alterei o método de busca, o 2005 ali é um ano inexistente no banco de dados

public static void buscaPeloAno() {
		Map<String, String> param = new HashMap<>();
		param.put("anoNascimento", "2005");
		Cliente cliente = restTemplate.getForObject(BUSCA_PELO_ANO, Cliente.class, param);
		
		if(cliente.getAnoNascimento().isEmpty()==true) {
			System.out.println("Ano não encontrado no banco de dados");
		} else {
			Integer ano = Integer.parseInt(cliente.getAnoNascimento());
			Integer anoAtual = LocalDate.now().getYear();
			Integer resultado = anoAtual - ano;
			String resultadoString = resultado.toString();
			System.out.println("A idade é: "+resultadoString);
			
		}
	}
Silas_Fernandes

Esse é o erro que me retorna com um ano inexistente no banco de dados.

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.NullPointerException
	at br.com.santarosa.clinica.service.ClienteService.buscaPeloAno(ClienteService.java:85)
	at br.com.santarosa.clinica.ClinicaApplication.main(ClinicaApplication.java:19)
	... 5 more
Lucas_Camara

Talvez o endpoint esteja retornando vazio qdo vc passa um ano inexistente. Com isso, o cliente deve ficar NULL e talvez esteja estourando null pointer nessa linha:

if(cliente.getAnoNascimento().isEmpty()==true) {
      ^
      +-> Se o cliente for NULL, vai  nullpointer aqui

Vc deve verificar se o cliente é NULL ou não, e fazer algum tratamento.

Silas_Fernandes

Entendi Lucas, muuuuito obrigado pela ajuda mesmo, vou tentar fazer esse tratamento aqui, obrigado.

Criado 21 de abril de 2021
Ultima resposta 21 de abr. de 2021
Respostas 14
Participantes 2