Could not write JSON: Infinite recursion

I am getting StackOverflow recursion error when I run query in Postman or Browser .

When i run says:

.w.s.m.s.DefaultHandlerExceptionResolver : Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)

Here is the model classes :

@Entity 
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotNull
    private String title;
    @NotNull
    private String description;
    @NotNull
    private double price;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "category_id", nullable = false)
    private Category category;
    private boolean isSealed;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "currency_id", nullable = false)
    private Currency currency;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;
    @Nullable
    @OneToMany(mappedBy = "product",
            cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Images> images;
    private Date createdDate = new Date();
    @OneToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            mappedBy = "product")
    private View view;
    @OneToOne(fetch = FetchType.LAZY,cascade=CascadeType.ALL)
    @JoinColumn(name="type_id")
    private Type type;
    private Long viewCount; }
@Entity public class Images{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String imagePath;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id")
    private Product product; }
@Entity public class User implements UserDetails, Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotEmpty
    private String fullName;
    @NotEmpty
    @Email
    @Column(unique = true)
    private String email;
    @NotNull
    @Column(unique = true)
    private int phoneNumber;
    @NotEmpty
    @Size(min = 5)
    private String password;
    private Date createAt = new Date();
    @Nullable
    private String picPath;
    @Nullable
    private String token;
    @ManyToMany
    @JoinTable(name = "user_roles", joinColumns = {@JoinColumn(
            name = "user_id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id")})
    private List<Role> roles;
    @OneToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            mappedBy = "user")
    private Product product;
    @OneToOne(fetch = FetchType.LAZY,
    cascade = CascadeType.ALL,
    mappedBy = "user")
    private View view; }
@Entity 
public class Currency{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String code;
    private String currency;
    private String region_country;
    @OneToOne(mappedBy = "currency", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Product product; }
@Entity 
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String imagePath;
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY,
    mappedBy = "category")
    private Product product;
    @OneToMany(mappedBy = "category", fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    private Set<Brand> brands; }
@Entity public class Brand {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "category_id", nullable = false)
    private Category category; }
@Entity public class View {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "product_id", nullable = false)
    private Product product; }
@Entity public class Type {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotNull
    private String name;
    @OneToOne(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            mappedBy = "type")
    private Product product; }
    @Id
    private String role;
    @ManyToMany(mappedBy = "roles")
    private List<User> users; 
}

Upvotes: 0

Views: 5716

Answers (2)

dxjuv
dxjuv

Reputation: 909

More than one of your entities have each other in themselves. For example, Product has an object of User, and User has an object of Product.

To solve this, you have to write

@JsonBackReference(value = "user-product")
private User user;

in the Product class, and

@JsonManagedReference(value = "user-product")
private Product product;

In the user class. Do it in every field and for every class that call each other.

Also, Check this out JPA: Having lists on both ends without infinite loop

Upvotes: 1

phisch
phisch

Reputation: 4731

You have cycles in your data model. For example, Product holds Images and Images point back to Products.

This works in an object oriented world, because only pointer references are stored in those fields.

When serialized, however, the actual object is written out as json text. Your Product prints the Images object which in turn prints the Product object which again prints the Image object and so on.

You need to decide how you want to represent your json, map your database model into simple plain old java object and use this for serializations. These POJOs are often called View Model or Transport Objects.

Upvotes: 1

Related Questions