[英]Multi-context spring-boot application: how to define standard spring-boot properties for each child context
[英]Tomcat multi-context deployment stops whole process if spring-boot context fails to deploy
我有一個非常具體的 Tomcat 配置,我不想更改它,我正在為這個特定配置尋找解決方案。
我已經在 Tomcat 中的conf/server.xml文件中聲明了多個上下文 ( <Context>
) 進行部署,我知道不建議這樣做。 我的問題是,如果其中一個部署失敗,整個 Tomcat 進程將停止,從而終止已成功啟動的應用程序的 rest。 這種行為是預期的嗎? 是否有屬性或方法可以防止這種情況並模擬不同上下文聲明的行為,類似於使用context.xml
文件?
我得到的錯誤如下:
ConfigServletWebServerApplicationContext:上下文初始化期間遇到異常
使用此堆棧跟蹤(對於 Tomcat 版本 8.5.24):
SEVERE [Catalina-startStop-1] org.apache.catalina.core.ContainerBase.startInternal A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/auth-service]]
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:939)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/auth-service]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
... 6 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'app.client-html.context' in value "${app.client-html.context}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1415)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:608)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:173)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:153)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:95)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 6 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'app.client-html.context' in value "${app.client-html.context}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:931)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1308)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1287)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
... 27 more
示例配置:
<Host name="localhost" unpackWARs="true" autoDeploy="true">
<Context docBase="../../app-that-works" path="/itworks"/>
<Context docBase="../../app-that-fails" path="/itfails"/>
</Host>
重要提示:失敗的應用程序是 spring-boot 應用程序,它被打包為 a.war 文件並在普通 tomcat 中運行,而不是嵌入式 tomcat 方式。 這很重要,因為這些應用程序似乎具有這種行為......
免責聲明:我指的是普通 Tomcat,而不是spring 引導或嵌入式 tomcat 等。我不是在尋找這樣的解決方案,只是解決這個特定問題。
基本上:
server.xml
中配置的任何組件的start
階段(參見LifeCycle )的異常會導致服務器退出。 但是,某些異常(例如失敗的ServletContextListener
)不會傳播。 如果您不希望整個服務器停止,當上下文無法啟動時,請使用自動部署:為server.xml
中定義的每個上下文創建文件$CATALINA_BASE/conf/<engine_name>/<host_name>/<context_path>.xml
內容:
<Context docBase="/path/to/application" />
在您的情況下,您需要創建$CATALINA_BASE/conf/Catalina/localhost/itworks.xml
和$CATALINA_BASE/conf/Catalina/localhost/itfails.xml
。 請參閱 Tomcat 對 XML 描述符的命名約定的命名。
編輯:您的堆棧跟蹤表明我們可能正在處理 Tomcat 或 Spring 錯誤:
一方面, StandardContext
期望ServletContainerInitializer
僅拋出ServletException
(參見源代碼),讓所有未經檢查的異常通過。 請注意,同時捕獲並記錄來自ServletContextListener
的所有異常(參見源代碼)。
另一方面,Spring 的SpringServletContainerInitializer
可能應該將所有未經檢查的異常包裝到ServletException
中。
在您的情況下發生的情況是未經檢查的異常一直到StandardContext
並被重新拋出為LifecycleException
停止服務器。 無論如何,設置:
<Context throwOnFailure="false" ... />
應該阻止 Tomcat 傳播異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.