When lombok and mapstruct are used at the same time; the get and set methods of the pojo class fail to be generated, and the implementation class of mapstruct fails to be generated. It is just a new object.

Project scenario: When lombok and mapstruct are used at the same time; the get and set methods of the pojo class fail to be generated, and the implementation class of mapstruct fails to be generated. It is just a new object.

Project related background:

In recent work, I have been converting objects related to DTO, VO, and PO. I came into contact with the mapstruct toolkit and used lombok in the project. At this time, a problem occurred. When the two tools are used at the same time, lombok uses @Data. , @Setter, @Getter related annotations, the get and set methods failed to be generated, and the automatic conversion of mapstruct also failed to be generated.

Problem description

Problems encountered in the project:
Simplified code:

 <properties>
<org.mapstruct.version>1.5.0.Final</org.mapstruct.version>
        <org.projectlombok.verion>1.18.12</org.projectlombok.verion>
</properties>
\t
<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${org.projectlombok.verion}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

<!-- This is in the build tag -->
<annotationProcessorPaths>
    <path>
         <groupId>org.mapstruct</groupId>
         <artifactId>mapstruct-processor</artifactId>
         <version>${org.mapstruct.version}</version>
     </path>
     <path>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>${org.projectlombok.verion}</version>
     </path>
</annotationProcessorPaths>
@Data
public class TestDTO {<!-- -->
    
    private String name;
    
    private String age;
}
@Data
public class TestVO {<!-- -->
    
    private String name;
    
    private String age;
}
@Mapper
public class DtoAssembler {<!-- -->

    DtoAssembler INSTANCE = Mappers.getMapper(DtoAssembler.class);
    
    TestDTO toDTO(TestVO testVO);

}

After compilation at this time, TestDTO will not generate set and get methods;
The implementation class automatically generated through mapstruct just creates a new object, and no binding value is generated.

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2023-10-27T14:24:37 + 0800",
    comments = "version: 1.5.0.Final, compiler: javac, environment: Java 1.8.0_281 (Oracle Corporation)"
)
public class DtoAssemblerImpl implements DtoAssembler{<!-- -->
@Override
public TestVO toRegionInfoVO(TestDTO testDTO) {<!-- -->
\t    
if ( testDTO == null ) {<!-- -->
return null;
}
\t
TestVO testVO = new TestVO();
\t
return testVO;
}
}

Cause analysis:

Tip: Fill in the analysis of the problem here:

1. Before this problem first occurred, I confirmed that lombok can be used normally in the IDE and has been used in the project. There are no problems with plug-in installation and package import. So there are no problems related to lombok;

2. There is no problem in importing mapstruct;

3. I tried to manually generate set and get methods in related classes such as DTO and VO, and found that mapstruct can generate implementation classes normally. At this time, problems with mapstruct itself were queued;

4. Will there be an incompatibility problem between lombok and mapstruct? Because it is normal to use it alone, I think this is a direction. Then I searched for related questions on the Internet, but did not find the answer. I could only log on to the official website to query, and then found the answer in the middle.

5. Original description of mapstruct official website:

A brief explanation: First of all, MapStruct and Lombok can be used at the same time.
Starting from MapStruct 1.2.0. Beta1 and Lombok 1.16.14 versions, and divided into two situations
1. If you are using Lombok 1.18.16 or newer, you also need to add lombok-mapstruct-binding to make Lombok and MapStruct work together.

2. If you are using an older MapStruct or Lombok version, the solution is to separate the JavaBeans to be modified by Lombok and the mapper interface to be handled by MapStruct into two separate modules of your project. Lombok will then be run during the compilation of the first module, making the bean class complete when MapStruct is run during the compilation of the second module.

Judging from my situation, I belong to the first situation, which means that I need to add a new support package;

Solution:

Add a new third-party support package, used here: version 0.2.0,

 <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok-mapstruct-binding</artifactId>
         <version>${lombok-mapstruct-binding.version}</version>
     </dependency>


<path>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok-mapstruct-binding</artifactId>
        <version>${lombok-mapstruct-binding.version}</version>
   </path>

At this point, when compiling again, the methods and implementations are successfully generated.

@Data
public class TestDTO {<!-- -->
    
    private String name;
    
    private String age;

public String getName() {<!-- --> return this.name; }
\t
public String getAge() {<!-- --> return this.age; }

public void setName(final String name) {<!-- --> this.name = name; }
\t
public void setAge(final String age) {<!-- --> this.age = age; }

// ...If omitted here, it will not be copied. equals, toString
}
@Data
public class TestVO {<!-- -->
    
    private String name;
    
    private String age;

public String getName() {<!-- --> return this.name; }
\t
public String getAge() {<!-- --> return this.age; }

public void setName(final String name) {<!-- --> this.name = name; }
\t
public void setAge(final String age) {<!-- --> this.age = age; }

// ...If omitted here, it will not be copied. equals, toString
}
@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2023-10-27T16:29:32 + 0100",
    comments = "version: 1.5.0.Final, compiler: javac, environment: Java 1.8.0_281 (Oracle Corporation)"
)
public class DtoAssemblerImpl implements DtoAssembler{<!-- -->
@Override
public TestVO toRegionInfoVO(TestDTO testDTO) {<!-- -->
\t    
if ( testDTO == null ) {<!-- -->
return null;
}
\t
TestVO testVO = new TestVO();
testVo.setName( testDTO.getName() );
testVo.setAge( testDTO.getAge() );
return testVO;
}
}

in conclusion:
1. Lombok 1.18.16 or newer version, you need to add lombok-mapstruct-binding to use together;
2. The low version JavaBeans modified by Lombok and the mapper interface to be processed by MapStruct are divided into two separate modules of your project. Lombok will then be run during the compilation of the first module, making the bean class complete when MapStruct is run during the compilation of the second module.