I’m trying to map DTOs to entities. I created a service that only takes care of mapping objects – ObjectMapper. DTO objects have relationships with each other. When I map a single object, for example when I create User, Group, Note, everything works. But when I want to use a method that returns a Note with a specific ID – /notes/{id}, I get the following error.
Handler dispatch failed; nested exception is java.langStackOverflowError] with root cause
To get specific Note, I need to use this mapping method that also cause this error. As u can see, I have to also convert Group and Tags.
//Note public NoteDTO NoteEntityToDtoGet(Note note) { NoteDTO noteDTO = new NoteDTO(); noteDTO.setId(note.getId()); noteDTO.setTitle(note.getTitle()); noteDTO.setDescription(note.getDescription()); noteDTO.setGroup(GroupEntityToDtoGet(note.getGroup())); noteDTO.setTags(TagConvertSet(note.getTags())); return noteDTO; }
When I don’t have relationships defined as another DTO in the DTO class, but as an entity, everything works, since I don’t have to convert the DTO to an entity.
Do you know where I’m making a mistake when mapping? Am I making a mistake in mapping multiple objects at once?
ObjectMapper
@Service public class ObjectMapper { //User public UserDTO UserEntityToDtoGet(User user) { UserDTO userDTO = new UserDTO(); userDTO.setId(user.getId()); userDTO.setName(user.getName()); userDTO.setEmail(user.getEmail()); userDTO.setGroup(user.getGroups()); return userDTO; } private UserCreationDTO UserEntityToDtoCreate(User user) { UserCreationDTO userCreationDTO = new UserCreationDTO(); userCreationDTO.setName(user.getName()); userCreationDTO.setEmail(user.getEmail()); return userCreationDTO; } private User UserDtoToEntityCreate(UserCreationDTO userCreationDTO) { User user = new User(); user.setName(userCreationDTO.getName()); user.setEmail(userCreationDTO.getEmail()); return user; } //Group public GroupDTO GroupEntityToDtoGet(Group group) { GroupDTO groupDTO = new GroupDTO(); groupDTO.setId(group.getId()); groupDTO.setName(group.getName()); groupDTO.setUser(UserEntityToDtoGet(group.getUser())); groupDTO.setNotes(NoteConvertList(group.getNotes())); groupDTO.setTags(TagConvertSet(group.getTags())); return groupDTO; } public GroupCreationDTO GroupEntityToDtoCreate(Group group) { GroupCreationDTO groupCreationDTO = new GroupCreationDTO(); groupCreationDTO.setName(group.getName()); groupCreationDTO.setUser(UserEntityToDtoGet(group.getUser())); groupCreationDTO.setTags(TagConvertSet(group.getTags())); return groupCreationDTO; } public Group GroupDtoToEntityCreate(GroupCreationDTO groupCreationDTO) { Group group = new Group(); group.setName(groupCreationDTO.getName()); return group; } //Note public NoteDTO NoteEntityToDtoGet(Note note) { NoteDTO noteDTO = new NoteDTO(); noteDTO.setId(note.getId()); noteDTO.setTitle(note.getTitle()); noteDTO.setDescription(note.getDescription()); noteDTO.setGroup(GroupEntityToDtoGet(note.getGroup())); noteDTO.setTags(TagConvertSet(note.getTags())); return noteDTO; } public Note NoteDtoToEntityCreate(NoteCreationDTO noteCreationDTO) { Note note = new Note(); note.setTitle(noteCreationDTO.getTitle()); note.setDescription(noteCreationDTO.getDescription()); return note; } public NoteCreationDTO NoteEntityToDtoCreate(Note note) { NoteCreationDTO noteCreationDTO = new NoteCreationDTO(); noteCreationDTO.setTitle(note.getTitle()); noteCreationDTO.setDescription(note.getDescription()); return noteCreationDTO; } public List<NoteDTO> NoteConvertList(List<Note> note) { return note.stream() .map(this::NoteEntityToDtoGet) .collect(Collectors.toList()); } //Tag public TagDTO TagEntityToDtoGet(Tag tag) { TagDTO tagDTO = new TagDTO(); tagDTO.setId(tag.getId()); tagDTO.setName(tag.getName()); tagDTO.setNotes(tag.getNotes()); tagDTO.setGroups(tag.getGroups()); return tagDTO; } public TagCreationDTO TagEntityToDtoCreate(Tag tag) { TagCreationDTO tagCreationDTO = new TagCreationDTO(); tagCreationDTO.setId(tag.getId()); tagCreationDTO.setName(tag.getName()); tagCreationDTO.setNotes(tag.getNotes()); return tagCreationDTO; } public Set<TagDTO> TagConvertSet(Set<Tag> groups) { return groups.stream() .map(this::TagEntityToDtoGet) .collect(Collectors.toSet()); } }
Advertisement
Answer
You get StackOverFlowError
because you end up with infinite recursive methods call and your application creates infinite amount of objects, so you just run out of memory:
1) your NoteEntityToDtoGet
method gets Note
‘s group and calls GroupEntityToDtoGet
method on the Group
object;
2) in GroupEntityToDtoGet
method you get all Group
‘s notes and call NoteConvertList
method on them, which calls NoteEntityToDtoGet
on each of the ‘Note’
3) step 1 again…
… the same cycle goes over and over without a stop until your stack memory, you know, overflows 🙂
So you should decide do your DTO classes really need to hold references to other entity collections.