Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MapStruct: How to pass input object to expression?

Tags:

mapstruct

In MapStruct version 1.1.0.Final, this was possible....

@Mappings({
    @Mapping(target = "transaction.process.details", expression = "java(MappingHelper.mapDetails(request))"),
     //more mappings
})
Response requestToResponse(Request request);

It was possible, since the mapDetails method was (by coincidence?) generated into the requestToResponse method. That's why request was not null.

Now, since 1.1.0.Final didn't work with Lombok, I had to upgrade to 1.2.0.CR2. With this version, the mapDetails will be generated into a separate method where request is not passed, so request is null within this method now and I get a NPE with the expression. (It's a sub-sub-method of requestToResponse now.)

Did I misuse the expression, so did it just work by coincidence, or does the new version has a bug? If no bug, how do I have to pass the request instance to the expression properly?

like image 726
Bevor Avatar asked Dec 14 '22 20:12

Bevor


1 Answers

You were / are misusing the expression. What you need to do is to map your target to your source parameter.

@Mapper(uses = { MappingHelper.class })
public interface MyMapper {

    @Mappings({
        @Mapping(target = "transaction.process.details", source = "request"),
         //more mappings
    })
    Response requestToResponse(Request request);
}

MapStruct then should create intermediary methods and use the MappingHelper and invoke the mapDetails method. In case you have multiple methods that map from Request to whatever type details are then you are going to need to used qualified mappings (see more here in the documentation).

It will look something like:

public class MappingHelper {
    @Named("mapDetails") // or the better type safe one with the meta annotation @Qualifier
    public static String mapDetails(Request request);
}

And your mapping will look like:

@Mapper(uses = { MappingHelper.class })
public interface MyMapper {

    @Mappings({
        @Mapping(target = "transaction.process.details", source = "request", qualifiedByName = "mapDetails"), //or better with the meta annotation @Qualifier qualifiedBy
         //more mappings
    })
    Response requestToResponse(Request request);
}
like image 101
Filip Avatar answered Jan 28 '23 15:01

Filip