I cannot ignore fields when trying to return them as Json causing "Infinite recursion"

Asked

Viewed 893 times

4

I’m working with Hibernate, Spring and Jackson (to ignore fields) and when trying to return the class User in a json request java returns error due to mapping @Onetomany and @Manytoone with class Profile. Does anyone know why ?

Ah, important to inform you that I am working with several modules managed by Maven, being them:

|--marcenaria-dao

|--marcenaria-service

|--marcenaria-ws

|--marcenaria-web

With this, joinery-dao contains the Beans (User and Profile) and is dependent on the joinery-service project which in turn is dependent on the joinery-Ws webservice.

Below the Exception and the classes.

Java user (carpentry-dao)

package br.com.marcenaria.bean;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import com.fasterxml.jackson.annotation.JsonManagedReference;

@Entity
public class Usuario extends BaseBean{

    private static final long serialVersionUID = 9146984943787732965L;

    private String nome;
    private String email;
    private String senha;
    private Perfil perfil;
    private Marcenaria marcenaria;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Column(nullable=false,unique=true)
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    @Column(nullable=false,unique=true)
    public String getSenha() {
        return senha;
    }
    public void setSenha(String senha) {
        this.senha = senha;
    }
    @JsonManagedReference(value="perfil")
    @ManyToOne
    @JoinColumn(name = "perfil_id")
    public Perfil getPerfil() {
        return perfil;
    }
    public void setPerfil(Perfil perfil) {
        this.perfil = perfil;
    }
    @Column
    public Date getCriado() {
        return criado;
    }
    public void setCriado(Date criado) {
        this.criado = criado;
    }
    @Column
    public Date getInativo() {
        return inativo;
    }
    public void setInativo(Date inativo) {
        this.inativo = inativo;
    }
    @ManyToOne
    @JoinColumn(name="marcenaria_id")
    public Marcenaria getMarcenaria() {
        return marcenaria;
    }
    public void setMarcenaria(Marcenaria marcenaria) {
        this.marcenaria = marcenaria;
    }
    public String getNome() {
        return nome;
    }
    public void setNome(String nome) {
        this.nome = nome;
    }
}

Java profile (carpentry-dao)

package br.com.marcenaria.bean;

import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;

@Entity
public class Perfil extends BaseBean{

    private static final long serialVersionUID = -6933398409318466304L;

    private String descricao;
    private List<Usuario> listaUsuario;

    public Perfil() {}

    public Perfil(String descricao) {
        this.descricao = descricao;
    }

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Column(nullable=false)
    public String getDescricao() {
        return descricao;
    }
    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
    @JsonIgnore
    @JsonBackReference(value="lista-usuario")
    @OneToMany(mappedBy="perfil")
    public List<Usuario> getListaUsuario() {
        return listaUsuario;
    }
    public void setListaUsuario(List<Usuario> listaUsuario) {
        this.listaUsuario = listaUsuario;
    }
    @Column
    public Date getCriado() {
        return criado;
    }
    public void setCriado(Date criado) {
        this.criado = criado;
    }
    @Column
    public Date getInativo() {
        return inativo;
    }
    public void setInativo(Date inativo) {
        this.inativo = inativo;
    }
}

pom.xml (joinery-dao)

<?xml version="1.0"?>
<project
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
    xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>marcenaria</groupId>
        <artifactId>marcenaria</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>marcenaria-dao</groupId>
    <artifactId>marcenaria-dao</artifactId>
    <name>marcenaria-dao</name>
    <url>http://maven.apache.org</url>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.10.Final</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
    </dependencies>
</project>

Usuariocontroller.java (woodworking-Ws)

package br.com.marcenaria.controller;

import java.util.Arrays;
import java.util.Date;

import javax.servlet.ServletException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import br.com.marcenaria.bean.Usuario;
import br.com.marcenaria.service.UsuarioService;
import br.com.marcenaria.view.Retorno;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@RestController
@RequestMapping("/usuario")
public class UsuarioController {

    @Autowired
    private UsuarioService usuarioService;

    @RequestMapping(value = "login", method = RequestMethod.POST)
    public Retorno<Usuario> login(@RequestBody final Usuario pUsuario)
        throws ServletException {
        Usuario usuario = usuarioService.acessar(pUsuario);

        String token = Jwts.builder().setSubject(usuario.getEmail())
                .claim("roles",Arrays.asList(usuario.getPerfil().getDescricao())).setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, "secretkey").compact();

        Retorno<Usuario> retorno = new Retorno<Usuario>();
        retorno.setObjeto(usuario);
        retorno.setToken(token);

        return retorno;
    }
}

Exception

mar 11, 2016 2:30:15 AM org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver handleHttpMessageNotWritable
ADVERTÊNCIA: Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) (through reference chain: br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]->br.com.marcenaria.bean.Usuario["perfil"]->br.com.marcenaria.bean.Perfil["listaUsuario"]->org.hibernate.collection.internal.PersistentBag[0]-

1 answer

4


You have here an infinite recursion case due to bi-directional relationship.

Let’s say John is a Admin:

  • The object of type Usuário John, therefore had a reference to the Perfil Admin.
  • The object Perfil in question, in turn, has a list of users, which includes John.

On the Java side this is no problem, the references are just notes for pieces of memory. It’s time to write the Usuário John in JSON this will result in an infinite tree.

I noticed you’re trying to use the note @JsonIgnore to try to solve the problem. See if you are using the right package. Other options are "disassemble" (in the absence of a good technical translation for the term detach) the object of the type Perfiland set the value of listaUsuariofor null, or create a new class for the view (E.g., Um UserDto where profile is a String)

  • Thanks for the reply Anthony. I am using the correct packages yes. I don’t want to use Dtos but ignore the fields using the Annotations. Changing the null attribute listUsuario worked, but I’ll still leave the question open to see if someone points to the Annotations error. Thanks.

  • Oops, just out of curiosity, try to include a package dependency Jackson-databind, also worth checking if other notes on Jackson are working properly (officially Spring 4.2.5 only was tested with Jackson 2.4, 2.5 and 2.6). Finally, choose between @JsonManagedReference / @JsonBackReference or @JsonIgnore (not both).

  • I added the dependency but no result. About using @JsonIgnore along with the @JsonBackReference and the @JsonManagedReference was one of 7235 attempts to solve the problem, rsrs. I believe the problem is in my poms, I believe that WS is not using the updated jar of joinery-dao. I will investigate in this sense.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.