Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to spring inject configuration value for Joda Period

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
like image 256
Pat Avatar asked Nov 30 '15 17:11

Pat


People also ask

What are Joda-Time periods?

The first type, single-field periods, is new to version 1.4 of Joda-Time. These classes - Years, Months, Weeks, Days, Hours, Minutes, Seconds - all follow a very similar design, and only store the single field as implied by their name. Thus a Days object can only store a number of days.

How to bind properties to a POJO in Spring Framework?

The Spring framework uses standard Java bean setters, so we must declare setters for each of the properties. Note: If we don't use @Configuration in the POJO, then we need to add @EnableConfigurationProperties (ConfigProperties.class) in the main Spring application class to bind the properties into the POJO: That's it!

How to configure a Spring container with Java configuration?

For a reminder, there are three ways of configuring a Spring container: Using XML configuration, here we list all our beans in the XML file, Using XML component scan, here we make use of Java annotation, which simply scans and looks for classes with @Component class, Using Java Configuration class, which we will discuss in this article.

How to inject a dependency into a @configuration class?

For eg, had the bar bean been defined in a different @Configuration class , the way to inject the dependency then is along these lines: @Configuration public class AppConfig { @Autowired @Qualifier ("bar1") private Bar bar1; @Bean public Foo foo () { return new Foo (bar1); } }


3 Answers

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;
like image 157
smasseman Avatar answered Nov 03 '22 00:11

smasseman


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);
    }
}
like image 38
Adam Michalik Avatar answered Nov 03 '22 01:11

Adam Michalik


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);
}
like image 25
usr-local-ΕΨΗΕΛΩΝ Avatar answered Nov 02 '22 23:11

usr-local-ΕΨΗΕΛΩΝ