본문 바로가기

SPRING

[Spring boot] java 파일을 특정 패키지로 이동 시 발생하는 ConflictingBeanDefinitionException 문제 해결

 

 

 

 

 

ControllerAdvice 를 이용하여 예외처리를 작업하던 중 패키지 이름에 대한 수정사항이 생겨 2개의 파일을 새로 만든 패키지로 이동시켰습니다. IntelliJ 에서는 워낙 Refactoring 기능을 다양하게 재공하기 때문에 파일을 옮기는데는 큰 문제는 발생하지 않았습니다.

하지만, Gradle 을 빌드하면서 다음과 같은 오류가 발생하였습니다.

 

10:05:20.310 [restartedMain] WARN  o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - (AbstractApplicationContext.java:557) Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [xxx.xxxx.xxxxApplication]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'businessExceptionControllerAdvice' for bean class [xxx.xxxx.xx.api.manager.exception.BusinessExceptionControllerAdvice] conflicts with existing, non-compatible bean definition of same name and class [com.xxxx.xx.api.manager.aspect.BusinessExceptionControllerAdvice]
  10:05:20.324 [restartedMain] ERROR o.s.boot.SpringApplication - (SpringApplication.java:858) Application run failed
  org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [xxx.xxxx.xxxxApplication]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'businessExceptionControllerAdvice' for bean class [com.xxxx.xx.api.manager.exception.BusinessExceptionControllerAdvice] conflicts with existing, non-compatible bean definition of same name and class [com.xxxx.xx.api.manager.aspect.BusinessExceptionControllerAdvice]
      at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:181)
      at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:315)
      at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232)
      at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275)
      at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95)
      at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705)
      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531)
      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 com.xxxx.xxxxApplication.main(xxxxApplication.java:39)
      at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.base/java.lang.reflect.Method.invoke(Method.java:566)
      at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
  Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'businessExceptionControllerAdvice' for bean class [com.xxxx.xx.xxx.manager.exception.BusinessExceptionControllerAdvice] conflicts with existing, non-compatible bean definition of same name and class [com.xxxx.xx.api.manager.aspect.BusinessExceptionControllerAdvice]
      at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:348)
      at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:286)
      at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132)
      at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:287)
      at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:242)
      at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199)
      at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167)
      ... 16 common frames omitted

  Process finished with exit code 0
  

 

위의 내용을 보면

nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name

ConflictingBeanDefinitionException 에러인 것을 볼 수 있습니다. 즉, Bean 의 이름이 중복이라는 것입니다.

 

하지만, 파일을 복사해서 옮긴 것이 아니라 파일을 이동시킨 것이기 때문에 아무리 찾아도 해당되는 중복된 파일이나 Bean 을 찾을 수 없었습니다.

 

 

단순히 뭔가 파일을 옮기면서 캐시 파일이나 symbols 같은 잔여물(?) 이 남아있는게 아닐까 추측 뿐이었습니다.

IntelliJ 에서 제공하는 Invalid Cash 나 Gradle reImport 를 실행해봤지만, 똑같은 오류만 계속 발생하였습니다.

그렇게 이것저것 시도해보다가 아래 Stack overflow 에서 답변을 보고 해결할 수 있었습니다.

https://stackoverflow.com/questions/28498295/spring-boot-conflictingbeandefinitionexception-annotation-specified-bean-name-f

 

 

핵심은 gradle warpper 를 이용해서 gradleclean 시켜주는 것 이었습니다.

./gradlew clean

Gradle Warpper 란, Gradle 을 build 하기 위한 Gradle 에서 공식적으로 제안하는 script 파일입니다.

Gradle 을 별다른 설치 작업 없이 버전을 내포해서 다운로드 및 실행시키기위해 필요한 스크립트입니다.

IntelliJ 에서는 Gradle 을 기본적으로 build tool 로 사용한다면 제공됩니다.

 

자세한 내용은 아래 공식 홈페이지를 참고 부탁드립니다.

https://docs.gradle.org/current/userguide/gradle_wrapper.html

 

 

만약, 단순 파일이동이나 작업 후 ConflictingBeanDefinitionException 오류가 발생하였는데 중복된 Bean 이 존재하지 않는다면 ./gradlew clean 을 우선적으로 실행시키는 것이 정신적으로나 시간적으로도 이롭습니다.

 

The Gradle Wrapper

It is recommended to always execute a build with the Wrapper to ensure a reliable, controlled and standardized execution of the build. Using the Wrapper looks almost exactly like running the build with a Gradle installation. Depending on the operating syst

docs.gradle.org