0

I have a problem I dont know how to track the StackOverFlowError it says And the converting to datatypes is okay but I dont know what the error comes from: How to fix this issue? Can you please help what is the most approach to track this error to generate the list and save it to database?

    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.pioneer.ams.backend.entity.AbstractEntity.toString(AbstractEntity.java:178)
    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 org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510)
    at java.lang.String.valueOf(String.java:2994)

Here's my code:

-- EmployeeService.java --

@Autowired
private EmployeeRepository employeeRepository;

public List<Map<String, String>> uploadEmployee(MultipartFile multip) throws Exception {

String fileNames = multip.getOriginalFilename();

DataFormatter formatter = new DataFormatter();

File file = new File("./reports/" + fileNames);
Workbook workbook = WorkbookFactory.create(file);

FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();

Sheet sheet = workbook.getSheetAt(0);

int headerRowNum = sheet.getFirstRowNum();

Map<Integer, String> colHeaders = new HashMap<Integer, String>();
Row row = sheet.getRow(headerRowNum);
for (Cell cell : row) {
    int colIdx = cell.getColumnIndex();
    String value = formatter.formatCellValue(cell, evaluator);
    colHeaders.put(colIdx, value);
}

  List<Employee> content = new ArrayList<>();
  for (int r = headerRowNum + 1; r <= sheet.getLastRowNum(); r++) {
   row = sheet.getRow(r);
   if (row == null)
      continue;
   Employee employee = new Employee();
   for (Map.Entry<Integer, String> entry : colHeaders.entrySet()) {
    int colIdx = entry.getKey();
    Cell cell = row.getCell(colIdx);
    if (cell != null) {
        String cellValue = formatter.formatCellValue(cell, evaluator);
        switch(entry.getValue()) {
             case "lastname": {
                  employee.setLastName(cellValue);
                  break;
             }
             case "firstname": {
                  employee.setFirstName(cellValue);
                   break;
             }
             case "mi": {
                  employee.setMiddleInitial(cellValue);
                   break;
             }
             case "rank": {
                  employee.setRank(cellValue);
                   break;
             }
             case "emp_id": {
                  employee.setEmpId(cellValue);
                   break;
             }
             case "po_company_id": {
                 POCompany poCompanyId = poCompanyRepository.findById(Long.parseLong(cellValue));
                  employee.setPoCompany(poCompanyId);
                  break;
             }
             case "business_id": {
                 Business businessId = businessRepository.findById(Long.parseLong(cellValue));
                  employee.setBusiness(businessId);
                   break;
             }
             case "department_id": {
                 Department departmentId = departmentRepository.findById(Long.parseLong(cellValue));
                  employee.setDepartment(departmentId);
                   break;
             }
             case "status_id": {
                 Status statusId = statusRepository.findById(Long.parseLong(cellValue));
                  employee.setStatus(statusId);
                   break;
               }
          }
          employeeRepository.save(employee);
       }
    }
    content.add(employee);
}

workbook.close();

System.out.println(content);

return content;
}

-- Employee.java --

@Entity
@Table(name = "employee")
public class Employee extends AbstractEntity<Long> {

private static final long serialVersionUID = 1L;

@Column(name = "lastname", length = 200)
private String lastName;

@Column(name = "firstname")
private String firstName;

@Column(name = "mi")
private String middleInitial;

@Column(name = "rank", nullable = true)
private String rank;

@Column(name = "emp_id")
private String empId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "po_company_id")
private POCompany poCompany;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "business_id")
private Business business;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Department department;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "status_id")
private Status status;

public Employee() {
    super();
}

public Employee(String empId, String lastName, String firstName, String middleInitial, String rank,
        List<User> user) {
    this();
    this.empId = empId;
    this.lastName = lastName;
    this.firstName = firstName;
    this.middleInitial = middleInitial;
    this.rank = rank;
    this.user = user;
}

public String getEmpId() {
    return empId;
}

public void setEmpId(String empId) {
    this.empId = empId;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getMiddleInitial() {
    return middleInitial;
}

public void setMiddleInitial(String middleInitial) {
    this.middleInitial = middleInitial;
}

public String getRank() {
    return rank;
}

public void setRank(String rank) {
    this.rank = rank;
}

public Department getDepartment() {
    return department;
}

public void setDepartment(Department department) {
    this.department = department;
}

public Status getStatus() {
    return status;
}

public void setStatus(Status status) {
    this.status = status;
}

public Business getBusiness() {
    return business;
}

public void setBusiness(Business business) {
    this.business = business;
}

public void setBranch(Branch branch) {
 this.branch = branch;
}

public POCompany getPoCompany() {
    return poCompany;
}

public void setPoCompany(POCompany poCompany) {
    this.poCompany = poCompany;
}
}

-- EmployeeController.java --

@RequestMapping(value = "/uploadEmployee", method = RequestMethod.POST)
public ResponseEntity<List<Employee>> uploadEmployee(MultipartFile file) throws Exception{

    return new ResponseEntity<List<Employee>>(employeeService.uploadEmployee(file), HttpStatus.OK);
}
Bryan Caliwag
  • 35
  • 3
  • 10

2 Answers2

2

You are facing the issue probably because you are returning the Employee.class entity object directly from your endpoint.In your Employee Entity class you have @ManyToOne relations with several tables.So, Jpa will resolve all these relations and populate the fields. In your Business.class or other entity class that you used in your code , you might be having a bi-directional relation mapping to the Employee. So , when Jackson tries to convert this class to a json it might be causing the StackOverflow error as a result of the Infinite reference.

Use annotations like @JsonBackReference and @JsonManagedBackReference to prevent infinite loop in your entity class returned.The better approach being to create a DTO object and map the entity fields to the DTO object and return the DTO object from the endpoint.

`@JsonManagedReference` is the forward part of reference – the one that gets serialized normally.
`@JsonBackReference` is the back part of reference – it will be omitted from serialization.

If this did not help, please provide more details like the entire stacktrace, as well as the entity classes referenced in Employee entity class. Read Guide.

Ananthapadmanabhan
  • 5,706
  • 6
  • 22
  • 39
1

The error is pretty clear:

at com.pioneer.ams.backend.entity.AbstractEntity.toString(AbstractEntity.java:178)

So you have a toString() implementation that creates a circular loop i.e.

A.toString(){
    //references B.toString();
}

B.toString(){
    //references A.toString();
}
Alan Hay
  • 22,665
  • 4
  • 56
  • 110