8

I am getting below error.

SLF4J: Failed toString() invocation on an object of type [com.xxxx.entity.Employee]
Reported exception:
java.lang.StackOverflowError
    at java.time.temporal.ValueRange.isValidIntValue(ValueRange.java:295)
    at java.time.temporal.ValueRange.checkValidIntValue(ValueRange.java:329)
    at java.time.temporal.ChronoField.checkValidIntValue(ChronoField.java:722)
    at java.time.LocalDate.ofEpochDay(LocalDate.java:341)
    at java.time.LocalDateTime.ofEpochSecond(LocalDateTime.java:422)
    at java.time.format.DateTimeFormatterBuilder$InstantPrinterParser.format(DateTimeFormatterBuilder.java:3194)
    at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2179)
    at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1746)
    at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1720)
    at java.time.Instant.toString(Instant.java:1330)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.xxxx.entity.AuditEnabledEntity.toString(AuditEnabledEntity.java:25)
    at com.xxxx.entity.Department.toString(Department.java:38)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.xxxx.entity.Employee.toString(Employee.java:30)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.xxxx.entity.Department.toString(Department.java:38)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.xxxx.entity.Employee.toString(Employee.java:30)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.xxxx.entity.Department.toString(Department.java:38)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.xxxx.entity.Employee.toString(Employee.java:30)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.xxxx.entity.Department.toString(Department.java:38)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.xxxx.entity.Employee.toString(Employee.java:30)

AuditEnabledEntity.java

@Data
@NoArgsConstructor
@AllArgsConstructor
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class AuditEnabledEntity {
    @CreatedDate
    @Column(name = "createdDate", nullable = false, updatable = false)
    private Instant createdDate;

    @LastModifiedDate
    @Column(name = "lastUpdateDate", nullable = false)
    private Instant lastUpdateDate;

    @Column(name = "createUser", nullable = false, length = IConst.USER_LENGTH)
    private String createUser;

    @Column(lastUpdateUser)
    private String lastUpdateUser;
}

Employee.java

@Data
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Employee extends AuditEnabledEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "emp_id")
    private Integer id;

    .......
    .......
    .......

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name = "program_member_program", 
            joinColumns = { @JoinColumn(name = "emp_id", nullable = false, updatable = false}, 
            inverseJoinColumns = { @JoinColumn(name = "dept_id", nullable = false, updatable = false})
    @JsonIgnore
    private List<Department> departments;

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "programMembers", cascade = CascadeType.ALL)
    @JsonIgnore
    private List<Role> roles;
}

Department.java

@Data
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper=true, includeFieldNames=true)
@NoArgsConstructor
@Entity
@Table(uniqueConstraints = {
        @UniqueConstraint(name="department_name_key",columnNames = {"department_name"})
})
public class Department extends AuditEnabledEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "department_id")
    private Long departmentId;

    ....
    ....
    ....
    ....

    // bi-directional
    @ManyToMany(fetch = FetchType.LAZY, mappedBy="employees", cascade = CascadeType.ALL)
    @JsonIgnore
    private List<Department> departments;
}
PAA
  • 1
  • 46
  • 174
  • 282

2 Answers2

12

You have a bidirectional reference between Employee (via field departments) and Department (we cannot see which field because you omitted that, or your pasted code is wrong). Both generated toString() methods in these classes call each other endlessly.

Exclude one of these fields for the generated toString() (preferably the field that is less important) using @ToString.Exclude.

PS: You will probably run into a similar problem for equals and hashCode. Exclude it there too using @EqualsAndHashCode.Exclude.

Jan Rieke
  • 7,027
  • 2
  • 20
  • 30
  • I can't simply omit references between `Employee` & `Department`. Also, not good practice to removed `Equals & Hashcode` when dealing with collections. Could you please show some code to fix this issue ? – PAA Aug 04 '19 at 08:10
  • 1
    You should not omit one of the fields, you should just skip it for the Lombok-generated `toString()`. – Jan Rieke Aug 04 '19 at 10:57
0

You can override toString method instead of lombok annotation