Java: Error passing references in a Supertype using Convert Pattern to convert DTO/Entity

Asked

Viewed 73 times

0

I’m doing a serialization process of a DTO class for Entity and vice versa. And for that, I use a design pattern called Convert Pattern.

At first, I created a generic class that performs these actions. see:

public abstract class Converter<DTO, ENTITY> {

    private final Function<DTO, ENTITY> fromDto;
    private final Function<ENTITY, DTO> fromEntity;

    public Converter(Function<DTO, ENTITY> fromDto, Function<ENTITY, DTO> fromEntity) {
        this.fromDto = fromDto;
        this.fromEntity = fromEntity;
    }

    public final ENTITY toEntity(final DTO dto) {
        return fromDto.apply(dto);
    }

    public final DTO toDto(final ENTITY entity) {
        return fromEntity.apply(entity);
    }

    public final List<ENTITY> toEntityList(final Collection<DTO> dtos) {
        return dtos.stream().map(this::toEntity).collect(Collectors.toList());
    }

    public final List<DTO> toDtoList(final Collection<ENTITY> entities) {
        return entities.stream().map(this::toDto).collect(Collectors.toList());
    }

    public final List<DTO> toDtoList(final Iterable<ENTITY> entities) {
        List<DTO> dtos = new ArrayList<>();
        entities.forEach(e -> dtos.add(toDto(e)));
        return dtos;
    }

}

And to use, I create a service that consumes this feature by extending this class, and step as class parameters to DTO and the Entity to establish the serialization process. Take an example:

@Service
public class DisciplinaConverter extends Converter<DisciplinaDto, DisciplinaEntity> {
    public DisciplinaConverter() {
        super(
                disciplinaDto -> new DisciplinaEntity(disciplinaDto.id, disciplinaDto.nome),
                disciplinaEntity -> new DisciplinaDto(disciplinaEntity.getId(), disciplinaEntity.getNome())
        );
    }
}

So far so good, they’re not custom objects. I’m finding trouble to actually render these objects. See an example of an error occurring:

@Service
public class TurmaConverter extends Converter<TurmaDto, TurmaEntity> {

    @Autowired
    private DisciplinaConverter disciplinaConverter;

    @Autowired
    private ProfessorConverter professorConverter;

    public TurmaConverter() {
        super(
            fromDto -> {
                TurmaEntity entity = new TurmaEntity();
                entity.setId(fromDto.id);
                entity.setDisciplina(disciplinaConverter.toEntity(fromDto.disciplina));
                entity.setProfessor(professorConverter.toEntity(fromDto.professor));
                return entity;
            },
            fromEntity -> new TurmaDto(
                fromEntity.getId(),
                professorConverter.toDto(fromEntity.getProfessor()),
                disciplinaConverter.toDto(fromEntity.getDisciplina())
            )
        );
    }
}

When I try to convert one the objects Professoredto/Professorentity and Disciplinadto/Disciplinaentity, acbo finding error:

Cannot reference 'TurmaConverter.disciplinaConverter' before supertype constructor has been called.

How to get out of this error to convert my object? I have tried to extract but haven’t had the solution yet.

1 answer

2

I believe the problem is occurring because you are using class attributes in the constructor and the attributes have not been injected (via @Autowired) by Spring.

Suggestions:

  1. Use a ready, tested and functional library that maps DTO / Entity, just like the Modelmapper. It’s not worth reinventing wheel. With Spring Boot is even simpler.

  2. Remove constructor logic by choosing another default (FactoryPattern, for example). No, seriously, use the Model Mapper and be happy.

  • Grateful for the advice... on Council 1 it is important to still evaluate it under the table. Because the business is not to reinvent the wheel, but to leave the performatico system. I do not know if modelmapper uses reflection can under the cloths. And reflection is a great enemy for performance. About the 2, standard that I usually use is the convert, but I will see the solution with the Factory. VLW!

  • I understand, but remember a famous phrase: "Premature optimization is the root of all evil". Joking aside, you can opt for Mapstruct, another mapping library, a little more complex to implement, however, one of the fastest in various benchmarks. He also works well with CDI. https://www.baeldung.com/mapstruct

Browser other questions tagged

You are not signed in. Login or sign up in order to post.