Search code examples
javamodelconvertersmodelmapper

Custom converter in ModelMapper not working


I have a converter that converts a double to a string. Before conversion, I want to format the double to a fix number of decimal place. But I noticed that it is not being invoked. Here is my method:

The two models I have has the same attribute names.

private String price;  // my DTO
private Double price;  // my JPA entity

This is my modelMapper bean ModelMapperConfig.java:

public ModelMapper modelMapper() {
  ModelMapper modelMapper = new ModelMapper();
  modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
  modelMapper.getConfiguration().setAmbiguityIgnored(true);
  modelMapper.addConverter(convertDoubleToString());
  return modelMapper;
}

private Converter<Double, String> convertDoubleToString() {
    return mappingContext -> Utility.formatDoubleToString(mappingContext.getSource());
}

The ModelMapper is mapping my Double to String fine.

But it is not keeping to the formatted decimal place. Any idea what I am missing?


Solution

  • Adding converter directly to ModelMapper like this:

    modelMapper.addConverter(convertDoubleToString());
    

    has never quite worked for me if implementing Converter interface. Luckily you can have your converter registered against TypeMap so this should work:

    modelMapper.createTypeMap(Double.class, String.class)
               .setConverter(convertDoubleToString());      
    

    Another way to get it registered successfully is to extend AbstractConverter which is a bit more ugly way:

    private AbstractConverter<Double, String> convertDoubleToString = 
        new AbstractConverter<>() {
        @Override
        protected String convert(Double src) {
            return Utility.formatDoubleToString(src);
        }
    };
    

    Then this works:

    modelMapper.addConverter(convertDoubleToString);
    

    The difference might be (so just guessing) that due to the type erasure ModelMapper might not be able to associate converter correctly when Interface is implemented so it needs explicit type mapping.