0

I cound't find any solution to manage that fail, so I decided to create a new question. I have a simple class

@Entity
public class Reservation {

// private Integer RESERVATION_ID;
// private Integer id;
private long code;
private Date date;
private Client reservationClient;
private WashType reservationWashType;
private Vehicle reservationVehicle;
private Wash reservationWash;
private Worker reservationWorkerPesel;
private Review reservationReview;
private ReservationReminder reservationReminder;
 }

Where I run a query like that:

  @Query("SELECT r FROM Reservation r JOIN FETCH r.reservationReminder where r.reservationWorkerPesel = :worker")
List<Reservation> findByReservationWorkerPesel(@Param("worker") Worker worker);

And at first I everything looks nice, but then I do some operations like that:

    public List<ReservationReminder> findByReservationWorkerPesel(Worker worker) {
    List<ReservationReminder> reservationReminderList = new ArrayList<>();
    List<Reservation> byReservationWorkerPesel = reservationDao.findByReservationWorkerPesel(worker);
    for (Reservation r : byReservationWorkerPesel) {
        if (r.getReservationReminder() != null && r.getReservationReminder().getChecked() == false)
            reservationReminderList.add(r.getReservationReminder());
    }
    return reservationReminderList;
}

And after that when I see how JSON looks like - it's strange, because:

[{"reservationReminderId":2,"reservation":{"code":263022,"date":1487851200000,"reservationClient":{"clientPesel":"91122619197","name":"Client 1","surname":"Client 1","email":"client@wp.pl","phone":"234567890","accountNumber":"34567897654345678987654356","clientUser":{"userId":3,"login":"client","passwordHash":"$2a$10$0jJMMzeh2CTRagk3hwRSlurx.mxLgR1aAUQOYBD9QFqbISeoTSVN.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":

....

[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":{"timestamp":1489015140465,"status":200,"error":"OK","exception":"org.springframework.http.converter.HttpMessageNotWritableException","message":"Could not write content: Infinite recursion (StackOverflowError) (through reference chain: com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]-

...

\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"])","path":"/api/reservationreminder"}

What am I doing wrong?

Perhaps it can say you something - I don't why after making a GET method (only get) I got some those bugs?

enter image description here

bielas
  • 672
  • 2
  • 12
  • 29

2 Answers2

1

You have a Infinite recursion between your User and UserRole object. Whenever a user is serialized his related user roles are also serialized. Since user roles does also have a relation back to the user you have the recursion.

Solution to this could be to use @JsonManagedReference (added to the relation in User) and @JsonBackReference (realtion at UserRoles). See also here: Infinite Recursion with Jackson JSON and Hibernate JPA issue

@Entity
public class User
   ...
   @JsonManagedReference
   private Set<UserRole> userRoles;


@Entity
public class UserRole
   ...
   @JsonBackReference
   private User user;

@JsonManagedReference would mean that during serialization the relation part is taken into account. So the related user roles would be also serialized. Since there the related connection is marked with @JsonBackReference serialization stops to go further.

Community
  • 1
  • 1
KLHauser
  • 856
  • 5
  • 11
  • I have just realised where the problem is, but I can't get how to use `@JsonBackReference` and `@JsonManagedReference`? On which site should be put `@JsonBackReference` and on which site `@JsonManagedReference`? – bielas Mar 09 '17 at 08:48
  • Ok, but why you use `@JsonManagedReference private Set userRoles;` instead of `@JsonBackReference private Set userRoles;`? – bielas Mar 09 '17 at 09:04
  • Again edited ;).. I can't explain it better. Please also look into the other issue I linked. There somebody also descibed it (maybe better). – KLHauser Mar 09 '17 at 09:13
  • Ok, I understand. Below I asked question which is releated to those annotation, can you help me? – bielas Mar 09 '17 at 09:23
  • Maybe should have added a real new question. It's a little bit mixed up here. – KLHauser Mar 09 '17 at 09:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/137651/discussion-between-klhauser-and-bielas). – KLHauser Mar 09 '17 at 10:18
0

@KLHauser

So how to manage the case if I have a class

@Entity
public class ReservationReminder {
private int reservationReminderId;
private Reservation reservation;
private boolean isChecked;
private Date checkedDate;

and Reservation class

@Entity
public class Reservation {

// private Integer RESERVATION_ID;
// private Integer id;
private long code;
private Date date;
private Client reservationClient;
private WashType reservationWashType;
private Vehicle reservationVehicle;
private Wash reservationWash;
private Worker reservationWorkerPesel;
private Review reservationReview;
private ReservationReminder reservationReminder;

@Entity
public class Worker {

private String workerPesel;
private String name;
private String surname;
private Date startDateWorking;
private String accountNumber;
private List<Review> workerReview;
private Adress workerAdress;
private List<LaborHistory> workerLaborHistory;
private Wash workerWash;
//private List<WorkerWorkerTime> workerWorkTime;
// private Role WORKER_ROLE;
private User workerUser;
private List<Reservation> workerReservation;

And I'd like to load ReservationReminder class with Worker from Reservation class? If I use @JsonIgonre like that

@OneToOne(mappedBy = "reservationReminder", fetch = FetchType.LAZY)
@JsonIgnore
public Reservation getReservation() {
    return reservation;
}

I only got a Json with checkedDate, isChecked and reservationReminderId from ReservationReminder

bielas
  • 672
  • 2
  • 12
  • 29
  • If you want to load a ReservationReminder object together with Reservation and its Worker, then you should not use `@JsonIgnore` on any of the corresponding relations. It would mean that the relation would be ignored when generating the Json. – KLHauser Mar 09 '17 at 09:42
  • Also tried to use `@JsonManagedReference` and `@JsonBackReference `but doesn;t work – bielas Mar 09 '17 at 09:46
  • First you need to add these annotations to `User` and `UserRole` as descibed in my answer. Then if the infinite recursion there is fixed, we look further. A serialization path following the relations there would look like ReservationReminder -> Reservation -> Worker -> User -> UserRole – KLHauser Mar 09 '17 at 10:00
  • I fix the recursion. Can we create a chat ad discuss there further? – bielas Mar 09 '17 at 10:06
  • http://chat.stackoverflow.com/rooms/137651/discussion-between-klhauser-and-bielas – KLHauser Mar 09 '17 at 10:20