티스토리 뷰
Spring properties 사용시 UnsatisfiedDependencyException: Could not resolve placeholder 오류 조치
호형 2020. 12. 29. 12:57Spring을 사용하면서 외부 설정 파일(properties or yml)은 필수적으로 사용된다. 하지만 이를 읽어오지 못하는 문제는 자주 직면하게 된다. 예를 들면 다음과 같은 오류다.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'apiService': Unsatisfied dependency expressed through field 'jwtUtil'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jwtUtil': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'jwt.secretKey' in value "${jwt.secretKey}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:139)
at cj.enm.dmr.frontuserapi.BootApplication.main(BootApplication.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jwtUtil': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'jwt.secretKey' in value "${jwt.secretKey}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:380)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1244)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
... 23 common frames omitted
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'jwt.secretKey' in value "${jwt.secretKey}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:172)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:237)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:211)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:851)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1185)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
... 34 common frames omitted
이런 오류가 발생하면 해결하는 방법은 몇가지가 있다.
1. application.yml or application.properties 파일에 jwt.secretKey를 정의했는지 여부
@Value("${jwt.secretKey}")
private String secretKey;
@Value("${jwt.algorithm}")
private String algorithm;
이런식으로 Java에서는 잘 정의를 했다고 하더라도 application.yml or application.properties 에서는 정의를 하지 않았을 수도 있다.
jwt:
algorithm: "HS256"
이렇게 jwt.secretKey 의 정의를 빠뜨리지는 않았나 체크해보자.
2. application.yml or application.properties 를 사용하지 않고 별도의 외부 설정파일을 사용하는 경우
별도의 외부 설정파일을 정의해서 사용을 하는 경우는 그 파일을 읽을수 있도록 설정이 필요하다.
Annotation 방식
@Configuration
@PropertySource("classpath:config/jwt.properties")
public class JwtProperties {
@Value("${jwt.secretKey}")
private String secretKey;
@Value("${jwt.algorithm}")
private String algorithm;
Xml 방식
<context:property-placeholder location="classpath:config/jwt.properties"/>
application.yml or application.properties 가 아닌 jwt.properties 파일에서 관리하는 경우 이 파일이 읽힐수 있도록 별도로 명세를 해줘야 한다.
3. spring profile을 적용하지 않은 경우
위 두가지를 잘 했다 하였고 개발서버에서는 문제없이 잘 동작을 하는데 내 로컬에서만 외부 환경변수값들을 잘 읽어들이지 못하는 경우는 spring profile을 설정하지 않았을 수가 있다.
application.yml
management:
endpoints:
web:
exposure:
include:
- health
- info
- prometheus
---
spring:
profiles: local
jwt:
secretKey: "oingdaddyfighting"
algorithm: "HS256"
application.yml 파일에 위와 같이 구성을 해놨다고 한다면 spring profile을 local 로 지정을 해놓지 않으면 오류가 발생한다.
기동시키는 was의 vm argument에 -Dspring.profiles.active=local 을 추가시켜주도록 하자.
4. 그 외 Spring Batch 와 같이 Scope에 따라 bean이 로딩되는 경우
아래 글을 참조하도록 하자.
끝!
'Framework > Spring' 카테고리의 다른 글
Springboot 에서 @ComponentScan 설정 및 사용법 (2) | 2021.01.14 |
---|---|
Springboot + Redis 연동하는 초간단 샘플 만들어보기 (3) | 2021.01.05 |
Spring 설정 Xml Config에서 Java Config로 바꾸는 방법 (요령) (1) | 2020.12.21 |
spring 프로젝트에서 springboot 프로젝트로 migration 하기 (6) - XML config to JAVA config (0) | 2020.12.16 |
Springboot static resource ERR_ABORTED 404 오류 (1) | 2020.12.16 |