Solucionado (ver solução)
Solucionado
(ver solução)
12
respostas

[Dúvida] java.lang.ClassCastException em API

Estou fazendo um endpoint para "/{ano}/{mes}" na minha API com um resumo de dados e valores etc contendo:

Valor total das receitas no mês Valor total das despesas no mês Saldo final no mês Valor total gasto no mês em cada uma das categorias

Criei esse controller chamado ResumoMensalController para organizar melhor e criei os metodos auxiliares fazendo cada uma dessas partes do resumo ultilizando os services/repositories das minhas entidades e depois por ultimo um metodo resumo() que chame todos eles, tudo certo.

Meu atributo de valor nessas entidades estava como String, então mudei todos para int tanto código como no banco de dados pra poder usar a função SUM na minha query e obter os valores, tudo certo.

Porém na hora de chamar o método estou recebendo essa exception: java.lang.ClassCastException: class java.lang.Long cannot be cast to class

Já tentei fazer um cast na query passando de INT para VARCHAR e não funcionou, não sei se fiz 100% do jeito certo.

Tentei reescrever os métodos como "public String" , também com List e a exception sumiu porém o body não retornava na requisição, então desfiz.

Imagino que o problema seja de CAST como diz o próprio erro ou a forma de escrever os métodos, mas já rodei mto e não chego em uma solução.

O erro ocorre ao chamar todos os métodos, mas no momento no método resumo estou usando apenas um e comentei os outros pra focar em resolver ele.

segue o repositório pra quem quiser baixar e dar uma olhada: https://github.com/matthewmatheus/renda-familiar-api

