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
exception sending context initialized event to listener instance of class
提问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:
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 UtilService
is 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 ApplicationWebListener
as 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 ApplicationListener
interface which can be implemented by a class and then registered as a bean. The ApplicationListener
will 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
:
And an example of registering that listener in your configuration file, which must be the dispatcher's configuration file:
以及在您的配置文件中注册该侦听器的示例,该文件必须是调度程序的配置文件:
And the documentation
和文档