Приложение Spring Boot с иерархией контекста пытается запустить встроенный tomcat при развертывании на существующем

Я пытаюсь создать приложение Spring Boot с иерархией контекста, которое следует развернуть на существующем Tomcat.

Это мой SpringBootServletInitializer:

@Slf4j
@SpringBootApplication
@RestController
public class ParentContext extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(ParentContext.class)
                .child(ChildContext1.class)
                .sibling(ChildContext2.class);
    }
}

Когда я развертываю это на существующем tomcat, запуск завершается ошибкой со следующим исключением, потому что Spring Boot пытается запустить встроенный tomcat:

 java.lang.ClassNotFoundException: org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:466)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:566)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:291)
    at org.apache.catalina.loader.WebappLoader.createClassLoader(WebappLoader.java:503)
    at org.apache.catalina.loader.WebappLoader.startInternal(WebappLoader.java:388)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4955)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1429)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:944)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:839)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1429)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:944)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:261)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:770)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.startup.Tomcat.start(Tomcat.java:370)
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:107)
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:86)
    at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:413)
    at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:174)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:179)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:152)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:797)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:421)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:340)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:157)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:137)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:171)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5098)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:703)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1737)
    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:564)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:809)
    at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:457)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:406)
    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:564)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:809)
    at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1466)
    at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:75)
    at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1307)
    at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1399)
    at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:827)
    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:564)
    at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:844)

Я использую Spring Boot 2.1.0.M4 и Tomcat 9.0.12 на Java 10.0.1

Вот MCVE: https://github.com/larsgrefer/spring-war-test/

Та же ошибка возникает с Spring Boot 2.1.0.BUILD-SNAPSHOT (20181015.191213-574), 2.0.5.RELEASE и 1.5.16.RELEASE.

Просто преобразуйте приложение SpringBoot в режим войны и настройте его для работы на Tomcat: docs.spring.io/spring-boot/docs/current/reference/html/…

Randy Casburn 13.10.2018 23:56

@RandyCasburn Я сделал именно это. Как видно из кода, у меня уже есть SpringBootServletInitializer.

larsgrefer 14.10.2018 00:11

Две мысли: 1) Возможно, аннотация @RestController, которая здесь не подходит, вызывает некоторую странность, ИЛИ 2) Вам понадобится основной метод, чтобы гарантировать, что инициализатор создан.

Randy Casburn 14.10.2018 00:25

1) удаление @RestController ничего не меняет (и почему он там не подходит?) 2) основной метод будет использоваться только тогда, когда файл войны запускается с java -jar, но я должен развернуть его на существующем tomcat, поэтому основной метод не будет вызываться.

larsgrefer 14.10.2018 00:30

Я согласен с основным методом, но не был уверен, как вы запускаете свое приложение. @RestController в любом случае ничего не делал, но это не подходило: потому что ваш класс приложения не ожидает использования @RequestMapping. docs.spring.io/spring-framework/docs/current/javadoc-api/org‌ /…

Randy Casburn 14.10.2018 00:34

В исходном классе есть метод @GetMapping, который я удалил для MCVE.

larsgrefer 14.10.2018 00:40

Да, я вернулся к коду. На самом деле не ожидал наличия контроллера в вашем классе Application, но whatevs. Вы правильно настроили его. Не думаю, что я могу помочь, так как я не хочу менять среду разработки, чтобы включить Gradle.

Randy Casburn 14.10.2018 00:45

Вам не нужно устанавливать Gradle. Скрипта gradlew в репо достаточно. Просто позвоните gradlew war, чтобы создать файл войны

larsgrefer 14.10.2018 00:48

Хорошо, правда, в STS есть всевозможные проблемы с зависимостями, с которыми я действительно хочу справиться.

Randy Casburn 14.10.2018 00:50

Ваши ChildContext1 и ChildContext2 не должны иметь аннотации @SpringBootApplication. Они должны быть аннотированы @Configuration.

M. Deinum 16.10.2018 07:54
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
10
463
0

Другие вопросы по теме