Lorsque Spring MVC essaie de convertir un objet JPA associé à une association bidirectionnelle en JSON par jackson 2.6.1, je continue à obtenir
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError)
et la première entité est:
import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.Entity;
import javax.persistence.Table;
...
@Entity
@Table(name = "user")
public class User implements Java.io.Serializable {
private Integer userId;
@JsonManagedReference
private UserClass userClass;
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "userId", unique = true, nullable = false)
public Integer getUserId() {
return this.userId;
}
@ManyToOne()
@JoinColumn(name = "userClassId")
public UserClass getUserClass() {
return this.userClass;
}
.......
}
la seconde est:
import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.Entity;
import javax.persistence.Table;
...
@Entity
@Table(name = "user_class")
public class UserClass implements Java.io.Serializable {
private Integer userClassId;
@JsonBackReference
private List<User> users = new ArrayList<User>(0);
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "userClassId", unique = true, nullable = false)
public Integer getUserClassId() {
return this.userClassId;
}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "userClass")
public List<User> getUsers() {
return this.users;
}
et voici les dépendances:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.8.2.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate4</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-Java</artifactId>
<version>5.1.34</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.3.Final</version>
</dependency>
<dependency>
<groupId>org.Apache.tiles</groupId>
<artifactId>tiles-core</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.Apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.Apache.tiles</groupId>
<artifactId>tiles-api</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.Apache.tiles</groupId>
<artifactId>tiles-template</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
</dependencies>
J'ai utilisé "@JsonIgnore", "@JsonIdentityInfo" et "XmlTransient" pour empêcher la récursivité, mais ils ne fonctionnent pas tous les deux et le serveur a signalé cette erreur. Est-ce que quelqu'un peut m'aider?
Merci.
Edit: Et trace de pile:
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) (through reference chain:
sss.com.model.UserClass["users"]->org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]->
org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]->org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]... .
nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain:
sss.com.model.UserClass["users"]->org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]->
org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]->org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]... . with root cause
Java.lang.StackOverflowError
at Java.io.IOException.<init>(IOException.Java:58)
at com.fasterxml.jackson.core.JsonProcessingException.<init>(JsonProcessingException.Java:25)
at com.fasterxml.jackson.core.JsonProcessingException.<init>(JsonProcessingException.Java:41)
at com.fasterxml.jackson.databind.JsonMappingException.<init>(JsonMappingException.Java:143)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.Java:689)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.Java:157)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.Java:149)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.Java:111)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.Java:24)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.Java:656)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.Java:675)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.Java:157)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.Java:656)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.Java:675)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.Java:157)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.Java:149)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.Java:111)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.Java:24)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.Java:656)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.Java:675)
...
RESOLU: Dans mon entité d'origine, j'ai 5 relations bidirectionnelles mais, juste, j'ai été annoté d'une relation. La raison en est que Tomcat n'a pas imprimé d'exception dans la page de résultats et que je ne vérifie pas le fichier journal Tomcat.
Il suffit de mettre @JsonIgnore
@JsonIgnore
@OneToMany(fetch = FetchType.LAZY, mappedBy = "userClass")
public List<User> getUsers() {
return this.users;
}
Cela ignorera l'objet de chargement paresseux et corrigera votre problème.
Mise à jour
bi-directional relationship
par @JsonManagedReference, @JsonBackReference
.@JsonIgnore ignore simplement le champ annoté du résultat. Si vous devez également inclure le champ généré par une exception avec le résultat, utilisez @JsonManagedReference, @JsonBackReference conformément au didacticiel suivant. http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion
Si une classe a plus d'une relation bidirectionnelle, mieux d'utiliser @JsonIdentityInfo
Essayez d’ajouter une annotation @XmlTransient au-dessus du côté de la référence manytoone,
import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.Entity;
import javax.persistence.Table;
...
@Entity
@Table(name = "user")
public class User implements Java.io.Serializable {
private Integer userId;
@JsonManagedReference
private UserClass userClass;
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "userId", unique = true, nullable = false)
public Integer getUserId() {
return this.userId;
}
@XmlTransient
@ManyToOne()
@JoinColumn(name = "userClassId")
public UserClass getUserClass() {
return this.userClass;
}
.......
}