17

I writing application using spring-boot-starter-jdbc (v1.3.0).

The problem that I met: Instance of BeanPropertyRowMapper fails as it cannot convert from java.sql.Timestamp to java.time.LocalDateTime.

In order to copy this problem, I implemented org.springframework.core.convert.converter.Converter for these types.

public class TimeStampToLocalDateTimeConverter implements Converter<Timestamp, LocalDateTime> {

    @Override
    public LocalDateTime convert(Timestamp s) {
        return s.toLocalDateTime();
    }
}

My question is: How do I make available TimeStampToLocalDateTimeConverter for BeanPropertyRowMapper.

More general question, how do I register my converters, in order to make them available system wide?

The following code bring us to NullPointerException on initialization stage:

private Set<Converter> getConverters() {
    Set<Converter> converters = new HashSet<Converter>();
    converters.add(new TimeStampToLocalDateTimeConverter());
    converters.add(new LocalDateTimeToTimestampConverter());

    return converters;
}

@Bean(name="conversionService")
public ConversionService getConversionService() {
    ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();
    bean.setConverters(getConverters()); 
    bean.afterPropertiesSet();
    return bean.getObject();
}    

Thank you.

M. Deinum
  • 104,041
  • 21
  • 200
  • 207
  • 2
    Just add your converter as a bean... Remove everything else. – M. Deinum Dec 14 '15 at 11:00
  • Confusing `HttpMessageConverter` and `Converter` here. Just add a class that extends `WebMVcConfigurerAdapter` and implement the `addFormatters` method. On the `FormatterRegistry` call `addConverter` for the ones you want to add. – M. Deinum Dec 14 '15 at 11:14
  • 1
    I do not have web environment at all. –  Dec 15 '15 at 12:18
  • Then it indeed won't work :). But the code you have should work, can you add the full configuration class and the error you get (the stack trace) when you use this... – M. Deinum Dec 15 '15 at 12:25
  • To save some code I wouldn't call the `afterPropertiesSet()` and `getObject()`. instead let Spring do that for you, simply return the factory bean. – M. Deinum Dec 15 '15 at 12:34
  • Possible duplicated off https://stackoverflow.com/questions/35025550/register-spring-converter-programmatically-in-spring-boot/41205653#41205653 – deFreitas Dec 01 '17 at 23:29

4 Answers4

2

All custom conversion service has to be registered with the FormatterRegistry. Try creating a new configuration and register the conversion service by implementing the WebMvcConfigurer

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addallFormatters(FormatterRegistry registry) {
        registry.addConverter(new TimeStampToLocalDateTimeConverter());
    }
}

Hope this works.

0

I suggest to use @Autowired and the related dependency injection mechanism of spring to use a single ConversionService instance throughout your application. The ConversionService will be instantiated within the configuration.

All Converters to be available application wide receive an annotation (e.g. @AutoRegistered). On application start a @Component FormatterRegistrar (Type name itself is a bit misleading, yes it is "...Registrar" as it does the registering. And @Component as it is fully spring managed and requires dependency injection) will receive @AutoRegistered List of all annotated Converters.

See this thread for concrete implementation details. We use this mechanism within our project and it works out like a charm.

Community
  • 1
  • 1
s10z
  • 1,025
  • 8
  • 11
0

org.springframework.web.servlet.config.annotation.WebMvcConfigurer or any on its implementation is one stop place for any kind of customization in spring boot project. It prvoides various methods, for your Converter requirement.

Just create a new Converter by extending org.springframework.core.convert.converter.Converter<S, T>. Then register it with Spring by your class overriding method org.springframework.web.servlet.config.annotation.WebMvcConfigurer.addFormatters(FormatterRegistry)

Note there are Other types of Converter also which basically starts from ConditionalConverter.

UkFLSUI
  • 5,161
  • 6
  • 32
  • 45
SauriBabu
  • 240
  • 1
  • 14
-2

Trying adding

@Converter(autoApply = true)

Its needs to be placed over the convertor class. This works for me in case of Convertor needed for Localdate for interacting to DB.

@Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> {

    @Override
    public Date convertToDatabaseColumn(LocalDate locDate) {
      return (locDate == null ? null : Date.valueOf(locDate));
    }

    @Override
    public LocalDate convertToEntityAttribute(Date sqlDate) {
      return (sqlDate == null ? null : sqlDate.toLocalDate());
    }
}

This is now applied automatically while interacting with DB.

Ankit Bansal
  • 1,868
  • 4
  • 33
  • 63