Mapstruct problem: Unknown property error, but property is present

Dmitry Chkoniya picture Dmitry Chkoniya · Jun 12, 2019 · Viewed 7k times · Source

I'm using:

  • spring-boot 2.1.5.RELEASE
  • mapstruct 1.3.0.Final
  • lombok 1.18.8

and I'm trying to map two objects, Model and DTO:

  • DTO ClientDto - gotten from nesux repository as a dependency
  • Model Client

in both classes has a property settlementCentre, but at compile time I get an error (method toDto):

error: Unknown property "settlementCentre" in result type ru.rt.eip.boot.domain.ClientDto. Did you mean "null"?

but if i create class ClientDto directly in my project (not as a dependency) compilation goes without problems.

Surprisingly, but toModel method works fine, and after compile i see next in generated source:

@Override
Client toModel(ClientDto clientDto) {
    if ( clientDto == null ) {
        return null;
    }

    Client client = new Client();

    if ( clientDto.getSettlementCentre() != null ) {
        client.setSettlementCentre( settlementCentreDtoToSettlementCentre( clientDto.getSettlementCentre() ) );
    }
    else {
        client.setSettlementCentre( null );
    }
}

I have no idea how to fix this mapping problem. Someone can help?

here is my mapper:

@Mapper(
        componentModel = "spring",
        unmappedTargetPolicy = ReportingPolicy.IGNORE,
        uses = {EntityIdMapper.class,
                LegalFormMapper.class,
                EmployeeMapper.class,
                SettlementTypeMapper.class,
                TrippingDisabledReasonMapper.class,
                ProprietaryFormMapper.class,
                BillingGroupMapper.class,
                SettlementCentreMapper.class,
                ClientClassMapper.class,
                ClientCategoryMapper.class,
                DepartmentMapper.class},
        injectionStrategy = InjectionStrategy.CONSTRUCTOR
)
public abstract class ClientMapper {

    @Mappings({
            @Mapping(source = "client.parent.id", target = "parentId"),
            @Mapping(target = "isVip", defaultValue = "false"),
            @Mapping(target = "isSpecial", defaultValue = "false"),
            @Mapping(target = "includeToDebtor", defaultValue = "false"),
            @Mapping(target = "excludeFromInform", defaultValue = "false"),
            @Mapping(source = "client.passport", target = "passport", defaultExpression = "java(null)"),
            @Mapping(source = "client.trippingDisabledReason", target = "trippingDisabledReason", defaultExpression = "java(null)"),
            @Mapping(source = "client.proprietaryForm", target = "proprietaryForm", defaultExpression = "java(null)"),
            @Mapping(source = "client.billingGroup", target = "billingGroup", defaultExpression = "java(null)"),
            @Mapping(source = "client.clientClass", target = "clientClass", defaultExpression = "java(null)"),
            @Mapping(source = "client.settlementCentre", target = "settlementCentre")
    })
    abstract ClientDto toDto(Client client);

    @Mapping(source = "clientDto.settlementCentre", target = "settlementCentre", defaultExpression = "java(null)")
    abstract Client toModel(final ClientDto clientDto);
}

DTO - ClientDto:

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ClientDto implements BusinessObject, WithParent {
    private EntityIdDto id;
    private String dtype;
    @Deprecated //SystemInfo
    private Long currentVersion;
    private String juridicalType;
    private String nls;
    private String nlsAdditional;
    private String inn;
    private String kpp;
    private String title;
    private String shortName;
    private String juridicalName;
    private String email;
    private String phone;
    private Boolean isVip;
    @Deprecated //SystemInfo
    private Boolean isDeleted;
    private Boolean isSpecial;
    private LocalDateTime changeDate;
    @Deprecated //SystemInfo
    private LocalDateTime persistDate;
    @Deprecated //SystemInfo
    private LocalDateTime endDate;
    @Deprecated //SystemInfo
    private LocalDateTime localsystemdatesnapshot;
    private String settlementAccount;
    private String bik;
    private String contact;
    private String companyUrl;
    private String inetSystemCode;
    private Boolean includeToDebtor;
    private Boolean excludeFromInform;
    private String deliveryArea;
    private String passport;
    private String fldFilialName;
    private String fldDocumentUnId;
    @Deprecated //parent
    private EntityIdDto parentId;
    private DepartmentDto department;
    private DepartmentDto ownerFilial;
    private SettlementTypeDto settlementType;
    private ClientClassB2BDto clientClassB2B;
    private String fldClientAttributes;
    private String regionId;
    @Deprecated // Address
    private Map<String, AddressDto> adresses;
    @Deprecated // ClientCategory
    private Map<String, ClientCategoryDto> clientCategories;
    private ServiceClassDto serviceClass;
    private String className;
    private LegalFormDto legalForm;
    private EmployeeDto employee;
    private String lastName;
    private String firstName;
    private String middleName;
    private String gender;
    private LocalDate birthday;
    private ClientTypeDto clientType;
    private ClientDto parent;
    private AddressDto postAddress;
    private AddressDto lawAddress;
    private AddressDto deliveryAddress;
    private ClientCategoryDto clientCategory;
    private ClientCategoryDto clientCategorySub;
    private ClientCategoryDto clientCategoryMacro;
    private SystemInfoDto systemInfo;
    private DeliveryInfoDto deliveryInfo;
    private TrippingDisabledReasonDto trippingDisabledReason;
    private ProprietaryFormDto proprietaryForm;
    private DocumentTypeDto documentType;
    private BillingGroupDto billingGroup;

    private SettlementCentreDto settlementCentre;

    private ClientClassDto clientClass;
    private ContractDto contract;
    private String okved;
    private String okpo;
    private String ogrn;
    private String docNumber;
    private String birthPlace;
}

