Skip to content

Mapping with source parameter in Mapping#source ignored on inner objects when another mapping is specified #2322

Description

@tiller

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);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions