Java 异常将上下文初始化事件发送到类的侦听器实例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19513947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 17:55:02  来源:igfitidea点击:

exception sending context initialized event to listener instance of class

javaspringspring-mvcconfiguration

提问by gstackoverflow

I have this class:

我有这门课:

public class DatabaseHelper {
    @Autowired
    static UtilService utilService;

    public static void fillEmptyTables(){
        if(!isSkillsInDatabase()){
            utilService.addGeneratedSkill();
        }
        if(!isEventTypesInDatabase()){
            utilService.addGeneratedEventType();
        }
        if(!isEventStatusesInDatabase()){
            utilService.addGeneratedEventStatus();
        }

    }
    public static boolean isSkillsInDatabase(){
        return utilService.getAllSkills().size() != 0; 
    }
    public static boolean isEventStatusesInDatabase(){
        return utilService.getAllEventStatuses().size() != 0; 
    }
    public static boolean isEventTypesInDatabase(){
        return utilService.getAllEventTypes().size() != 0; 
    }
}

and this listener:

和这个听众:

@WebListener
public class ApplicationWebListener implements ServletContextListener {
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("ServletContextListener destroyed");
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("ServletContextListener started");
        DatabaseHelper.fillEmptyTables();
    }
}

When I run my application I see following:

当我运行我的应用程序时,我看到以下内容:

INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 10029 ms
ServletContextListener started
22.10.2013 13:21:16 org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class com.epam.hhsystem.web.controllers.ApplicationWebListener
java.lang.NullPointerException
    at com.epam.hhsystem.util.DatabaseHelper.isSkillsInDatabase(DatabaseHelper.java:25)
    at com.epam.hhsystem.util.DatabaseHelper.fillEmptyTables(DatabaseHelper.java:13)
    at com.epam.hhsystem.web.controllers.ApplicationWebListener.contextInitialized(ApplicationWebListener.java:19)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4887)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5381)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
22.10.2013 13:21:16 org.apache.catalina.core.StandardContext startInternal
SEVERE: Error listenerStart

What the cause of this problem?

这个问题的原因是什么?

How to fix it?

如何解决?

UPDATE

更新

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="com.epam.hhsystem.web.controllers"/>


</beans:beans>

and this:

和这个:

<import resource="classpath:spring/BeanConfig.xml" />
    <!-- Файл с настройками Security -->
    <import resource="security_config.xml" />

and this:

和这个:

<context:annotation-config />

    <!--ищем тут разные аннотации (например @service)  -->
    <context:component-scan base-package="com.epam.hhsystem.jpa" />
    <context:component-scan base-package="com.epam.hhsystem.util" />
    <context:component-scan base-package="com.epam.hhsystem.services" />

    <context:component-scan base-package="com.epam.hhsystem.web.controllers" />



    <!-- Файл с настройками ресурсов для работы с данными (Data Access Resources) -->
    <import resource="data.xml" />

that so.

这么。

UPDATE

更新

@WebListener
public class ApplicationWebListener implements ServletContextListener {
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("ServletContextListener destroyed");
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("ServletContextListener started");
    }
}

this code works good. When I run my application I see

这段代码效果很好。当我运行我的应用程序时,我看到

servletContextListener started

servletContextListener 启动

message

信息

UtilService location: enter image description here

UtilService 位置: 在此处输入图片说明

string from configuration:

配置中的字符串:

<context:component-scan base-package="com.epam.hhsystem.services" />

after adding this code to @Configuration class

将此代码添加到@Configuration 类后

    @Bean
    ApplicationWebListener getApplicationWebListener(){
        return new ApplicationWebListener();
    }

I see old error.

我看到旧错误。

UPDATE 2

更新 2

I refactor my code for your advice. I am confused:

为了您的建议,我重构了我的代码。我很迷惑:

variant1:

变体1:

   public class MyApplicationListener  implements ApplicationListener<ContextRefreshedEvent> {
            @Autowired
            UtilService utilService;

            public  void fillEmptyTables(){
                if(!isSkillsInDatabase()){
                    utilService.addGeneratedSkill();
                }
                if(!isEventTypesInDatabase()){
                    utilService.addGeneratedEventType();
                }
                if(!isEventStatusesInDatabase()){
                    utilService.addGeneratedEventStatus();
                }

            }
            public  boolean isSkillsInDatabase(){
                return utilService.getAllSkills().size() != 0; 
            }
            public  boolean isEventStatusesInDatabase(){
                return utilService.getAllEventStatuses().size() != 0; 
            }
            public  boolean isEventTypesInDatabase(){
                return utilService.getAllEventTypes().size() != 0; 
            }    

            @Override
            public void onApplicationEvent(ContextRefreshedEvent event) {
                fillEmptyTables();
        }


    }

This variant works good but it is architecture horror

这个变体效果很好,但它是架构恐怖

variant 2:

变体2:

public class MyApplicationListener  implements ApplicationListener<ContextRefreshedEvent> {
                @Override
                public void onApplicationEvent(ContextRefreshedEvent event) {
                           DatabaseHelper.fillEmptyTables();

            }
}

I see old stacktrace.

我看到旧的堆栈跟踪。

why?

为什么?

回答by Kevin Bowersox

Make sure you have component scanning enabled in the Spring configuration file. The compenent scan tag should point to the package containing UtilService. I would fathom that UtilServiceis currently not initialized as a Spring bean making it not a candidate for autowiring.

确保在 Spring 配置文件中启用了组件扫描。组件扫描标记应指向包含UtilService. 我想知道UtilService目前没有初始化为 Spring bean,因此它不是自动装配的候选者。

<context:component-scan base-package="package.containing.UtilService" />

Try registering the ApplicationWebListeneras a bean in your Spring Configuration, I'm not sure if this will work, but in order to autowire a field in a class, that class must be a bean. Spring cannot autowire beans into classes that were not instantiated as part of the IOC container.

尝试ApplicationWebListener在 Spring 配置中将注册为 bean,我不确定这是否可行,但是为了自动装配类中的字段,该类必须是 bean。Spring 无法将 bean 自动装配到未实例化为 IOC 容器的一部分的类中。

There is another approach. Spring provides an ApplicationListenerinterface which can be implemented by a class and then registered as a bean. The ApplicationListenerwill be called at various points during the applications lifecycle such as startup, restart and shutdown.

还有另一种方法。Spring 提供了一个ApplicationListener可以通过类实现然后注册为 bean 的接口。该ApplicationListener会在不同的点在生命周期中的应用,如启动,重启和关机调用。

Here is an example of the ApplicationListener:

下面是一个例子ApplicationListener

Listener Example

监听器示例

And an example of registering that listener in your configuration file, which must be the dispatcher's configuration file:

以及在您的配置文件中注册该侦听器的示例,该文件必须是调度程序的配置文件:

Configuration

配置

And the documentation

文档