Skip to content
Advertisement

Mapping multiple DTO to entities – nested exception

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.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement