Search code examples
spring-bootjava-8convertersmapstructsoftware-quality

When should I use mapstruct or converters with java 8 to avoid error-prone?


At work, we use MapStruct in many SpringBoot projects with Java 8 REST Full applications and when we need to map Entity to DTO or DTO to Response or in similar cases. But today my friend showed me a great advantage of using a simple Converter instead of MapStruct.

This is a simple example using MapStrurct:

@Mapper(componentModel="spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface AccountMapper {
    @Mapping(source = "customerBank.customerId", target = "customerId")
    AccountResponse toResponse(AccountBank accountBank);
}

It works perfectly but actually in the case of someone change the customerId attribute by another name and forgets to change this mapper we will have a Runtime error.

The pros for Converter is we will have a Compile time error and avoid Runtime error.

Please, let me know if someone managed to share how to avoid Runtime error, like my presented scenario, using MapStruct, due to Converter does not bring the same advantage.

My question is: Is it possible to use MapStruct with efficiency, I mean without Runtime error prone?


Solution

  • If I understand well, you would like to have a compile-time error for wrong property naming, using MapStruct custom mapping. If so, you should add a necessary build plugin in your pom.xml (if you use maven).

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.5.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>${mapstruct.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
    

    And of course declare a property for MapStruct version:

    <properties>
        <mapstruct.version>1.4.1.Final</mapstruct.version>
    </properties>
    

    After compiling the project, with the added plugin, the annotation processor will generate full implementation: public class AccountMapperImpl implements AccountMapper In target\generated-sources\annotations folder. You can check generated source of the implementation class, all is set and carefully checked. In case of unexisting property names in @Mapping annotation, the compiler will throw an error.