79703148

Date: 2025-07-16 08:47:47
Score: 0.5
Natty:
Report link

The problem you are facing is caused by mapstruct's mapping method resolution. From the docs(https://mapstruct.org/documentation/stable/reference/html/#mapping-method-resolution):

When mapping a property from one type to another, MapStruct looks for the most specific method which maps the source type into the target type. The method may either be declared on the same mapper interface or on another mapper which is registered via @Mapper#uses()

Because you have declared a String -> String mapping method inside the mapper interface, it is more specific than implicit String -> String mapping(https://mapstruct.org/documentation/stable/reference/html/#implicit-type-conversions).

To fix this, you can encode and map password inside @afterMapping method:

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
public abstract class UsuarioRegisterMapper {

    @Mapping(target = "rol", constant = "User")
    @Mapping(target = "id", ignore = true)
    Usuario toEntity(RegisterRequest request, @Context PasswordEncoder passwordEncoder);
    
    @AfterMapping
    protected void after(RegisterRequest request, @MappingTarget Usuario usuario, @Context PasswordEncoder passwordEncoder) {
        usuario.setContrasena(encodePassword(request.getContrasena()));
    }

    private String encodePassword(String rawPassword, PasswordEncoder passwordEncoder) {
        return passwordEncoder.encode(rawPassword);
    }
}

Note that the `encodePassword` method is private in mapper, so the implementation will not use it to map other fields.

You could also implement string encoding outside the mapper, and use qualifiers to apply it.

Also, refrain from using expression attribute in @Mapping, it is considered bad practice.

Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @afterMapping
  • User mentioned (0): @Mapping
  • Low reputation (1):
Posted by: Jan Borowy