Reputation: 1058
When using multiple arguments in a @Mapper, it seems that the @Context arguments is unreachable
public interface MyMapper {
@Mapping(target="target1", source="arg1.arg") //works
@Mapping(target="target2", source="arg2") //works
@Mapping(target="target3", source="arg2.arg") //works
@Mapping(target="target2", source="context.arg") //NOT WORKING
public MyTarget convert(Object arg1, Object arg2, @Context Object context);
}
I am trying to use and expression=""
to work around it, but I can't get it to work.
Any suggestions?
I can see I am not the only one to ever wish this. https://github.com/mapstruct/mapstruct/issues/1280
Thanks
Upvotes: 21
Views: 41406
Reputation: 4140
To answer your second question:
public interface MyMapper {
@Mapping(target="target1", source="arg1.arg")
@Mapping(target="target2", ignore = true ) // leave to after mapping
MyTarget convert(Object arg1, @Context Object context);
@AfterMapping
default void convert(Object arg1, @MappingTarget MyTarget target, @Context context) {
target.setTarget2( convert (context) );
}
// if you have multipe mappings, you could address them here
@Mapping(target="target2", source="context.arg")
MyInnerTarget convert(Object arg1, Object context);
}
Upvotes: 8
Reputation: 12139
Alternative way, is to define additional mapping method:
public interface MyMapper {
@Mapping(target="target1", source="arg1.arg")
@Mapping(target="target3", source="arg2.arg")
@Mapping(target="target2", source="arg3.arg")
MyTarget convert(Object arg1, Object arg2, Object arg3, @Context Object context);
default MyTarget convert(Object arg1, Object arg2, Object context) {
return convert(arg1, arg2, context, context);
}
}
Upvotes: 0
Reputation: 510
I ran into the same scenario as I needed a @Context
param to be able to pass to a nested mapping function, but also wanted to use it as a source in a @Mapping
. I was able to achieve this using expression
as follows:
public interface MyMapper {
@Mapping(target="target1", source="arg1")
@Mapping(target="target2", source="arg2")
@Mapping(target="target3", expression="java( contextArg )")
public MyTarget convert(Object arg1, Object arg2, @Context Object contextArg);
}
Upvotes: 33
Reputation: 10294
Not really clean, but it seems having the same object as source and context allows to use it both ways.
@Mapping(target="target1", source="arg1.arg")
@Mapping(target="target2", source="arg2")
@Mapping(target="target3", source="arg2.arg")
@Mapping(target="target4", source="contextAsSource.arg")
public MyTarget convert(Object arg1, Object arg2, Object contextAsSource, @Context Object context);
Here contextAsSource and context are the same.
Upvotes: 2
Reputation: 4140
By definition a @Context
annotated object is not a source. It is context So you can't use it as source
in the @Mapping(target="target2", source="context.arg")
Here is a related github issue with official answer: github issue
Upvotes: 5