Issue
I have a personal war going against writing java code in strings. What I'm trying to achieve is 100% doable with an expression. I would, however, like to try and find a way of doing it without.
Situation:
TargetJpa {
...
Instant createdAt;
}
What I want to do:
// using 1.5.2.Final
@Mapper(...)
public interface JpaMapper {
@Mapping(target = "createdAt", qualifiedByName = "now")
TargetJpa toJpa(Srouce s);
@Named("now")
default Instant now() {
return Instant.now();
}
}
This obviously does not work. It complains that I'm missing a source. Which is correct, I don't need a source, I'm generating a value. But this can't be a constant. And I personally wish to use java code in strings as little as humanly possible.
Ofc, there is an obvious workaround, pass a dummy source value.
@Mapper(...)
public interface JpaMapper {
@Mapping(target = "createdAt", source = "s", qualifiedByName = "now")
TargetJpa toJpa(Srouce s);
@Named("now")
default Instant now(Source s) {
return Instant.now();
}
}
But this has a huge disatvantage. Had I not have to name a source, I could remove this "now" from this interface alltogeather, make a "InstantMapper" and reuse the code:
@InstantMapper
public class InstantMapperImpl {
@Now
default Instant now() {
return Instant.now();
}
}
Then use it on anything:
... uses = { ..., InstantMapperImpl.class }
...
@Mapping(target = "createdAt", qualifiedBy = {InstantMapper.class, Now.class})
TargetJpa1 toJpa(Srouce1 s);
@Mapping(target = "createdAt", qualifiedBy = {InstantMapper.class, Now.class})
TargetJpa2 toJpa(Srouce2 s);
@Mapping(target = "createdAt", qualifiedBy = {InstantMapper.class, Now.class})
TargetJpa3 toJpa(Srouce3 s);
Any way to achieve this without tying myself to some source that I simply don't need?
Solution
MapStruct currently doesn't support using a random method to map into a specific property. When using Mapping#target
you have few options that you can use for the source of the mapping:
source
- map from a specific sourceexpression
- map using an expressionconstant
- map using some constant valueignore
- ignore the mapping
All the rest of the properties are in one way or another used for specifying some other things for the mapping.
When none of those 4 options are provided it is assumed that the value that is in target
is the value in source
.
e.g.
@Mapping(target = "createdAt", qualifiedByName = "now")
actually means
@Mapping(target = "createdAt", source = "createdAt", qualifiedByName = "now")
If you are interested in seeing something like you are requesting in MapStruct I would suggest raising a feature request
Answered By - Filip
Answer Checked By - Candace Johnson (JavaFixing Volunteer)