Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MapStruct mapper with BeanMapping#ignoreByDefault=true and SubclassMapping doesn't ignore properties from Subclasses

Tags:

java

mapstruct

Below is an example of the entity to DTO mapping and mapper and generated Map Struct implementation.


public abstract class User {
    private int id;
    private String firstName;
    private String lastName;
    private int age;
    private LocalDateTime dateOfBirth;
    private List<Address> addresses;
}

public class Address {
    private int userId;
    private String streetAddress;
    private String city;
    private String state;
    private String zipCode;
}

public class Employee extends User {
    private String designation;
    private Employee reportingManager;
}

public class Contractor extends User {
    private String contractingCompanyName;

}

public abstract class UserDTO {
    private int id;
    private String firstName;
    private String lastName;
    private int age;
    private LocalDateTime dateOfBirth;
}

public class EmployeeDTO extends UserDTO {
    private String designation;
    private EmployeeDTO reportingManager;
}

public class ContractorDTO extends UserDTO {
    private String contractingCompanyName;

}

@Mapper(subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION)
public abstract class UserMapper {

    @BeanMapping(ignoreByDefault = true)
    @SubclassMapping(source = Employee.class, target = EmployeeDTO.class)
    @SubclassMapping(source = Contractor.class, target = ContractorDTO.class)
    @Mapping(source = "id", target = "id")
    @Mapping(source = "firstName", target = "firstName")
    @Mapping(source = "lastName", target = "lastName")
    public abstract UserDTO map(User user);
}



Generated Mapper

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2023-07-14T12:56:15-0400",
    comments = "version: 1.5.5.Final, compiler: javac, environment: Java 17.0.5 (Amazon.com Inc.)"
)
public class UserMapperImpl extends UserMapper {

    @Override
    public UserDTO map(User user) {
        if ( user == null ) {
            return null;
        }

        if (user instanceof Employee) {
            return employeeToEmployeeDTO( (Employee) user );
        }
        else if (user instanceof Contractor) {
            return contractorToContractorDTO( (Contractor) user );
        }
        else {
            throw new IllegalArgumentException("Not all subclasses are supported for this mapping. Missing for " + user.getClass());
        }
    }

    protected EmployeeDTO employeeToEmployeeDTO(Employee employee) {
        if ( employee == null ) {
            return null;
        }

        EmployeeDTO employeeDTO = new EmployeeDTO();

        employeeDTO.setId( employee.getId() );
        employeeDTO.setFirstName( employee.getFirstName() );
        employeeDTO.setLastName( employee.getLastName() );
        employeeDTO.setDesignation( employee.getDesignation() );
        employeeDTO.setReportingManager( employeeToEmployeeDTO( employee.getReportingManager() ) );

        return employeeDTO;
    }

    protected ContractorDTO contractorToContractorDTO(Contractor contractor) {
        if ( contractor == null ) {
            return null;
        }

        ContractorDTO contractorDTO = new ContractorDTO();

        contractorDTO.setId( contractor.getId() );
        contractorDTO.setFirstName( contractor.getFirstName() );
        contractorDTO.setLastName( contractor.getLastName() );
        contractorDTO.setContractingCompanyName( contractor.getContractingCompanyName() );

        return contractorDTO;
    }

I expected that adding BeanMapping#ignoreByDefault=true would only map the explicitly mapped properties. But that is not the case with the subclasses.

I was hoping for a better way other than explicitly mapping each subtype and annotating with InhertConfiguration and excluding the other properties from the subclasses.

like image 879
Kartik Avatar asked Jan 22 '26 14:01

Kartik


1 Answers

As mentioned in MapStruct Discussion, this is a known bug in MapStruct versions up to 1.5.5 and is fixed in main (possibly in 1.6.0 Release)

like image 103
Kartik Avatar answered Jan 24 '26 02:01

Kartik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!