Warning
Models designed withBuilder Pattern is not supported with this solution
Models With Circular Dependencies
public class Child {
private String name;
private Father father;
// default constructor with accessors
}
public class Father {
private String name;
private List<Child> children = new ArrayList<>();
// default constructor with accessors
}
public class ChildDto {
private String name;
private FatherDto father;
// default constructor with accessors
}
public class FatherDto {
private String name;
private List<ChildDto> children = new ArrayList<>();
// default constructor with accessors
}
Define MappingContext
/**
* An implementation to track cycles in graphs to be used as {@link @Context} parameter.
*/
public class CycleAvoidingMappingContext {
private final Map<Object, Object> knownInstances = new IdentityHashMap<>();
/**
* Gets an instance out of this context if it is already mapped.
*
* @param source given source
* @param targetType given target type.
* @return Returns the resulting type.
*/
@BeforeMapping
public <T> T getMappedInstance(Object source, @TargetType Class<T> targetType) {
return targetType.cast(knownInstances.get(source));
}
/**
* Puts an instance into the cache, so that it can be remembered to avoid endless mapping.
*
* @param source given source
* @param target given target
*/
@BeforeMapping
public void storeMappedInstance(Object source, @MappingTarget Object target) {
knownInstances.put(source, target);
}
}
Define Mapper with MappingContext
@Mapper(componentModel = "spring", builder = @Builder(disableBuilder = true))
public interface CircularDependencyMapper {
FatherDto toDto(Father father, @Context CycleAvoidingMappingContext context);
ChildDto toDto(Child child, @Context CycleAvoidingMappingContext context);
}
Using Mapper
FatherDto fatherDto = circularDependencyMapper.toDto(father, new CycleAvoidingMappingContext());