Prevent circular reference with ModelMapper - List

Viewed 855

I'm having a Json error because my DTO's are keeping a circular reference each other.

CompanyDTO:

@Data
public class CompanyDTO {

    private Long id;
    private String name;
    private List<CompanyCountryDTO> companyCountries;
    //getters and setters
}

CompanyCountryDTO:

@Data
public class CompanyCountryDTO {

    private Long id;
    private LocalDateTime createdAt;
    private CompanyDTO company;
    private CountryDTO country;
    //getters and setters

CompanyService implementation convert a list of Company to a list of CompanyDTO:

@Override
public List<CompanyDTO> getAllCompaniesWithCountryDTO() {
   List<Company> listCompanies = companyRep.findAll();
   return listCompanies.stream().map(this::convertToDto).collect(Collectors.toList());
}

private CompanyDTO convertToDto(Company company) {
    CompanyDTO companyWithServiceDTO = modelMapper.map(company, CompanyDTO.class);
    return companyWithServiceDTO;
}

I would like to do something like this but using ModelMapper because I have others references that are circular:

listCompanies.stream().forEach(company -> {
    if (!ObjectUtils.isEmpty(company.getCompanyCountries())) {
        company.getCompanyCountries().forEach(companyCountry -> {
           companyCountry.setCompany(null);             
        });
    }
});

How can I remove company reference from CompanyCountryDTO since company also have another list of CompanyCountryDTO?

2 Answers

I think that you just need to skip the "back reference" to avoid circularity and infinite recursion. In this case the field company in CompanyCountryDTO.

To have it work configure your ModelMapper like:

modelMapper.addMappings(new PropertyMap<CompanyCountry, CompanyCountryDTO>() {
    @Override
    protected void configure() {
        // Tells ModelMapper to NOT populate company
        skip(destination.getCompany());
    }
});

http://modelmapper.org/user-manual/configuration/ says

Prefer nested properties | Determines if the implicit mapping should map the nested properties, we strongly recommend to disable this option while you are mapping a model contains circular reference | true

So another fix might be to

getConfiguration().setPreferNestedProperties(false);
Related