트러블슈팅(Trouble Shooting)

class path resource ‘A’ cannot be opened because it does not exist : 스프링 배치 사용

토끼C 2023. 6. 28. 12:05
반응형

java.io.FileNotFoundException: class path resource ‘A’ cannot be opened because it does not exist

스프링 배치 사용을 위해 maven dependency를 추가하고 기타 설정을 한 후 앱을 배포하자 다음과 같은 에러가 발생했다.

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.test.SpringAppliction]; nested exception is java.io.FileNotFoundException: 
class path resource [org/springframework/batch/core/listener/JobExecutionListenerSupport.class] cannot be opened because it does not exist
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.5.jar:2.4.5]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:782) ~[spring-boot-2.4.5.jar:2.4.5]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:774) [spring-boot-2.4.5.jar:2.4.5]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) [spring-boot-2.4.5.jar:2.4.5]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:339) [spring-boot-2.4.5.jar:2.4.5]
        at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:173) [spring-boot-2.4.5.jar:2.4.5]
        at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:153) [spring-boot-2.4.5.jar:2.4.5]
        at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:95) [spring-boot-2.4.5.jar:2.4.5]
        at com.tmax.proobject.runtime.ProObjectServletInitializer.onStartup(ProObjectServletInitializer.java:43) [proobject-runtime-21.0.0.1.33.jar:21.0.0.1.33]
        at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174) [spring-web-5.3.6.jar:5.3.6]
Caused by: java.io.FileNotFoundException: class path resource [org/springframework/batch/core/listener/JobExecutionListenerSupport.class] cannot be opened because it does not exist
        at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:187) ~[spring-core-5.3.6.jar:5.3.6]
        at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:55) ~[spring-core-5.3.6.jar:5.3.6]
        at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:49) ~[spring-core-5.3.6.jar:5.3.6]
        at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103) ~[spring-core-5.3.6.jar:5.3.6]
        at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:86) ~[spring-boot-2.4.5.jar:2.4.5]
        at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:73) ~[spring-boot-2.4.5.jar:2.4.5]
        at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81) ~[spring-core-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:696) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getSuperClass(ConfigurationClassParser.java:1010) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:341) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:304) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) ~[spring-context-5.3.6.jar:5.3.6]
        at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175) ~[spring-context-5.3.6.jar:5.3.6]

‘class path resource’ 해당 부분을 보고 resource의 경로를 잘못 설정해준 곳이 있나 생각했지만, 실제 원인은 달랐다.

 

batch 관련 dependency를 가져올때 다른 dependency를 복붙했는데, 이 과정에서 <scope>provided</scope>가 실수로 포함되었다.

 

scope이 provided로 지정된 api는 마지막 빌드시에 포함되지 않는다. 그렇기 때문에 스튜디오에서는 사용할 api가 존재하여 에러가 발생하지 않았지만, 배포할 때 사용할 provided 옵션으로 제외되어서 JobExecutionListenerSupport.class를 찾지 못하고 에러가 발생한 것으로 보인다.

 

dependency의 <scope>provided</scope> 부분만 삭제한 후 재배포 했더니 정상적으로 동작했다.

참고로 scope type의 default 동작은 <scope>compile</scope>이다.

반응형