Im trying to use MapStruct to map an object that has a nested object and requires an external variable.
The source -> target mapping is lossy, and requires the external string
The target -> source mapping works and output is generated
I'm using Lombok and my objects are immutable.
//Entities
public class Repro {
@Value
@Builder
public static class Nested {
@NonNull
private String id;
@Nullable
private String version;
@NonNull
private String externalId;
}
@Value
@Builder
public static class SourceEntity {
@NonNull
private String id;
@NonNull
private String anotherId;
}
@Value
@Builder
public static class TargetEntity {
@NonNull
private Nested nested;
@NonNull
private String anotherId;
}
}
//Mapper
@Mapper
public interface ReproMapper {
@Mapping(target = "nested.version", ignore = true)
@Mapping(source = "source.id", target = "nested.id")
@Mapping(source = "source.anotherId", target = "anotherId")
@Mapping(source = "externalId", target = "nested.externalId")
Repro.TargetEntity fromSource(Repro.SourceEntity source, String externalId);
@Mapping(source = "nested.id", target = "id")
@Mapping(source = "anotherId", target = "anotherId")
Repro.SourceEntity fromTarget(Repro.TargetEntity target);
}
I get the error message (package names omitted):
Can't map property "Repro.SourceEntity source" to "Repro.Nested nested". Consider to declare/implement a mapping method: "Repro.Nested map(Repro.SourceEntity value)
Which tells me to implement a mapping method which is not feasible (since it would construct a partial Nested
object) which would fail during the build()
call.
Is there a way around this using MapStruct or do I just implement my own mapper ?
You could try it like this (handwritten method icm @MappingContext to hand down the externalId:
@Mapper
public interface ReproMapper {
@Mapping(target = "nested",source = "source")
@Mapping(target = "anotherId",source = "source.anotherId")
Repro.TargetEntity fromSource(Repro.SourceEntity source, @Context String externalId);
//A default impl that delegates to MapStruct generated method
default Repro.TargetEntity.Nested resolveNested(Repro.SourceEntity source, @Context String externalId) {
return delegate(source, externalId);
}
//Actual Mapping method, generated by MapStruct
//Note here externalId is not @Context annotated
@Mapping(target = "version", ignore = true)
@Mapping(target = "id", source = "source.id")
@Mapping(target = "externalId", source = "externalId")
Repro.TargetEntity.Nested delegate(Repro.SourceEntity source, String externalId)
@Mapping(source = "nested.id", target = "id")
@Mapping(source = "anotherId", target = "anotherId")
Repro.SourceEntity fromTarget(Repro.TargetEntity target);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With