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

Aula 3 - HTTP Status 500, problema com casting para (Predicate[])

No segundo vídeo da aula 3 fiz o código conforme o instrutor:

public List<Produto> getProdutos(String nome, Integer categoriaId, Integer lojaId) {

        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<Produto> query = criteriaBuilder.createQuery(Produto.class);
        Root<Produto> root = query.from(Produto.class);

        Path<String> nomePath = root.<String>get("nome");
        Path<Integer> lojaPath = root.<Loja>get("loja").<Integer>get("id");
        Path<Integer> categoriaPath = root.join("categorias").<Integer>get("id");

        List<Predicate> predicates = new ArrayList<>();

        if(!nome.isEmpty()) {
            Predicate nomeIgual = criteriaBuilder.like(nomePath, nome);
            predicates.add(nomeIgual);
        }
        if(categoriaId != null) {
            Predicate categoriaIgual = criteriaBuilder.equal(categoriaPath, categoriaId);
            predicates.add(categoriaIgual);
        }
        if(lojaId != null) {
            Predicate lojaIgual = criteriaBuilder.equal(lojaPath, lojaId);
            predicates.add(lojaIgual);
        }

        query.where((Predicate[]) predicates.toArray());

        TypedQuery<Produto> typedQuery = em.createQuery(query);
        return typedQuery.getResultList();

}

Coloco o Tomcat para rodar (versão 9.0.34), acesso a página da livraria e quando tento fazer qualquer tipo de pesquisa ocorre o erro 500 abaixo:

HTTP Status 500 – Internal Server Error
Type Exception Report

Message Request processing failed; nested exception is java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljavax.persistence.criteria.Predicate; ([Ljava.lang.Object; is in module java.base of loader 'bootstrap'; [Ljavax.persistence.criteria.Predicate; is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @2352a87d)

Description The server encountered an unexpected condition that prevented it from fulfilling the request.

Exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljavax.persistence.criteria.Predicate; ([Ljava.lang.Object; is in module java.base of loader 'bootstrap'; [Ljavax.persistence.criteria.Predicate; is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @2352a87d)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Root Cause

java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljavax.persistence.criteria.Predicate; ([Ljava.lang.Object; is in module java.base of loader 'bootstrap'; [Ljavax.persistence.criteria.Predicate; is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @2352a87d)
    br.com.caelum.dao.ProdutoDao.getProdutos(ProdutoDao.java:62)
    br.com.caelum.dao.ProdutoDao$$FastClassBySpringCGLIB$$86b6783b.invoke(<generated>)

...

Note A pilha de erros completa da causa principal está disponível nos logs do servidor.

Apache Tomcat/9.0.34

Por favor, solicito ajuda para ver o que pode estar ocorrendo e como corrigir o problema?

2 respostas
solução!

Olá Rafael, tudo bem com você?

Antes de mais nada peço perdão pelo inconveniente, pois houve um pequeno corte no vídeo (observe o minuto 11:42 e 11:43) e com isso faltou você copiar uma parte do código, no caso aqui:

        query.where((Predicate[]) predicates.toArray());

Quando utilizamos o método toArray por padrão o que ele devolve é um vetor de Object ( e não há como ter a conversão para Predicate[] ), quando sabemos o tipo desses elementos, como é o nosso caso que teremos um vetor de Predicates, precisamos indicar para o método passando uma instância de um vetor vazio do mesmo tipo, ou seja:

        query.where((Predicate[]) predicates.toArray( new Predicate[0]));

Dessa forma o toArray consegue devolver um vetor de Predicate

Poderiamos até reduzir o código, pois não há mais necessidade do casting, e deixar, já que o casting não funciona neste caso:

query.where(predicates.toArray(new Predicate[0]));

Mas recomendo deixar da primeira maneira correta para manter igualdade com os códigos do professor :)

Abraços e Bons Estudos!

Geovani,

Boa tarde. Conforme você explicou foi isso mesmo que estava faltando na linha de cógido do Predicate[]. Agora está funcionando normalmente.

Muito obrigado pela ajuda.