TaskScheduler 中的 NullPointerException
NullPointerException at TaskScheduler
我有一个像这样的 TaskScheduler class :
public class NotificationManger {
@Autowired
private TaskScheduler scheduler;
private ScheduledFuture<?> sc;
public NotificationManger(WebSocketMessage webSocketMessage, String userName, Date date, Date time) {
scheduleTask(webSocketMessage, userName, combine(date,time));
}
public void scheduleTask(WebSocketMessage webSocketMessage, String userName, Date startTime)
{
Runnable r = new NotificationSenderTask(webSocketMessage, userName);
sc = scheduler.schedule(r, new Date());//here I get a NullPointerException
}
}
和一个 Runnable class 像这样:
class NotificationSenderTask implements Runnable {
@Autowired
SimpMessagingTemplate webSocketMessageTemplate;
private String userName;
private WebSocketMessage webSocketMessage;
public NotificationSenderTask(WebSocketMessage webSocketMessage, String userName) {
this.webSocketMessage = webSocketMessage;
this.userName = userName;
}
public void run() {
webSocketMessageTemplate.convertAndSendToUser(userName, "/notification", webSocketMessage);;
}
}
我调用 TaskScheduler:NotificationManger mn = new NotificationManger(new WebSocketMessage(n), user.getEmail(),date1,date2 );
但我在 sc = scheduler.schedule(r, new Date());
得到 java.lang.NullPointerException: null
可能我用的runnableclass错了。
任何帮助将不胜感激,谢谢。
编辑:
@EnableWebMvc
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
@Configuration
@ComponentScan(basePackages = "gestionprojet.java")
@PropertySource("classpath:application.properties")
@Import({PersistenceJPAConfig.class, WebSecurityConfig.class})
public class WebConfig extends WebMvcConfigurerAdapter {...}
你还没有初始化全局实例变量
私有 TaskScheduler 调度程序;
因为它是一个全局实例变量,所以它不会给出任何编译时错误,并且会隐式地使用空值进行初始化。
这就是为什么当您尝试访问 scheduler.schedule 时会抛出空指针错误。
希望这能解决您的问题。
AutowireHelper 助你一臂之力
OP 实际上没有重构所有代码,而是找到了一个库来强制自动装配到 non-spring-managed bean 中:
图书馆是:https://github.com/alv-ch/alv-ch-java
可以这样使用:
public class NotificationManager {
@Autowired
private TaskScheduler scheduler;
public NotificationManager(WebSocketMessage webSocketMessage, String userName, Date date, Date time) {
AutowireHelper.autowire(this, scheduler);
scheduleTask(webSocketMessage, userName, combine(date,time));
}
...
}
这会将 TaskScheduler
自动连接到 NotificationManager
,即使它不是 spring 托管的。
可以查看AutowireHelper源码here.
另一种可能的解决方案
1。使用@Service 注释 NotificationManager 并删除构造函数:
@Service
public class NotificationManager {
@Autowired
private TaskScheduler scheduler;
private ScheduledFuture<?> sc;
public void scheduleTask(WebSocketMessage webSocketMessage, String userName, Date date, Date time) {
scheduleTask(webSocketMessage, userName, combine(date,time));
}
public void scheduleTask(WebSocketMessage webSocketMessage, String userName, Date startTime)
{
Runnable r = new NotificationSenderTask(webSocketMessage, userName);
sc = scheduler.schedule(r, new Date());
}
}
2。自动装配 NotificationManager
然后,在您以前 NotificationManager mn = new NotificationManager(...)
执行的位置改为执行以下操作:
@Autowired
private NotificationManager notificationManager;
...
notificationManager.scheduleTask(new WebSocketMessage(n), user.getEmail(),date1,date2);
为此,无论它在哪里,它都需要在 spring-managed bean 中。
我有一个像这样的 TaskScheduler class :
public class NotificationManger {
@Autowired
private TaskScheduler scheduler;
private ScheduledFuture<?> sc;
public NotificationManger(WebSocketMessage webSocketMessage, String userName, Date date, Date time) {
scheduleTask(webSocketMessage, userName, combine(date,time));
}
public void scheduleTask(WebSocketMessage webSocketMessage, String userName, Date startTime)
{
Runnable r = new NotificationSenderTask(webSocketMessage, userName);
sc = scheduler.schedule(r, new Date());//here I get a NullPointerException
}
}
和一个 Runnable class 像这样:
class NotificationSenderTask implements Runnable {
@Autowired
SimpMessagingTemplate webSocketMessageTemplate;
private String userName;
private WebSocketMessage webSocketMessage;
public NotificationSenderTask(WebSocketMessage webSocketMessage, String userName) {
this.webSocketMessage = webSocketMessage;
this.userName = userName;
}
public void run() {
webSocketMessageTemplate.convertAndSendToUser(userName, "/notification", webSocketMessage);;
}
}
我调用 TaskScheduler:NotificationManger mn = new NotificationManger(new WebSocketMessage(n), user.getEmail(),date1,date2 );
但我在 sc = scheduler.schedule(r, new Date());
java.lang.NullPointerException: null
可能我用的runnableclass错了。
任何帮助将不胜感激,谢谢。
编辑:
@EnableWebMvc
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
@Configuration
@ComponentScan(basePackages = "gestionprojet.java")
@PropertySource("classpath:application.properties")
@Import({PersistenceJPAConfig.class, WebSecurityConfig.class})
public class WebConfig extends WebMvcConfigurerAdapter {...}
你还没有初始化全局实例变量
私有 TaskScheduler 调度程序;
因为它是一个全局实例变量,所以它不会给出任何编译时错误,并且会隐式地使用空值进行初始化。
这就是为什么当您尝试访问 scheduler.schedule 时会抛出空指针错误。
希望这能解决您的问题。
AutowireHelper 助你一臂之力
OP 实际上没有重构所有代码,而是找到了一个库来强制自动装配到 non-spring-managed bean 中:
图书馆是:https://github.com/alv-ch/alv-ch-java
可以这样使用:
public class NotificationManager {
@Autowired
private TaskScheduler scheduler;
public NotificationManager(WebSocketMessage webSocketMessage, String userName, Date date, Date time) {
AutowireHelper.autowire(this, scheduler);
scheduleTask(webSocketMessage, userName, combine(date,time));
}
...
}
这会将 TaskScheduler
自动连接到 NotificationManager
,即使它不是 spring 托管的。
可以查看AutowireHelper源码here.
另一种可能的解决方案
1。使用@Service 注释 NotificationManager 并删除构造函数:
@Service
public class NotificationManager {
@Autowired
private TaskScheduler scheduler;
private ScheduledFuture<?> sc;
public void scheduleTask(WebSocketMessage webSocketMessage, String userName, Date date, Date time) {
scheduleTask(webSocketMessage, userName, combine(date,time));
}
public void scheduleTask(WebSocketMessage webSocketMessage, String userName, Date startTime)
{
Runnable r = new NotificationSenderTask(webSocketMessage, userName);
sc = scheduler.schedule(r, new Date());
}
}
2。自动装配 NotificationManager
然后,在您以前 NotificationManager mn = new NotificationManager(...)
执行的位置改为执行以下操作:
@Autowired
private NotificationManager notificationManager;
...
notificationManager.scheduleTask(new WebSocketMessage(n), user.getEmail(),date1,date2);
为此,无论它在哪里,它都需要在 spring-managed bean 中。