5

How can I use the @Value annotation to configure a Joda-Time Period field in my spring bean?

E.g. Given the following component class:

@Component
public class MyService {

  @Value("${myapp.period:P1D}")
  private Period periodField;
...
}

I want to use standard ISO8601 format to define the period in a properties file.

I get this error:

Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [org.joda.time.Period]: no matching editors or conversion strategy found
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:302)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:125)
    at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:61)
    ... 35 more
Pat
  • 95
  • 1
  • 6

4 Answers4

8

A simple solution that does not require any java code is to use Spring Expression Language (SpEL).

(My example uses java.time.Duration and not Joda stuff but I think you get it anyway.)

    @Value("#{T(java.time.Duration).parse('${notifications.maxJobAge}')}")
    private Duration maxJobAge;
smasseman
  • 158
  • 2
  • 8
5

What you can do is register a Spring ConversionService bean and implement a proper converter.

@Bean
public ConversionServiceFactoryBean conversionService() {
    ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
    Set<Converter<?, ?>> myConverters = new HashSet<>();
    myConverters.add(new StringToPeriodConverter());
    conversionServiceFactoryBean.setConverters(myConverters);
    return conversionServiceFactoryBean;
}

public class StringToPeriodConverter implements Converter<String, Period> {

    @Override
    public Period convert(String source) {
        return Period.parse(source);
    }
}
Adam Michalik
  • 9,678
  • 13
  • 71
  • 102
1

Another, not elegant, option, is to use a String setter who invokes the parse method.

@Value("${myapp.period:P1D}")
public void setPeriodField(String periodField)
{
    if (isBlank(periodField))
        this.periodField= null;
    this.periodField= Duration.parse(periodField);
}
usr-local-ΕΨΗΕΛΩΝ
  • 26,101
  • 30
  • 154
  • 305
0

For joda-time:2.10.13 and spring-boot:2.3.2.RELEASE next example (like in question) is worked:

  @Value("${myapp.period:P1D}")
  private Period periodField;

If you use java.time.Period, in addition, worked a simple period property format (org.springframework.boot.convert.PeriodStyle):

  @Value("${myapp.period:1d}")
  private Period periodField;
zbender
  • 357
  • 1
  • 14