작성
·
3.2K
·
수정됨
0
안녕하세요 자동 구성 정보 분리쪽 강의를 따라 구현하던 도중 문제가 발생하여 질문을 남깁니다.
return new String[]{
"tobyspring.config.autoconfig.TomcatWebServerConfig",
"tobyspring.config.autoconfig.DispatcherServletConfig"
};
직접 경로를 작성해주는 경우에는 문제 없이 동작합니다.
Iterable<String> candidates = ImportCandidates.load(MyAutoConfiguration.class, classLoader);
return StreamSupport.stream(candidates.spliterator(), false).toArray(String[]::new);
클래스 로더를 이용해서 외부에서 파일 경로를 불러오는 방법을 사용하면 아래와 같은 문제가 발생합니다.
오후 11:26:47: Executing ':HellobootApplication.main()'...
> Task :compileJava
> Task :processResources UP-TO-DATE
> Task :classes
> Task :HellobootApplication.main() FAILED
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.8)
2023-02-27 23:26:49.370 INFO 3532 --- [ main] t.helloboot.HellobootApplication : Starting HellobootApplication using Java 17.0.6 on yj_notebook with PID 3532 (C:\git\TID\helloboot\build\classes\java\main started by deter in C:\git\TID\helloboot)
2023-02-27 23:26:49.374 INFO 3532 --- [ main] t.helloboot.HellobootApplication : No active profile set, falling back to 1 default profile: "default"
2023-02-27 23:26:49.641 WARN 3532 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.context.MissingWebServerFactoryBeanException: No qualifying bean of type 'org.springframework.boot.web.servlet.server.ServletWebServerFactory' available: Unable to start AnnotationConfigServletWebServerApplicationContext due to missing ServletWebServerFactory bean
2023-02-27 23:26:49.667 ERROR 3532 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.
Action:
Check your application's dependencies for a supported servlet web server.
Check the configured web application type.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
See https://docs.gradle.org/7.6/userguide/command_line_interface.html#sec:command_line_warnings
3 actionable tasks: 2 executed, 1 up-to-date
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':HellobootApplication.main()'.
> Process 'command 'C:/Users/deter/.jdks/azul-17.0.6/bin/java.exe'' finished with non-zero exit value 1
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 2s
오후 11:26:49: Execution finished ':HellobootApplication.main()'.
제가 생각하기로는 클래스 로더를 통해서 구성 정보를 불러와야 하는데 못 불러오고 있는 것 같습니다.
package tobyspring.config.autoconfig;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import tobyspring.config.MyAutoConfiguration;
@MyAutoConfiguration
public class TomcatWebServerConfig {
@Bean
public ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
이 문제를 해결하기 위해서
java 버전 11, 17
gradle 버전 7.6, 8.0
Build and run 을 Geadle, IntelliJ
파일 경로 수정 등
로 변경하는 방법들을 시도해봤지만 해결하지 못했습니다.
현재 제 개발 환경은 아래와 같습니다.
IntelliJ버전은 2022.2.3 Community버전
spring boot 2.7.8
gradle 7.6
어디서 문제가 발생하는지 감을 잡을 수 없어서 문의드립니다.
답변 1
0
IntelliJ Community 버전을 사용하는 건 예제 동작하는 것에 영향을 주지 않습니다.
외부 파일에 구성정보를 가져오는 단계에서 주의할 점은 파일의 위치와 파일명이 바르게 설정되어있는지 확인하셔야 합니다. 애노테이션 이름과 일치하는 파일이 존재하지 않아도 에러가 나지 않습니다. 그냥 무시되죠. 이 경우에 톰캣 관련 빈이 생성되지 않으니 서블릿 컨테이너를 띄우지 못할 것이고요.
Github에 올려둔 예제를 받아서 비교하면서 파일명과 위치, 애노테이션 이름을 다시 확인해보세요.
아무리해도 안 되면 github에 작업 중인 예제를 공유하시고 알려주시면 제가 확인해보겠습니다.
JetBrains 제품군이 다그런건지 잘 모르겠지만, 패키지 표현방식에 있어 고정된 방식이 있는듯 합니다. 많이쓰는 VSCode 를 예로들면, 패키지 구분에 dot '.' 대신 slash '/' 구분을 기본으로 합니다. JetBrains 의 IntelliJ 는 지금에서야 다양한 멀티 언어의 IDE 이지만, 추측하기로는 태생이 Java 기반 Kotlin 에 특화된 배경이 있어 계층구조폴더의 압축된 표현을 패키지처럼 dot 표기방식을 기본으로 사용하는 듯 합니다. 저도 이 때문에 불만족스런 부분이 Java 패키지를 제외한, 계층적 폴더는 '/' 구분을 했으면 좋겠다는 아쉬움이 있습니다.
자신이 생성하는 것이 폴더 인지, 패키지인지 인지한 이후 생성 오더를 내림.
즉, 일반폴더에서 계층구조 폴더생성을 위해 패키지 작성하듯 dot '.' 을 남발하면,
aaa.bbb.cc 와 같은 폴더 1개
가 생성됨
아래 토글옵션 Uncheck : 패키지 표현 꺼짐(단점: 모든 패키지 표현이 계층표현으로 바뀜)
ps. 혹시, 패키지가 아닌 폴더 계층구조 표현을 dot 이 아니라, slash 로 바꾸는 옵션을 알고 계시다면 아래에 남겨주세요.
문제를 찾았습니다.
META-INF.spring 폴더를 생성할 때, 똑같이 META-INF.spring으로 입력했는데
실제 탐색기에서 찾아보니까 META-INF/spring이 아니라 META-INF.spring이라는 이름으로 만들어졌습니다.
다시 한번 test.test라는 이름으로 생성해 봤는데 resources하위에서는. 을 포함한 test.test폴더명으로 생성되고, java하위에서는. 을 구분해서 test/test 구조로 생성됩니다.
답변해 주셔서 감사합니다.