Reputation: 26858
I have a Spring Boot 2.2.6 application that uses an @ConfigurationProperties
component, something like this:
@Component
@ConfigurationProperties("myapplication")
public class MyApplicationSettings {
private LocalTime startOfDay;
// getter and setters here
}
My integration tests suddenly started failing on Jenkins, but worked fine locally. The exception was showing something like this:
Description:
Failed to bind properties under 'myapplication.start-of-day' to java.time.LocalTime:
Property: myapplication.start-of-day
Value: 06:00
Origin: class path resource [application-integration-test.properties]:29:62
Reason: failed to convert java.lang.String to java.time.LocalTime
Action:
Update your application's configuration
The full exception trace had a root cause of:
Caused by: java.time.format.DateTimeParseException: Text '06:00' could not be parsed at index 5
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.LocalTime.parse(LocalTime.java:463)
at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:72)
at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:46)
at org.springframework.format.support.FormattingConversionService$ParserConverter.convert(FormattingConversionService.java:217)
After some digging through the code, I discovered that Spring will use the default locale to parse the LocalTime
. As my local machine uses 24-hour notation, it works. The build server is on 12-hour locale, so it fails to parse the string because there is no am/pm indication.
My question:
How to configure Spring Boot to parse the configuration properties as ISO-8601 format, independent from the default locale of the JVM?
I also checked the documentation but the "Properties conversion" chapter does not mention LocalTime
(or LocalDate
)
Upvotes: 7
Views: 3289
Reputation: 42491
The solution should consist of the following steps:
@ConfigurationProperties
annotated class with LocalTime
field (MyApplicationSettings in your case) and register it in @Configuration
with @EnableConfigurationProperties(MyApplicationSettings.class)
application.properties
define the value:myapplication.startOfDay=06:00:00
@Component
@ConfigurationPropertiesBinding
public class LocalTimeConverter implements Converter<String, LocalTime> {
@Override
public LocalTime convert(String source) {
if(source==null){
return null;
}
return LocalTime.parse(source, DateTimeFormatter.ofPattern("HH:mm:ss"));
}
}
LocalTime
entries in @ConfigurationProperties
class will pass through this converter. Upvotes: 9
Reputation: 5388
There's a way to do it, but not a direct solution. You need a create a custom ConversionService
bean, place this code snippet in the Application file and it should work.
Here I'm registering a new converter that will convert always LocalTime
in the ISO_LOCAL_TIME format. You can choose to use other date formatter as well.
@Bean
public ConversionService conversionService() {
ApplicationConversionService conversionService = new ApplicationConversionService();
conversionService.addConverter(
String.class,
LocalTime.class,
(Converter) source -> LocalTime.parse((String) source, DateTimeFormatter.ISO_LOCAL_TIME));
return conversionService;
}
Upvotes: 0