Model - Client

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Builder
@Table(name = "CLIENT")
public class Client {
    @EmbeddedId
    private EntityId id;
    @Column(name = "DTYPE")
    private String dtype;
    @Column(name = "JURIDICALTYPE")
    private String juridicalType;
    @Column(name = "NLS")
    private String nls;
    @Column(name = "NLSADDITIONAL")
    private String nlsAdditional;
    @Column(name = "INN")
    private String inn;
    @Column(name = "KPP")
    private String kpp;
    @Column(name = "TITLE")
    private String title;
    @Column(name = "SHORTNAME")
    private String shortName;
    @Column(name = "JURIDICALNAME")
    private String juridicalName;
    @Column(name = "EMAIL")
    private String email;
    @Column(name = "PHONE")
    private String phone;
    @Column(name = "VIP")
    private Boolean isVip;
    @Column(name = "ISSPECIAL")
    private Boolean isSpecial;
    @Column(name = "CHANGEDATE")
    private LocalDateTime changeDate;
    @Column(name = "SETTLEMENTACCOUNT")
    private String settlementAccount;
    @Column(name = "BIK")
    private String bik;
    @Column(name = "PASSPORT")
    private String passport;
    @Column(name = "CONTACT")
    private String contact;
    @Column(name = "COMPANYURL")
    private String companyUrl;
    @Column(name = "INETSYSTEMCODE")
    private String inetSystemCode;
    @Column(name = "INCLUDETODEBTOR")
    private Boolean includeToDebtor;
    @Column(name = "EXCLUDEFROMINFORM")
    private Boolean excludeFromInform;
    @Column(name = "DELIVERYAREA")
    private String deliveryArea;
    @Column(name = "FLDFILIALNAME")
    private String fldFilialName;
    @Column(name = "FLDDOCUMENTUNID")
    private String fldDocumentUnId;
    @Column(name = "FLDCLIENTATTRIBUTES")
    private String fldClientAttributes;
    @Column(name = "LASTNAME")
    private String lastName;
    @Column(name = "FIRSTNAME")
    private String firstName;
    @Column(name = "MIDDLENAME")
    private String middleName;
    @Column(name = "GENDER")
    private String gender;
    @Column(name = "BIRTHDAY")
    private LocalDate birthday;

    @Column(name = "BIRTHPLACE")
    private String birthPlace;
    @Column(name = "OKVED")
    private String okved;
    @Column(name = "OKPO")
    private String okpo;
    @Column(name = "OGRN")
    private String ogrn;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "PARENT_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "PARENT_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "PARENT_VERSION", referencedColumnName = "VERSION")})
    private Client parent;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "DEPARTMENT_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "DEPARTMENT_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "DEPARTMENT_VERSION", referencedColumnName = "VERSION")})
    private Department department;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "OWNERFILIAL_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "OWNERFILIAL_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "OWNERFILIAL_VERSION", referencedColumnName = "VERSION")})
    private Department ownerFilial;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "SETTLEMENTTYPE_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "SETTLEMENTTYPE_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID")})
    private SettlementType settlementType;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "CLIENTCLASSB2B_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "CLIENTCLASSB2B_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID")})
    private ClientClassB2B clientClassB2B;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "POSTADDRESS_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "POSTADDRESS_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "POSTADDRESS_VERSION", referencedColumnName = "VERSION")})
    private Address postAddress;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "LAWADDRESS_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "LAWADDRESS_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "LAWADDRESS_VERSION", referencedColumnName = "VERSION")})
    private Address lawAddress;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "DELIVERYADDRESS_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "DELIVERYADDRESS_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "DELIVERYADDRESS_VERSION", referencedColumnName = "VERSION")})
    private Address deliveryAddress;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "CC_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "CC_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID")})
    private ClientCategory clientCategory;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "CCS_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "CCS_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID")})
    private ClientCategory clientCategorySub;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "CCM_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "CCM_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID")})
    private ClientCategory clientCategoryMacro;
    @OneToMany(mappedBy = "client")
    private List<Contract> contracts;
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "SERVICECLASS_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "SERVICECLASS_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "SERVICECLASS_VERSION", referencedColumnName = "VERSION")})
    private ServiceClass serviceClass;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "MANAGER_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "MANAGER_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "MANAGER_VERSION", referencedColumnName = "VERSION")})
    private Employee employee;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "LEGALFORM_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "LEGALFORM_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "LEGALFORM_VERSION", referencedColumnName = "VERSION")})
    private LegalForm legalForm;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "CLIENTTYPE_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "CLIENTTYPE_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID")})
    private ClientType clientType;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "TDR_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "TDR_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID")})
    private TrippingDisabledReason trippingDisabledReason;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "BILLINGGROUP_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "BILLINGGROUP_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID")})
    private BillingGroup billingGroup;
    private SettlementCentre settlementCentre;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "PROPRIETARYFORM_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "PROPRIETARYFORM_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "PROPRIETARYFORM_VERSION", referencedColumnName = "VERSION")})
    private ProprietaryForm proprietaryForm;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "CLIENTCLASS_APP_PKID", referencedColumnName = "APP_PKID"),
            @JoinColumn(name = "CLIENTCLASS_LOCALSYSTEMID", referencedColumnName = "LOCALSYSTEMID"),
            @JoinColumn(name = "CLIENTCLASS_VERSION", referencedColumnName = "VERSION")})
    private ClientClass clientClass;

    @Embedded
    private SystemInfo systemInfo;
}

Answer

Filip picture Filip · Jul 8, 2019

This is a known bug in MapStruct. Fluent setters starting with set have the starting set removed so settlementDate becomes tlementDate. That is why when the Lombok @Builder is removed it works, it is then using the getters / setters on the object and not the builder.

You can track mapstruct/mapstruct#1799 for the problem.