Reputation: 6057
I wrote a mapstruct mapper that uses a mapping like this:
@Mapping(target = "userId", source = "id.userId")
When I looked at the autogenerated mapstruct class I stubled upon that code:
if ( !foobar.hasId() ) {
return null;
}
This is a problem for me as hasId()
does not what mapstruct expects here. Can I force mapstruct somehow to not generate code that uses this method but checks for id != null
or something?
I could use a mapping like @Mapping(target = "userId", expression= "java(...)")
but I think there should be another way.
Upvotes: 6
Views: 2285
Reputation: 21094
MapStruct is treating the hasId()
method as a source presence checker method, only setting the id
value if it returns true
.
If conditionExpression
is specified, it is used instead of the source presence checker method. By specifying an always-true value for this, the value will always be mapped, rather than conditionally based on the result of hasId()
.
@Mapping(target = "userId", source = "id.userId", conditionExpression = "java(true)")
This results in the generated code like the following:
if ( true ) {
target.setUserId( userId );
}
Upvotes: 3
Reputation: 21094
While the answer that suggests providing your own AccessorNamingStrategy
explains how to solve this in general, often disabling the source presence checker is overkill. I think your solution of using expression
is probably often the right answer in terms of simplicity for a one-off override.
@Mapping(target = "userId", expression="java(source.getId().getUserId())")
MyTargetType map(MySourceType source);
or
@Mapping(target = "userId", source="id")
MyTargetType map(MySourceType source);
default String map(MySourceTypeId id) {
return id == null ? null : id.getUserId();
}
Upvotes: 1
Reputation: 21393
Yes you can force MapStruct not to use those presenceCheckers
. You can find more information in source presence checking in the documentation.
Basically the only way to do this is to provide an implementation of the MapStruct AccessorNamingStrategy
. You can just extend the DefaultAccessorNamingStrategy
and override itsisPresenceCheckMethod
.
You have access to the method ExecutableElement
and you can check the type of class it is in and other things as well.
MyAccessorNamingStrategy extends DefaultAccessorNamingStrategy {
@Override
public boolean isPresenceCheckMethod(ExecutableElement element) {
//You can do your checks here. You can ignore certain methods, from certain classes
}
Remember to register your SPI with a file META-INF-/services/com.example.MyAccessorNamingStrategy
There is also the examples where you can find an example for the SPI.
Upvotes: 5