Skip to content

MapStruct does not always use builders in target-object #1997

@mfriess2

Description

@mfriess2

Hi,

we try to use MapStruct with Lombok builders but MapStruct does not always seem to recognize and use the builders. Our particular problematic case is when the target object has a field which only has a builder.

Used MapStruct version: 1.3.1.FINAL
Used Lombok version: 1.18.10

It would be very helpful for us if you could let us know if this is considered a bug or not.
Looking forward to your feedback!

Here is an example:

Source POJO:

package example.model.source;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Car {
	private String model;
}

Target POJOs:

package example.model.target;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class CarInsurance {
	private CarDetail carDetail;   // this is the problematic case
}

@Data
@Builder
public class CarDetail {
	private String model;
}

Mapper:

package example.mapper;

import example.model.source.Car;
import example.model.target.CarInsurance;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;

@Mapper
public interface CarInsuranceMapper {
	@Mapping(source = "model", target = "carDetail.model")
	void map(Car source, @MappingTarget CarInsurance target);
}

MapStruct generates this mapper:

package example.mapper;

import example.model.source.Car;
import example.model.target.CarDetail;
import example.model.target.CarInsurance;
import javax.annotation.Generated;
import org.springframework.stereotype.Component;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor"
)
@Component
public class CarInsuranceMapperImpl implements CarInsuranceMapper {

    @Override
    public void map(Car source, CarInsurance target) {
        if ( source == null ) {
            return;
        }

        if ( target.getCarDetail() == null ) {
            target.setCarDetail( new CarDetail() );  // THIS CREATES A COMPILE ERROR
        }
        carToCarDetail( source, target.getCarDetail() );
    }

    protected void carToCarDetail(Car car, CarDetail mappingTarget) {
        if ( car == null ) {
            return;
        }

        mappingTarget.setModel( car.getModel() );
    }
}

And the compiler fails with:

CarInsuranceMapperImpl.java:22: error: constructor CarDetail in class CarDetail cannot be applied to given types;
            target.setCarDetail( new CarDetail() );

It would work if MapStruct would generate:

if ( target.getCarDetail() == null ) {
    target.setCarDetail( CarDetail.builder().build() );
}

The annotation processor ordering in the Gradle build:

	implementation 'org.mapstruct:mapstruct'
	implementation 'org.projectlombok:lombok'
	annotationProcessor 'org.mapstruct:mapstruct-processor'
	annotationProcessor 'org.projectlombok:lombok'

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions