본문 바로가기

Programing/Framework

[SpringBoot] yml에서 Duration 사용하기는 2.1 부터 지원

yml 프로퍼티에서 Duration 사용을 하고 있었다.

pilot 프로젝트에서는 @Value로 잘 주입이 되는데, 본 branch로 해당 설정 코드를 옮겨오니 아래와 같은 에러가 발생했다.

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoBean' defined in com.github.detouched.DemoValueApp:
 Unsatisfied dependency expressed through method 'demoBean' parameter 0;
  nested exception is org.springframework.beans.ConversionNotSupportedException:
   Failed to convert value of type 'java.lang.String' to required type 'java.time.Duration';
    nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.time.Duration':
     no matching editors or conversion strategy found

로그를 보면 String 타입의 문자열을 Duration으로 변환하는 컨버터를 찾지 못했다는 것이다.

 

스프링 부트 깃헙의 이슈 13237을 보니Duration 타입의 설정은 application.properties 형태에서만 사용이 된다고 한다.
다행히 스프링팀에서도 스프링 부트 2.1 부터 yml에서도 컨버팅이 되도록 한다고 한다. ->  깃헙의 이슈12148 참고

본 브랜치의 스프링 부트 버전이 2.0.2.RELEASE 이다보니 Duration으로 변환이 되지 못하던 것이다.

주의해야 할 점은 단순히 build.gradle 상 버전만 수정하면 동일한 에러가 발생했다.
뭔가 캐싱이 되어 있는지 clear를 해야지 제대로 인식이 되었다.

2019-10-22 추가

통신사 멤버십 연동을 하다가 Duration을 적용을 했다.
확실히 시간기반으로 입력할 때보다 가독성이 좋다.

membership:
  redis:
    expire: 1h

만약 Duration을 안썼다면 아래와 같았을 것이다.

membership:
  redis:
    expire: 3600

이렇게되면 3600의 단위가 무엇인지 고민을 하게 된다.

참고로 포맷은 아래와 같다. (reference)

You can also use any of the supported units. These are:

  • ns for nanoseconds
  • us for microseconds
  • ms for milliseconds
  • s for seconds
  • m for minutes
  • h for hours
  • d for days

2020-03-20

Spring Integration을 하면서 connectTimeout은 단위가 초이고 soTimeout이나 remoteTimeout은 단위가 밀리초라서 Duration을 사용하게 되었다.

Duration을 다른 단위로 변환

초로..

int timeoutSeconds = (int)timeout.getSeconds();

밀리초로...

int timeoutMillis = (int)timeout.toMillis();

테스트 코드에서 Duration 값을 만들 때는 ofXXX 팩토리메서드를 이용하면 된다.

Duration.ofSeconds(3)