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

Erro ao retornar JSON do RESTContoller: Aula 4: Curso Spring MVC: Autenticação com Spring Security, API Rest e AJAX

2020-10-12 19:36:27.912 ERROR 64461 --- [nio-8080-exec-3] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/api/pedidos/aguardando] and exception [Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.model.User$HibernateProxy$r6kmFZ1Y["pedidos"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.alura.mvc.mudi.model.Pedido["user"]->br.com.alura.mvc.mudi.mo `

3 respostas
solução!
Could not write JSON: Infinite recursion

Você criou um mapeamento que auto-referencia, criando uma recurção infinita. Provavelmente terá que mapear uma das pontas do relacionamento com @JsonIgnore. Como ficou sua classe Pedido?

Anotei o mapeamento em user do Pedido, mas não mudou nada. Quando anotei em pedido do User deu erro 500.

A classe do Pedido ficou assim:

package br.com.alura.mvc.mudi.model;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

@Entity
public class Pedido {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;    
    private String nomeProduto;
    private BigDecimal valorNegociado;
    private LocalDate dataEntrega;
    private String urlProduto;
    private String urlImagem;
    private String descricao;

    @ManyToOne(fetch = FetchType.LAZY)
    private User user;
    /*
     * Relacionamento com a entidade Oferta
     * do tipo um pedido possui muitas ofertas.
     * Cascatear as inclusões e remoções. Definir o atributo forte como pedido.
     * Definir o carregamento como posterior.
     */
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "pedido", fetch = FetchType.LAZY)
    private List<Oferta> oferta;

    @Enumerated(EnumType.STRING)


    private StatusPedido status;
        public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public StatusPedido getStatus() {
        return status;
    }
    public void setStatus(StatusPedido status) {
        this.status = status;
    }
    public String getNomeProduto() {
        return nomeProduto;
    }
    public void setNomeProduto(String nomeProduto) {
        this.nomeProduto = nomeProduto;
    }
    public BigDecimal getValorNegociado() {
        return valorNegociado;
    }
    public void setValorNegociado(BigDecimal valorNegociado) {
        this.valorNegociado = valorNegociado;
    }
    public LocalDate getDataEntrega() {
        return dataEntrega;
    }
    public void setDataEntrega(LocalDate dataEntrega) {
        this.dataEntrega = dataEntrega;
    }
    public String getUrlProduto() {
        return urlProduto;
    }
    public void setUrlProduto(String urlProduto) {
        this.urlProduto = urlProduto;
    }
    public String getUrlImagem() {
        return urlImagem;
    }
    public void setUrlImagem(String urlImagem) {
        this.urlImagem = urlImagem;
    }
    public String getDescricao() {
        return descricao;
    }
    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
    public List<Oferta> getOferta() {
        return oferta;
    }
    public void setOferta(List<Oferta> oferta) {
        this.oferta = oferta;
    }
}

Desde já agradeço a ajuda!

Nas aulas seguintes o professor mostrou porque isso poderia ocorrer e foi o que você mencionou mesmo, anotando com @JsonIgnore.

Porém quando recupero o Json correto e formatado, o atributo id da classe Pedido não é retornada e não consigo enviar oferta via Json, pois dá erro 500. Minha classe PedidosRest está assim:

package br.com.alura.mvc.mudi.api;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import br.com.alura.mvc.mudi.model.Pedido;
import br.com.alura.mvc.mudi.model.StatusPedido;
import br.com.alura.mvc.mudi.repository.PedidoRepository;

@RestController
@RequestMapping("/api/pedidos")
public class PedidosRest {

    /*
     * Injeção de dependência para o repositório de pedidos.
     */
    @Autowired
    private PedidoRepository pedRepo;

    @GetMapping("aguardando")
    public List <Pedido> getPedidoAguardandoOferta(){

        Sort sort = Sort.by("dataEntrega").descending();
        PageRequest paginacao = PageRequest.of(0, 5, sort);

        return pedRepo.findByStatus(StatusPedido.AGUARDANDO, paginacao);
    }

}

E o JSON retornado está assim:

// 20201015235616
// http://localhost:8080/api/pedidos/aguardando

[
  {
    "nomeProduto": "Maleta de ferramentas kit com 129 peças",
    "valorNegociado": 120.00,
    "dataEntrega": "2020-11-30",
    "urlProduto": "https://www.amazon.com.br/Maleta-Ferramentas-Sparta-Kit-13564/dp/B076N2S8FV?ref_=Oct_s9_apbd_otopr_hd_bw_bIgAhLn&pf_rd_r=JVW4F93C372PRMB0PZRV&pf_rd_p=ff35255a-20a1-5903-9eee-f663411f87b8&pf_rd_s=merchandised-search-11&pf_rd_t=BROWSE&pf_rd_i=17113547011",
    "urlImagem": "https://images-na.ssl-images-amazon.com/images/I/61sxBRVVpAL._AC_SL1000_.jpg",
    "descricao": "São projetados especialmente para automobilistas e centros de manutenção.",
    "status": "AGUARDANDO"
  },

Logo não consigo criar uma oferta porque recebo o erro abaixo no navegador:

{timestamp: "2020-10-16T03:00:24.465+00:00", status: 500, error: "Internal Server Error",…}
error: "Internal Server Error"
message: "The given id must not be null!; nested exception is java.lang.IllegalArgumentException: The given id must not be null!"
path: "/api/ofertas"
status: 500
timestamp: "2020-10-16T03:00:24.465+00:00"
trace: "org.springframework.dao.InvalidDataAccessApiUsageE"

Mais uma vez, agradecido.