Search code examples
spring-bootmapstruct

Custom string to enum implementation is not called by mapstruct?


I have an entity called InstanceTask that has an Enum field called TaskStatusEnum status and a DTO InstanceTaskDto that has a String field called String status

Here is TaskStatusEnum:

@AllArgsConstructor
@Getter
public enum TaskStatusEnum {
    ACTIVE("En cours."),
    DONE("Traitée"),
    TO_DO("A faire");

    private final String value;
}

I'm trying to map from InstanceTaskDto.status to InstanceTask.status using mapstruct mapper:

@Mappings({
        @Mapping(target = "status" , source = "status", qualifiedByName = "getTaskInstanceStatusEnum"),
})
InstanceTask toEntity (InstanceTaskDto  instanceTaskDto);
@Mappings({       
        @Mapping(target = "status", source = ".", qualifiedByName = "getInstanceTaskStatus"),
})
 InstanceTaskDto  toDto (InstanceTask   instanceTask);

@Named("getInstanceTaskStatus")
default String getInstanceTaskStatus(InstanceTask instanceTask) 
{
    if(instanceTask.getStatus() == null)
        return null;

    return instanceTask.getStatus().getValue();
}

@Named("getTaskInstanceStatusEnum")
default Enum<TaskStatusEnum> getTaskInstanceStatusEnum(InstanceTaskDto instanceTaskDto) 
{
    if(instanceTaskDto.getStatus() == null)
        return null;

    TaskStatusEnum statusEnum = TaskStatusEnum.TO_DO;

    for (TaskStatusEnum status : TaskStatusEnum.values()) {
        if (status.getValue().equals(instanceTaskDto.getStatus())) {
            statusEnum = status;
        }
    }

    return statusEnum;
}

The issue i'm running into is that in the generated InstanceTaskMapperImpl getTaskInstanceStatusEnum is not called but instead this is the implementation of toEntity for the status field:

@Override
public InstanceTask toEntity(InstanceTaskDto instanceTaskDto) 
{
        if ( instanceTaskDto == null ) {
            return null;
        }

        InstanceTask instanceTask = new InstanceTask();

        if ( instanceTaskDto.getStatus() != null ) {
            instanceTask.setStatus( Enum.valueOf( TaskStatusEnum.class, instanceTaskDto.getStatus() ) );
        }
       // other stuff //
       return instanceTask ;
}

while on the toDTO, my custom method is called correctly:

@Override
    public InstanceTaskDto toDto(InstanceTask instanceTask) {
        if ( instanceTask == null ) {
            return null;
        }

        InstanceTaskDtoBuilder instanceTaskDto = InstanceTaskDto.builder();


        instanceTaskDto.status( getInstanceTaskStatus( instanceTask ) );
        // other stuff //
        return instanceTaskDto ;
    }

What do I have to do to make the toEntity implementation use my getTaskInstanceStatusEnum instead of the default implementation shown above?

Thank you.


Solution

  • Change default Enum<TaskStatusEnum>... to default TaskStatusEnum...