Mapstruct adding parameter impossible?

60 views Asked by At

I want to upgrade my MapStruct mapper with using specefic class to remove duplicated code, but I don't really know how can I do it because in my case I have to use a specefic class for each mapper but I didn't know if there is a method to use/pass other things than my source and target

Exemple of mapper :

    @Named("idsToActivity")
    default List<Activity> idsToActivity(List<Long> longs) {
        return longs.stream().map(id -> {
            if (id == null) {
                return null;
            }
            Activity activity = new Activity();
            activity.setId(id);
            return activity;
        }).collect(Collectors.toList());
    }

I tried something like this for using it inside my mapper :

    private List<?> mapperIdToEntity(List<Long> longs){
        return longs.stream()
                .map(id -> {
                    if (id == null) {
                        return null;
                    }
                    ClassFromMapstruct entity = new ClassFromMapstruct();
                    entity.setId(id);
                    return entity;
                }).collect(Collectors.toList());
    }
1

There are 1 answers

0
GJohannes On

Yes it is possible to add more parameters than just "source" and "target" in a Mapstruct Mapping. A simple exampe would be the following:

Mapper:

public interface TestMapper {

    @Mapping(source = "testObject.name", target = "nameInDto")
    @Mapping(source = "testObject.age", target = "ageInDto")
    @Mapping(source = "someString", target = "someStringInDto")
    TestDTO mapToDto(TestObject testObject, String someString);
}

Entity

@Data
@AllArgsConstructor
public class TestObject {
    private String name;
    private Integer age;
}  

DTO

@Data
public class TestDTO {

    private String nameInDto;
    private Integer ageInDto;
    private String someStringInDto;
}

Proof of Concept in an Unit-Test

@Spy
private TestMapper testMapper = Mappers.getMapper(TestMapper.class);

@Test
void mappingTest() {
    TestDTO helloWorld = testMapper.mapToDto(new TestObject("aaa",32), "Hello World");
    System.out.println(helloWorld);
}

Output : TestDTO(nameInDto=aaa, ageInDto=32, someStringInDto=Hello World)

If you want to continue using @Named or similar mapstruct annotations like @AfterMapping, the method signature hast to match.

public interface TestMapper {

  @Mapping(source = "testObject.name", target = "nameInDto")
  @Mapping(source = "testObject.age", target = "ageInDto")
  @Mapping(source = "someString", target = "someStringInDto")
  TestDTO mapToDto(TestObject testObject, String someString);


  @AfterMapping
  default void doExtendedMapping(@MappingTarget TestDTO target, String someString) {
      //custom code here
      System.out.println(someString);
  }
}