Hello,
I'm not entirely sure this is a bug as the use of source="." doesn't seem to be documented, but here it is anyway.
Considering the following example:
public class A {
public int field1A;
public int field2;
public int field3;
}
class B {
public int field1B;
public int field2;
public int field3;
}
class Wrap {
public B b;
}
@Mapper
interface MapInner {
// @Mapping(source = "field1A", target = "b.field1B")
@Mapping(source = ".", target = "b")
Wrap map(A a);
}
@Mapper
interface MapDirect {
// @Mapping(source = "field1A", target = "field1B")
@Mapping(source = ".", target = ".")
B map(A a);
}
The resulting mapping does bind field2 and field3 automatically, both for the direct A->B mapping and the A->Wrap(B)
class MapInnerImpl implements MapInner {
[...]
protected B aToB(A a) {
[...]
B b = new B();
b.field2 = a.field2;
b.field3 = a.field3;
return b;
}
}
class MapDirectImpl implements MapDirect {
@Override
public B map(A a) {
[...]
B b = new B();
b.field2 = a.field2;
b.field3 = a.field3;
return b;
}
}
However, when uncommenting the annotation that gives special instructions for an unmapped field, mapstruct no longer maps field2 and field3 for the A->Wrap(B) mapping but does it perfectly for the A->B mapping
class MapInnerImpl implements MapInner {
[...]
protected B aToB(A a) {
[...]
B b = new B();
b.field1B = a.field1A;
return b;
}
}
class MapDirectImpl implements MapDirect {
@Override
public B map(A a) {
[...]
B b = new B();
b.field1B = a.field1A;
b.field2 = a.field2;
b.field3 = a.field3;
return b;
}
}
I'm using version 1.4.1.Final
Note: working workaround is to use:
@Mapper
interface MapInner {
@Mapping(source = ".", target = "b")
Wrap map(A a);
@Mapping(source = "field1A", target = "field1B")
@Mapping(source = ".", target = ".")
B intermediateMap(A a);
}
The fact that dot (.) works in source is an accident. I don't think that we support that, so anything that works with that is an accident.
Why do you have to use .? Why can't you use the name of the parameter?
Why can't you use the name of the parameter?
It's not that I can't, it's just that as I have numerous fields, using source="." is simplier and faster to map them all
I don't think that we support that, so anything that works with that is an accident
Well, if it really is an accident and it was not meant to be, may I suggest making it an official feature? It's quite practical and worked great so far. It'd be a shame to have it disappear in later versions
What I meant is that instead of using source="." you can use source="a" (the name of the parameter in the source method), this has always been supported.
The problem with supporting it officially is multiple source parameters. What will that mean then?
Oh. I wasn't aware of this feature! Then indeed, using source="." seems useless now. And you're right, it'd be confusing with multiple sources.
I'll update all my mappers accordingly, and I'll test and see if it also resolves the issue presented in the ticket. I'll close it if it behaves as expected
Unfortunaly, the issue is also present with source="a". The resulting mapper is:
protected B aToB(A a) {
if ( a == null ) {
return null;
}
B b = new B();
b.field1B = a.field1A;
return b;
}
for
@Mapping(source = "a", target = "b")
@Mapping(source = "field1A", target = "b.field1B")
Wrap map(A a);
This could be related to #2278 and #2318.
I'll rename the issue and we will check it out
Most helpful comment
This could be related to #2278 and #2318.
I'll rename the issue and we will check it out