user731136
user731136

Reputation:

Include Mapstruct context into internal mappers

I'm using MapStruct 1.3.0.Final to convert Dtos into POJOs and vice versa with the spring value into mapstruct.defaultComponentModel option. To avoid stackoverflow errors due to bidirectional relations I have followed the next link:

Mapping With Cycles

However, the compilation phase (to generate the implementations) is taking a lot of time (with only 20 files around 15 minutes and I need to include more ones).

I cannot "reuse" existing mappers due to I cannot "send" then the context using:

@Mapper(uses=B_Mapper.class)
A_Mapper ...

So, is there an optimization option to reduce the amount of time required? Is there a way to pass the context into the "internal mappers" (in the above example B_Mapper)?

UPDATE

That is the skeleton of the application:

public class EntityA {
  ...
  @OneToMany(mappedBy="entityA")
  private List<EntityB> entitiesB;
  ...
}

public class EntityB {
  ...
  @ManyToOne
  private EntityA entityA;
  ...
}

DTO:

public class DtoA { 
  ...
  private List<DtoB> dtosB;
  ...
}

public class DtoB { 
  ...
  private DtoA dtoA;
  ...
}

There are many more "columns and bidirectional relations" in several entities/dtos.

Converter:

public interface BaseConverter<D, E> {

  E fromDtoToEntity(final D dto, @Context CycleAvoidingMappingContext context);

  // This is the method I really use for the conversions
  @Named("originalFromDtoToEntity")
  default E fromDtoToEntity(final D dto) {
    return fromDtoToEntity(dto, new CycleAvoidingMappingContext());
  }
  ...
}

@Mapper
public interface AConverter extends BaseConverter<DtoA, EntityA>{}

@Mapper
public interface BConverter extends BaseConverter<DtoB, EntityB>{}

Upvotes: 1

Views: 1841

Answers (1)

Filip
Filip

Reputation: 21403

Looking at your converters it means that the CycleAvoidingContext is already passed if you use them. For example:

@Mapper(uses = BConverter.class, componentModel = "spring")
public interface AConverter extends BaseConverter<DtoA, EntityA>{}

@Mapper(uses = AConverter.class, componentModel = "spring")
public interface BConverter extends BaseConverter<DtoB, EntityB>{}

Then when invoking it MapStruct will correctly invoke fromDtoToEntity and pass the CycleAvoidingContext there.

Keep in mind the spring componentModel, the default cannot be used due to the cyclic dependency between the mappers.

Upvotes: 1

Related Questions