I'm using Java 8, Spring Boot 2.3.4.RELEASE version, Maven as the build tool and IntelliJ as my IDE.
I have two DTO's called VehicleMasterDto and VehicleDetailDto
Using MapStruct, I created the following interface.
@Mapper(componentModel = "spring", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface MapStructVehicleMapper {
Vehicle toVehicle(VehicleMasterDto dto);
void updateVehicleFromDto(@MappingTarget Vehicle vehicle, VehicleDetailDto vehicleDetailDto);
}
Given below are the dependencies that I used.
<!-- MapStruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<!-- MapStruct processor -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
<scope>provided</scope>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<!-- MapStruct processor -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</path>
<!-- Lombok -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
The issue I'm facing is, when the mapstruct impl is generating in compile time, sometimes it generates the correct implementation, but sometimes it does not.
Given below is the correct implementation which is supposed to auto generate.
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2025-08-25T19:01:41+0530",
comments =
"version: 1.5.5.Final, compiler: javac, environment: Java 1.8.0_462 "
"(Private Build)"
)
@Component
public class MapStructVehicleMapperImpl implements MapStructVehicleMapper {
@Override
public Vehicle toVehicle(VehicleMasterDto dto) {
if (dto == null) {
return null;
}
Vehicle vehicle = new Vehicle();
vehicle.setVehicleNo(dto.getVehicleNo());
vehicle.setDriverMobileNo(dto.getDriverMobileNo());
vehicle.setDriverEmail(dto.getDriverEmail());
vehicle.setMaxWeight(dto.getMaxWeight());
vehicle.setMaxCapacity(dto.getMaxCapacity());
return vehicle;
}
@Override
public void updateVehicleFromDto(Vehicle vehicle, VehicleDetailDto vehicleDetailDto) {
if (vehicleDetailDto == null) {
return;
}
if (vehicleDetailDto.getDriverMobileNo() != null) {
vehicle.setDriverMobileNo(vehicleDetailDto.getDriverMobileNo());
}
if (vehicleDetailDto.getDriverEmail() != null) {
vehicle.setDriverEmail(vehicleDetailDto.getDriverEmail());
}
if (vehicleDetailDto.getMaxWeight() != null) {
vehicle.setMaxWeight(vehicleDetailDto.getMaxWeight());
}
vehicle.setMaxCapacity(vehicleDetailDto.getMaxCapacity());
}
}
Sometimes, it generates the following mapper which is incorrect:
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2025-08-26T09:43:06+0530",
comments =
"version: 1.5.5.Final, compiler: javac, environment: Java 1.8.0_462 "
"(Private Build)"
)
@Component
public class VehicleMapperMapStructImpl implements VehicleMapperMapStruct {
@Override
public Vehicle toVehicle(VehicleMasterDto dto) {
if (dto == null) {
return null;
}
Vehicle vehicle = new Vehicle();
return vehicle;
}
@Override
public void updateVehicleFromDto(Vehicle vehicle, VehicleDetailDto vehicleDetailDto) {
if (vehicleDetailDto == null) {
return;
}
}
}
Because of this random behavior, I can't trust Map Struct in our production environment. Thus I had to create a manual mapper. Can someone help me to understand the underlying issue here?
You need to put lombok first in annotationProcessorPaths.
EDIT
It may not work. You can specify annotationProcessor wich in turn isn't guarantee result either.
Only sure way is to use lombok - mapstruct integration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With