Ошибка определения множественного контекстного загрузчика в Tomcat - PullRequest
0 голосов
/ 10 октября 2019

У меня есть класс ApplicationInitializer, который реализует WebApplicationInitializer, и в него я добавляю свой собственный ContextLoaderListener. Когда я запускаю свое приложение в STS, оно работает отлично, но когда я пытаюсь развернуть файл war в моем tomcat, приложение не развертывается и выдает следующую ошибку многоконтекстного прослушивателя:

10-Oct-2019 10:51:58.252 INFO [Catalina-utility-2] org.apache.catalina.core.ApplicationContext.log 3 Spring WebApplicationInitializers detected on classpath
10-Oct-2019 10:52:05.987 INFO [Catalina-utility-2] org.apache.catalina.core.ApplicationContext.log Initializing Spring embedded WebApplicationContext
10-Oct-2019 10:52:11.237 SEVERE [Catalina-utility-2] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class [org.springframework.web.context.ContextLoaderListener]
    java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:262)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4683)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5146)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:717)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705)
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:978)
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1849)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        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:118)
        at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:773)
        at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:427)
        at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1620)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:305)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
        at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1151)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1353)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1357)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1335)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.base/java.lang.Thread.run(Thread.java:835)
10-Oct-2019 10:52:11.240 INFO [Catalina-utility-2] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext

Iпрочитайте следующую документацию: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file

Из того, что я понял, я могу полностью удалить свой класс AppInitializer и добавить его содержимое в класс приложения весенней загрузки. Затем я посмотрел, как было запущено onStartup SpringBootServletInitializer, и изменил мой код на:

@SpringBootApplication
@EntityScan("com.example")
@EnableJpaRepositories("com.example")
@ComponentScan("com.example")
@EnableConfigurationProperties(CustomProperties.class)
public class Application extends SpringBootServletInitializer{

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    @Override
    public void onStartup(final ServletContext sc) throws ServletException{

        AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();

        root.scan("com.example");
        sc.addListener(new ContextLoaderListener(root){
            @Override
            public void contextInitialized(ServletContextEvent event) {
                // no-op because the application context is already initialized
            }
        });

        ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext()));
        appServlet.setLoadOnStartup(1);
        appServlet.addMapping("/");

        sc.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"))
        .addMappingForUrlPatterns(null, false, "/*");
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

На этот раз файл войны развертывается нормально, но когда я пытаюсь попасть на домашнюю страницу, я получаю следующую ошибку, хотя и сделалдобавьте springSecurityFilterChain:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' available
    org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:771)
    org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1221)
    org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:294)
    org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204)
    org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1111)
    org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:337)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)

Это то, что у меня было изначально (два отдельных класса):

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(final ServletContext sc) throws ServletException{

        AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();

        root.scan("com.example");
        sc.addListener(new ContextLoaderListener(root));

        ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext()));
        appServlet.setLoadOnStartup(1);
        appServlet.addMapping("/");

        sc.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"))
        .addMappingForUrlPatterns(null, false, "/*");
    }
}
@SpringBootApplication
@EntityScan("com.example")
@EnableJpaRepositories("com.example")
@ComponentScan("com.example")
@EnableConfigurationProperties(CustomProperties.class)
public class Application extends SpringBootServletInitializer{
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

Пожалуйста, помогите мне понять, что я делаю неправильно.

...