I have been asking something similar in this question Link, but the answer did not resolve the problem.
-
I saw a tutorial for handling circular references here the post.
-
I applied those and the other ones, but no ones working and it shows the same error.
-
I’ve already try putting @JsonManagedReference and @JsonBackReference. At the class and at the attribute, but it didn’t work too.
-
I’ve already try putting @JsonIgnore, but it didn’t work too.
-
I’ve already try putting fetch: Lazy and Eager, but it didn’t work too.
-
I don’t want to create DTO or use mapper. Because de solution have to be simple. It’s a tutorial that I have to follow like that.
Following the my code here:
Departamento class:
package br.com.camila.projetoempresa.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
@Entity
@Table(name="departamento")
public class Departamento {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="numero_id")
private Integer numeroId;
@Column(name="nome", nullable = false, length = 100)
private String nome;
@Column(name="andar", nullable = false)
private Integer andar;
@OneToMany(mappedBy = "depto", cascade = CascadeType.ALL)
@JsonIgnoreProperties("depto")
private List<Funcionario> listaFuncionarios;
public Integer getNumeroId() {
return numeroId;
}
public void setNumeroId(Integer numeroId) {
this.numeroId = numeroId;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Integer getAndar() {
return andar;
}
public void setAndar(Integer andar) {
this.andar = andar;
}
public List<Funcionario> getListaFuncionarios() {
return listaFuncionarios;
}
public void setListaFuncionarios(List<Funcionario> listaFuncionarios) {
this.listaFuncionarios = listaFuncionarios;
}
}
Funcionario class:
package br.com.camila.projetoempresa.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
@Entity
@Table(name="funcionario")
public class Funcionario {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "num_funcional", nullable = false)
private Integer numFuncional;
@Column(name="nome", nullable = false, length = 100)
private String nome;
@Column(name="email", nullable = false, length = 100, unique = true)
private String email;
@Column(name="salario")
private Double salario;
@ManyToOne
@JoinColumn(name="numero_id")
@JsonIgnoreProperties("listaFuncionarios")
private Departamento depto;
public Integer getNumFuncional() {
return numFuncional;
}
public void setNumFuncional(Integer numFuncional) {
this.numFuncional = numFuncional;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Double getSalario() {
return salario;
}
public void setSalario(Double salario) {
this.salario = salario;
}
public Departamento getDepartamento() {
return depto;
}
public void setDepartamento(Departamento departamento) {
this.depto = departamento;
}
}
DepartamentoController:
package br.com.camila.projetoempresa.controller;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import br.com.camila.projetoempresa.dao.DepartamentoDAO;
import br.com.camila.projetoempresa.model.Departamento;
@RestController
public class DepartamentoController {
@Autowired
private DepartamentoDAO dao;
@GetMapping("/departamentos")
public ArrayList<Departamento> recuperarTodos(){
ArrayList<Departamento> departamentos;
departamentos = (ArrayList<Departamento>)dao.findAll();
return departamentos;
}
}
FuncionarioController:
package br.com.camila.projetoempresa.controller;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import br.com.camila.projetoempresa.dao.FuncionarioDAO;
import br.com.camila.projetoempresa.model.Funcionario;
@RestController
public class FuncionarioController {
@Autowired
private FuncionarioDAO dao;
@GetMapping("/testefuncionario")
public Funcionario recuperarTeste() {
Funcionario teste = dao.findById(1).get();
return teste;
}
@GetMapping("/todos")
public ArrayList<Funcionario> recuperarTodos(){
return (ArrayList<Funcionario>)dao.findAll();
}
}
Console from STS:
2024-08-04T20:48:20.846-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mb.c.c.p.ProjetoempresaApplication [0;39m [2m:[0;39m Starting ProjetoempresaApplication using Java 17.0.8 with PID 23136 (C:UsersCamilaOneDriveGitHubprojetoempresatargetclasses started by Camila in C:UsersCamilaOneDriveGitHubprojetoempresa)
[2m2024-08-04T20:48:20.849-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mb.c.c.p.ProjetoempresaApplication [0;39m [2m:[0;39m No active profile set, falling back to 1 default profile: "default"
[2m2024-08-04T20:48:20.910-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36m.e.DevToolsPropertyDefaultsPostProcessor[0;39m [2m:[0;39m Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
[2m2024-08-04T20:48:20.910-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36m.e.DevToolsPropertyDefaultsPostProcessor[0;39m [2m:[0;39m For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
[2m2024-08-04T20:48:21.593-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Bootstrapping Spring Data JPA repositories in DEFAULT mode.
[2m2024-08-04T20:48:21.659-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Finished Spring Data repository scanning in 57 ms. Found 2 JPA repository interfaces.
[2m2024-08-04T20:48:22.207-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.w.embedded.tomcat.TomcatWebServer [0;39m [2m:[0;39m Tomcat initialized with port 8080 (http)
[2m2024-08-04T20:48:22.219-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.apache.catalina.core.StandardService [0;39m [2m:[0;39m Starting service [Tomcat]
[2m2024-08-04T20:48:22.220-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.apache.catalina.core.StandardEngine [0;39m [2m:[0;39m Starting Servlet engine: [Apache Tomcat/10.1.26]
[2m2024-08-04T20:48:22.279-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.a.c.c.C.[Tomcat].[localhost].[/] [0;39m [2m:[0;39m Initializing Spring embedded WebApplicationContext
[2m2024-08-04T20:48:22.279-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mw.s.c.ServletWebServerApplicationContext[0;39m [2m:[0;39m Root WebApplicationContext: initialization completed in 1368 ms
[2m2024-08-04T20:48:22.411-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Starting...
[2m2024-08-04T20:48:22.710-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mcom.zaxxer.hikari.pool.HikariPool [0;39m [2m:[0;39m HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@13082f92
[2m2024-08-04T20:48:22.713-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mcom.zaxxer.hikari.HikariDataSource [0;39m [2m:[0;39m HikariPool-1 - Start completed.
[2m2024-08-04T20:48:22.768-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.hibernate.jpa.internal.util.LogHelper [0;39m [2m:[0;39m HHH000204: Processing PersistenceUnitInfo [name: default]
[2m2024-08-04T20:48:22.834-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36morg.hibernate.Version [0;39m [2m:[0;39m HHH000412: Hibernate ORM core version 6.5.2.Final
[2m2024-08-04T20:48:22.877-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.h.c.internal.RegionFactoryInitiator [0;39m [2m:[0;39m HHH000026: Second-level cache disabled
[2m2024-08-04T20:48:23.258-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.s.o.j.p.SpringPersistenceUnitInfo [0;39m [2m:[0;39m No LoadTimeWeaver setup: ignoring JPA class transformer
[2m2024-08-04T20:48:23.340-03:00[0;39m [33m WARN[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36morg.hibernate.orm.deprecation [0;39m [2m:[0;39m HHH90000025: MySQLDialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
[2m2024-08-04T20:48:24.278-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.h.e.t.j.p.i.JtaPlatformInitiator [0;39m [2m:[0;39m HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
[2m2024-08-04T20:48:24.281-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mj.LocalContainerEntityManagerFactoryBean[0;39m [2m:[0;39m Initialized JPA EntityManagerFactory for persistence unit 'default'
[2m2024-08-04T20:48:24.643-03:00[0;39m [33m WARN[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mJpaBaseConfiguration$JpaWebConfiguration[0;39m [2m:[0;39m spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
[2m2024-08-04T20:48:24.986-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.d.a.OptionalLiveReloadServer [0;39m [2m:[0;39m LiveReload server is running on port 35729
[2m2024-08-04T20:48:25.027-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mo.s.b.w.embedded.tomcat.TomcatWebServer [0;39m [2m:[0;39m Tomcat started on port 8080 (http) with context path '/'
[2m2024-08-04T20:48:25.037-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [ restartedMain][0;39m [2m[0;39m[36mb.c.c.p.ProjetoempresaApplication [0;39m [2m:[0;39m Started ProjetoempresaApplication in 4.617 seconds (process running for 5.316)
[2m2024-08-04T20:48:30.052-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [nio-8080-exec-2][0;39m [2m[0;39m[36mo.a.c.c.C.[Tomcat].[localhost].[/] [0;39m [2m:[0;39m Initializing Spring DispatcherServlet 'dispatcherServlet'
[2m2024-08-04T20:48:30.052-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [nio-8080-exec-2][0;39m [2m[0;39m[36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Initializing Servlet 'dispatcherServlet'
[2m2024-08-04T20:48:30.054-03:00[0;39m [32m INFO[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [nio-8080-exec-2][0;39m [2m[0;39m[36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Completed initialization in 2 ms
Hibernate: select f1_0.num_funcional,f1_0.numero_id,f1_0.email,f1_0.nome,f1_0.salario from funcionario f1_0
Hibernate: select d1_0.numero_id,d1_0.andar,d1_0.nome from departamento d1_0 where d1_0.numero_id=?
Hibernate: select d1_0.numero_id,d1_0.andar,d1_0.nome from departamento d1_0 where d1_0.numero_id=?
Hibernate: select d1_0.numero_id,d1_0.andar,d1_0.nome from departamento d1_0 where d1_0.numero_id=?
Hibernate: select d1_0.numero_id,d1_0.andar,d1_0.nome from departamento d1_0 where d1_0.numero_id=?
Hibernate: select d1_0.numero_id,d1_0.andar,d1_0.nome from departamento d1_0 where d1_0.numero_id=?
Hibernate: select lf1_0.numero_id,lf1_0.num_funcional,lf1_0.email,lf1_0.nome,lf1_0.salario from funcionario lf1_0 where lf1_0.numero_id=?
[2m2024-08-04T20:48:30.464-03:00[0;39m [33m WARN[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [nio-8080-exec-2][0;39m [2m[0;39m[36m.w.s.m.s.DefaultHandlerExceptionResolver[0;39m [2m:[0;39m Ignoring exception, response committed already: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Document nesting depth (1001) exceeds the maximum allowed (1000, from `StreamWriteConstraints.getMaxNestingDepth()`)
[2m2024-08-04T20:48:30.465-03:00[0;39m [33m WARN[0;39m [35m23136[0;39m [2m---[0;39m [2m[projetoempresa] [nio-8080-exec-2][0;39m [2m[0;39m[36m.w.s.m.s.DefaultHandlerExceptionResolver[0;39m [2m:[0;39m Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Document nesting depth (1001) exceeds the maximum allowed (1000, from `StreamWriteConstraints.getMaxNestingDepth()`)]
How can I solve this problem without infinite references? I’d like to solve this:
a) when I try finding all Funcionarios should return like this:
NOW:
[
{
"numFuncional": 1,
"nome": "Jose Alberto",
"email": "[email protected]",
"salario": 10000.0,
"departamento": {
"numeroId": 1,
"nome": "Presidência",
"andar": 1,
"listaFuncionarios": [
{
"numFuncional": 1,
"nome": "Jose Alberto",
"email": "[email protected]",
"salario": 10000.0,
"departamento": {
"numeroId": 1,
"nome": "Presidência",
"andar": 1,
"listaFuncionarios": [
{
"numFuncional": 1,
"nome": "Jose Alberto",
"email": "[email protected]",
"salario": 10000.0,
"departamento": {
"numeroId": 1,
"nome": "Presidência",
"andar": 1,
"listaFuncionarios": [
EXPECTATION:
[
{
"numFuncional": 1,
"nome": "Jose Alberto",
"email": "[email protected]",
"salario": 10000.0,
"departamento": {
"numeroId": 1,
"nome": "Presidência",
"andar": 1
},
{
"numFuncional": 3,
"nome": "Pedro Oliveira",
"email": "[email protected]",
"salario": 6000.0,
"departamento": {
"numeroId": 3,
"nome": "Infraestrutura",
"andar": 2
},
]
b) The same case, if I try finding Funcionario by ID
c) The same case, if I try finding all Departamentos or by ID;
I have a simple API Rest that aim my studies in Java.
Thanks guys!
2
Answers
The real problem is that my attribute: "DEPARTAMENTO" has Get and Set like "setDepartamento" and "getDepartamento", but the variable of the attribute is "depto". So I adjusted the get and set to:
BEFORE:
NOW:
So the result of the Postman is OK in all the get Departamento and Funcionario:
}
]
You putting wrong names.
In your
Departamento
you have:It means you want to ignore
depo
property, but you don’t have one. You need to put@JsonIgnoreProperties("listaFuncionarios")
to ignorelistaFuncionarios
property.