I asked today a question, i created a user model.
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "_user")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class User implements UserDetails {
@Id
@GeneratedValue
private Integer id;
private String firstname;
private String lastname;
@NotNull
@Column(unique=true)
private String email;
@NotNull
@Column(unique=true)
private String usrname;
@NotNull
@ColumnDefault("'img/avatar1.jpg'")
private String avatar;
@JsonIgnore
private String password;
@Enumerated(EnumType.STRING)
private Role role;
@JsonIgnore
@OneToMany(mappedBy = "user")
private List<Token> tokens;
In my service, i'd like to get the result when i evaluate method :
User updateUser = userRepository.getById(userId)
.orElseThrow(() -> new ResourceNotFoundException("L'utilisateur n'existe pas avec l'id: " + userId));
Here is my getById(userId)
@Query(value = "SELECT * FROM _user u where u.id = :id", nativeQuery = true)
Optional<User> getById(int id);
When i evaluate method to get result, i got this :
But there is no problems, because my code continue executing .. Strange things, in console, i haven't StackOverflow issues..
I want to enter in debug mode and evaluate result because i got a ERROR [https-jsse-nio-443-exec-3] c.d.x.ExceptionHandler: Could not commit JPA transaction
error.
EDIT
Add the fullstacktrace and my userId is int(1) not a String.
I hope someone had this bug and solved it.
The root cause is probably this lombok issue since toString()
method is by default invoked from console debugger and it fails because of infinitive recursion which is then causing the StackOverflowError.
The root cause for this in your specific example is the
public class User implements UserDetails {
....
@JsonIgnore
@OneToMany(mappedBy = "user")
private List<Token> tokens;
}
One workaround to solve this issue would be to exclude the field from toString()
that contains references back to the original object which causes infinite recursion. Somewhere in your Token.class
there should be a field:
@ManyToOne
private User user;
You can use there the lombok annotation @ToString.Exclude
as
@ManyToOne
@ToString.Exclude
private User user;
Now toString()
method provided from lombok for User.class
will be able to print the list from Token.class
without causing infinite recursion since the reference back to the original object will not be considered in that objects toString()
.