11

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;
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Dmitry Chkoniya
  • 111
  • 1
  • 1
  • 4
  • With the other reference you have defaultExpression = "java(null)" why don't you have it on the settlementCentre? – Simon Martinelli Jun 12 '19 at 09:57
  • I removed this condition at testing time. Anyway, defaultExpression = "java (null)" gives me != null check implementation – Dmitry Chkoniya Jun 12 '19 at 11:11
  • Does this happen only for `settlementCentre` or also for the other fields? – Filip Jun 13 '19 at 05:29
  • so strange, but it happens with only one field (settlementCentre), but I still need to write a lot of code, so I don’t know use mapstruct or not – Dmitry Chkoniya Jun 13 '19 at 06:46
  • 1
    After remove @Builder annotation from clazz (ClientDto - from nesux repository) the problem is gone, I think this is a bug in the mapstruct library. – Dmitry Chkoniya Jun 17 '19 at 07:03
  • I solved this issue with this answer : https://stackoverflow.com/questions/47676369/mapstruct-and-lombok-not-working-together#answer-47684351 – Joand Jan 27 '22 at 13:17

4 Answers4

12

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.

Filip
  • 19,269
  • 7
  • 51
  • 60
  • And, if you have properties 'addInfo' and if you use lombok builder still a problem, and it is marked 'wont fix'. Looks like only option is to remove the lombok Builder https://github.com/mapstruct/mapstruct/issues/2115 – kuhajeyan Feb 27 '23 at 09:07
3

I am also facing same error. In my case I have a boolean variable where I used is prefix on variable name. Then I used @Mapping in my mapper class and put same property name in target and remove

is

from source property name.

My source class looks like below

enter image description here

and my target class looks

enter image description here

and finally the function on my mapper class is like

enter image description here

Note here I am using lombok for setter and getter

Mapper generated my implementation class automatically. Here is my implementation class

enter image description here

0

I was facing this same issue. Reason behind it was @Builder annotation that was modifying default setters. After removing @Builder annotatino as said above it works fine.

  • 1
    This does not really answer the question. If you have a different question, you can ask it by clicking [Ask Question](https://stackoverflow.com/questions/ask). To get notified when this question gets new answers, you can [follow this question](https://meta.stackexchange.com/q/345661). Once you have enough [reputation](https://stackoverflow.com/help/whats-reputation), you can also [add a bounty](https://stackoverflow.com/help/privileges/set-bounties) to draw more attention to this question. - [From Review](/review/late-answers/30576339) – nighthawk Dec 13 '21 at 21:24
  • They didn't pose it as a question, sounds like a potential answer to me... – Josh M. May 26 '22 at 20:48
0

i had to remove @Builder as in 1st answer .. but @Getter @Setter not enough, I had to make for the relevant attribute one getter and one setter manually, too.. then it worked correctly -_-

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 06 '23 at 18:00