0
votes

I have the following DTO classes:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Conclusion {

    private Integer id;
    // ......
    private List<CType> cTypes;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class CType {

    private Integer id;
    // ......
    private VType vType;
}

And also their corresponding entity classes:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "conclusion")
public class Conclusion {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, updatable = false)
    private Integer id;

    // ......

    @OneToMany
    @JoinColumn(name = "id")
    private List<CTypeEntity> cTypeEntities;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "c_types")
public class CTypeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, updatable = false)
    private Integer id;

    // ......

    @Column(name = "v_type_id")
    private Integer vTypeId;
}

Also, all corresponding Dao and JPA Repository interfaces are present. Now, I am writing my mapstruct Mapper interface which should be used for mapping entities to DTOs and vice versa. Here is the mapper:

@Mapper
public interface ConclusionMapper {

    @Mappings({
            @Mapping(target = "cTypes", source = "cTypeEntities")
    })
    Conclusion toConclusion(ConclusionEntity entity);

    List<Conclusion> toConclusionList(List<ConclusionEntity> entities);

    @Mappings({
            @Mapping(target = "cTypeEntities", source = "cTypes")
    })
    ConclusionEntity fromConclusion(Conclusion conclusion);

    List<ConclusionEntity> fromConclusionList(List<Conclusion> conclusions);

    @Mappings({
            @Mapping(target = "cType", source = "vTypeId", qualifiedByName = "formVType")
    })
    ConclusionTaxType toCType(CTypeEntity cTypeEntity);

    List<CType> toCTypes(List<CTypeEntity> cTypeEntities);

    CTypeEntity fromCType(CType cType);

    List<CTypeEntity> fromCTypeList(List<CType> cTypes);

    @Named("formVType")
    default VType formVType(CTypeEntity entity) {
        // TODO: instantiate a DAO which will return an instance of VType
        VTypeDao dao; // instantiate somehow

        return vTypeDao.findById(entity.getVId()); 
    }
}

VTypeDao looks like this:

public interface VTypeDao {
    VType findById(int id);

    boolean exists(int id);

    List<VType> findAll();
}

@Component
public class VTypeDaoImpl implements VTypeDao {
    private final VTypeRepo vTypeRepo;

    public VTypeDaoImpl(VTypeRepo vTypeRepo) {
        this.vTypeRepo = vTypeRepo;
    }

    // ............................. method implementations
}

My question is: How to instantiate an object of VTypeDao (or at least VTypeRepo so I could pass if to VTypeDaoImpl as a parameter)?

There is no factory class for getting the appropriate implementation of VTypeDao.

EDIT: VTypeDao and its implementation are third party components to my project.

3
What's the relation between the VTypeDao and MapStruct? Btw: you can add a parameter to the @Mapper annotation called componentmodel. This you can set to spring which makes the mapper a spring component. - Sjaak
There's no relation between VTypeDao and MapStruct. VTypeDao is kind of third party DAO and I need to use it in my MapStruct. And as far as I understand, annotating my MapStruct with componentmodel just allows me to use that it in some DAO implementation. My aim is vice versa: I want VTypeDao to be used in my MapStruct. - Armine

3 Answers

1
votes

From your comment I got you want to do lookups on your VTypeDao during the mapping process. You can wrap it in another class and hand it as @Context annotated as mapping argument. MapStruct will not consider such class as source or target. However it will call lifecycle methods in this class.. have a look at this example: https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-jpa-child-parent/src.

It's jpa based, but you can map it easily to your problem..

1
votes

I eventually ended up with the following implementation:

@Mapper
public interface ConclusionMapper {

    @Mappings({
           @Mapping(target = "cTypes", source = "cTypeEntities")
    })
    Conclusion toConclusion(ConclusionEntity entity);

    List<Conclusion> toConclusionList(List<ConclusionEntity> entities);

    @InheritInverseConfiguration
    ConclusionEntity fromConclusion(Conclusion conclusion);

    List<ConclusionEntity> fromConclusionList(List<Conclusion> conclusions);

    @Mappings({
            @Mapping(target = "vType", ignore = true)
    })
    ConclusionTaxType toCType(CTypeEntity cTypeEntity);

    List<CType> toCTypes(List<CTypeEntity> cTypeEntities);

    @Mappings({
            @Mapping(target = "vTypeId", source = "vType.id")
    })
    CTypeEntity fromCType(CType cType);

    List<CTypeEntity> fromCTypeList(List<CType> cTypes);
}

So I just ignored vType member in entity to DTO mapping and put it manually in my DAO since that was the most simple way of doing.

0
votes

Integrate map-struct with spring :
http://mapstruct.org/documentation/stable/reference/html/#using-dependency-injection

Replace @Mapper with below

@Mapper(componentModel = "spring")    

and add below in VTypeDaoImpl

@Autowired  
private ConclusionMapper conclusionMapper;

Execute below maven command (Assuming you are using maven)

mvn clean compile

sources will be generated in targeted/generated-sources/annotations