티스토리 뷰

Spring을 사용하면서 외부 설정 파일(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이 로딩되는 경우 

아래 글을 참조하도록 하자. 

 

Springboot application.yml 파일의 값 가져오기 (feat. @Value is null)

아주 기본적인건데 삽질을 많이 했다. 나름 spring과 오랜 시간을 보내며 조금 안다고 생각을 했는데 한참 부족한것 같다. 지난번에 Springboot Batch Tasklet에 대해 글을 쓰며 두가지 방식에 소개를 했

oingdaddy.tistory.com

 

끝!

댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30