![Insira aqui a descrição dessa imagem para ajudar na acessibilidade](https://cdn1.gnarususercontent.com.br/1/1188180/18b2cd64-a78d-4101-bc3b-43e4794f0153.png)  

![Insira aqui a descrição dessa imagem para ajudar na acessibilidade](https://cdn1.gnarususercontent.com.br/1/1188180/20551b31-bf3c-4af4-b5b7-b1a6f3ce28f6.png) 

![Insira aqui a descrição dessa imagem para ajudar na acessibilidade](https://cdn1.gnarususercontent.com.br/1/1188180/7831425c-1bc1-4fa4-8924-5f359187f2ab.png) 

![Insira aqui a descrição dessa imagem para ajudar na acessibilidade](https://cdn1.gnarususercontent.com.br/1/1188180/19d3f4b3-ed5f-4ea5-975a-9135bb875976.png) 

![Insira aqui a descrição dessa imagem para ajudar na acessibilidade](https://cdn1.gnarususercontent.com.br/1/1188180/9d58c919-f43d-4151-a0de-98f8a45fdcc9.png) 

![Insira aqui a descrição dessa imagem para ajudar na acessibilidade](https://cdn1.gnarususercontent.com.br/1/1188180/8ed8f4de-287d-42a7-9da7-5dbcf38645b3.png) 

![Insira aqui a descrição dessa imagem para ajudar na acessibilidade](https://cdn1.gnarususercontent.com.br/1/1188180/73088f55-7b76-47dc-a271-ae4a2a19a121.png)  
12 respostas

Por algum motivo não carregou no post as imagens, mas o link com os prints está entre os ( ).

Exception completa:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Oii Matheus, tudo certo?

Fui mudando aqui tudo de Receita para Long, porque acho que a query no Repository retorna um Long. Por isso, ele está lançando a exceção do ClassCast. Ficou mais ou menos assim:

//Classe ReceitaRepository
@Query(value = "SELECT SUM(R.valor) AS total_receitas FROM Receita R WHERE R.ano = :ano and R.mes = :mes")
    Long somarValorReceitas(int ano, int mes);

//Classe ReceitaServiceImpl
@Override
    public Long somarValorReceitas(int ano, int mes) {
        Long valor = repo.somarValorReceitas(ano,mes);
        return valor;
    }
//ReceitaService
    Long somarValorReceitas(int ano, int mes);
    //ResumoMensalController
    public Long valorTotalReceitas(int ano, int mes) {
        Long valor =  receitasService.somarValorReceitas(ano, mes);
        return valor;
    }

Não cheguei a testar, porque meu MySQL não está devidamente configurado. Tenta fazer assim e conta aqui por favor, qualquer coisa eu configuro aqui para vermos o que está acontecendo.

Abraços!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!

Oi Iasmin! Então, acabo de dar um tapa no código e aproveitei pra mudar os atributos 'ano' e 'mes' nas entidades e no resto do código que estavam ainda como String para int, no caso de isso tb ser uma causa de problema.

Também atualizei com os Long's do mesmo jeito que você fez e a exception sumiu, porém o body retorna vazio na requisição..

retorno-requisicao

Estou tentando ver aqui o que pode ser também, mas muito estranho.

Foi o mesmo que ocorreu quando mudei pra String o retorno antes dessas alterações de String pra int, nesse caso também tentei fazer um List< String > e alterei a query pra "SELECT * FROM receitas.." e etc pra listar tudo e ver o que retornava mas o body também veio vazio.

Estranho pq o CRUD de Receita e Despesa continua funcionando perfeitamente.

Matheus, reparei que no seu controller de resumo mensal você não injetou nenhuma dependência. Tenta colocar o @Autowired em cima do construtor pra gente ver, às vezes é isso...

Também não é isso :(

Até deixei de usar a anotação propositalmente pq vi que os services não precisam do autowired pra injetar, só o repository mesmo.

Estava fazendo o teste com o método valorTotalGastoPorCategoria() também mas é a mesma coisa.. body vazio.

Tentei alterar a query e adicionei "native query = true" mas ela retorna Column 'id' not found., por esse mesmo motivo se não me engano foi que deixei false nas outras querys porém funcionou normalmente..

Fiz o mesmo teste com o public List< Despesa > valorTotalGastoPorCategoria e ele retorna um erro diferente, mas que parece relacionado a cast e converter o tipo de data também:

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Long] to type [@org.springframework.data.jpa.repository.Query br.com.rfapi.rendafamiliarapi.model.Despesa]

E quando mudo pra Long é o mesmo resultado do outro método, body vazio.

Consegui finalmente obter o retorno do método valorTotalReceitas()!

Alterei para um < Object > mas funcionou com Long também.

public List <Object> valorTotalReceitas(int ano, int mes) { List<Object> valor = receitasService.somarValorReceitas(ano, mes); return valor; }

Ao menos a query está certa e está somando todos os valores daquele mês conforme o esperado.

Porém o problema é que no método resumo() como está só consigo retornar 1 método.. tentei criar uma lista dentro do método e adicionar os métodos pra retornar ela mas não funcionou, não sei se foi por fazer errado.

O que me incomodou também é que esperava receber um json como nas outras requisições com o total_receitas que coloquei na query.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

solução!

Oii Matheus, que bom que conseguiu retornar os valores certos!

Pra retornar o json, você pode criar uma classe auxiliar (ela não precisa ser uma entidade, pode ser uma classe normal). Daí, essa classe terá os atributos valorTotalreceitas, valorTotalDespesas, saldoFinalDoMes e valorTotalPorCategoria. No método resumo do Controller, você chama o construtor dessa classe, passando os valores obtidos em cada consulta, e retorna um ResponseEntity de ResumoMensal.

Essa é uma estratégia pra lidar com o método do resumo, não sei se, caso você quisesse retornar os valores separados, isso daria certo.

Valeuu Iasmin! Ajudou demais, fiz o que você disse e criei a classe DTO com os atributos e agora consegui retornar o resultado de todos os métodos.

{
    "valorTotalReceitas": [
        [
            131313
        ]
    ],
    "valorTotalDespesas": 14446,
    "saldoFinalDoMes": 248180,
    "valorTotalGastoPorCategoria": [
        [
            [
                1313,
                13133
            ]
        ]
    ]
}

Só não tá retornando qual valor pertence a cada categoria, seria possível eu fazer isso? ex

                                        LAZER: 1113,
                                          SAUDE: 770

Ou essa parte quem cuidaria seria o front?

Já estou tentando caçar uma maneira por aqui, mas ao menos o problemão principal tá resolvido, obrigado!

Aaaaa, que ótimo! Feliz que deu certo!

Estranhei aquela primeira linha do json com colchetes, provavelmente é porque está com retorno de lista, aí aconselho deixar como Long/Object que nem o valorTotalDespesas. Inclusive, pela questão de deixar como um objeto o mais específico possível, aconselho trocar pra Long, uma vez que a classe Object é bastante genérica, e Long define mais o resultado que você espera.

Sobre separar por categorias, dá pra tentar mapear com um DTO de Categoria também, no caso, como já tem o Enum Categoria no seu projeto, acredito que não dê problemas. Fica mais ou menos assim no método principal:

public List<Categoria> valorTotalGastoPorCategoria(int ano, int mes) {

        List<Categoria> totalGasto = despesaService.somarDespesasPorCategoria(ano, mes);
        return totalGasto;
    }

Só tem que lembrar de trocar todas as referências de Object pra Categoria pra funcionar, incluve na classe DTO de ResumoMensal.

Caso o Java reclame porque se trata de um enum, você tem duas opções: trocar o seu enum por uma classe normal, ou criar outra classe de CategoriaDTO, vai depender bastante da sua modelagem.

Espero que dê certinho! Abraços,

Oi Iasmin, decidi há alguns dias seguir em frente com o projeto e depois resolver essa questão de retornar as categorias específicas kkkkk

Já que o problema principal foi resolvido vou encerrar o tópico, valeu demais pela ajuda!!