I've got a tree-like structure of entities that I'm trying to map to DTOs using ModelMapper. The trick is that I'm trying to break the graph after the first parent.
Following is a example of what I'm trying to do. I've got a Category entity which has a name and a parent Category. I want my DTO to have a link to it's parent but don't want the latter to have it's own parent (so that I don't get the whole hierarchy)
The trouble is that ModelMapper does not map my DTO's parent because it's of a different type; I declared it as being a DTO rather that a CategoryDTO in order to break the recursion. If I DO declare my parent as a CategoryDTO, the mapping works fine but I will get all of my parents and grand parents (which I do not want).
Anybody knows how I could fix this?
import java.util.UUID;
import org.junit.Assert;
import org.junit.Test;
import org.modelmapper.ModelMapper;
public class CategoryTest {
public static class Category {
private String uid = UUID.randomUUID().toString();
private String name;
private Category parent;
public Category () {}
public Category(String name, Category parent) {
this.name = name;
this.parent = parent;
}
public String getUid() {return uid;}
public void setUid(String uid) {this.uid = uid;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Category getParent() {return parent;}
public void setParent(Category parent) {this.parent = parent;}
}
public static class DTO {
private String uid;
private String name;
public String getUid() {return uid;}
public void setUid(String uid) {this.uid = uid;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
public static class CategoryDTO extends DTO {
private DTO parent;
public DTO getParent() {return parent;}
public void setParent(DTO parent) {this.parent = parent;}
}
@Test
public void simpleTest() {
Category dto = new Category("Test1",null);
CategoryDTO entity = new ModelMapper().map(dto, CategoryDTO.class);
Assert.assertEquals("Test1", entity.getName());
Assert.assertEquals(dto.getUid(), entity.getUid());
}
@Test
public void withParentTest() {
Category dto = new Category("child",new Category("root", null));
CategoryDTO entity = new ModelMapper().map(dto, CategoryDTO.class);
Assert.assertEquals("child", entity.getName());
Assert.assertEquals(dto.getUid(), entity.getUid());
Assert.assertNotNull(entity.getParent());
}
}
I've managed to solve my problem by customizing my ModelMapper with a Converter. My ModelMapper is now fetched by calling this method:
private ModelMapper getModelMapper() {
ModelMapper map = new ModelMapper();
map.addConverter(new AbstractConverter<Category, AbstractDTO>() {
@Override
protected AbstractDTO convert(Category source) {
if (source == null) return null;
AbstractDTO dto = new AbstractDTO();
dto.setUid(source.getUid());
dto.setName(source.getName());
return dto;
}
});
return map;
}