Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Map Struct sometimes generate the wrong mapper, and how can I fix it?

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?

like image 613
Arunoda Gunawardana Avatar asked Feb 17 '26 11:02

Arunoda Gunawardana


1 Answers

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.

like image 159
talex Avatar answered Feb 20 '26 02:02

talex