Skip to content

use spring-boot-starter-quartz and spring-boot-starter-websocket simultaneously #24448

@felixu1992

Description

@felixu1992

I want to use spring-boot-starter-quartz and spring-boot-starter-websocket simultaneously,but it fails to satisfy my needs, and when I try to use them,some errors as follow appeared.

2020-12-08 18:50:09.535 [main] ERROR org.springframework.boot.SpringApplication [line:837] - Application run failed
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'defaultSockJsTaskScheduler' is expected to be of type 'org.springframework.scheduling.TaskScheduler' but was actually of type 'org.springframework.beans.factory.support.NullBean'
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:399)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:227)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1175)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1142)
	at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.resolveSchedulerBean(ScheduledAnnotationBeanPostProcessor.java:327)
	at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:256)
	at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:233)
	at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:105)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:404)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:361)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:898)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:554)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)

I have figured out what caused these errors. It is because that there is a logical conflict on the instantiation of Taskscheuler after the procedure of use spring-boot-starter-quartz and spring-boot-starter-websocket simultaneously. spring-wesocket created a NullBean as instantiation of Taskscheduler. when the quartz is applied,the errors would emerge that is:
In org.springframework.web.socket.config.annotation.WebSocketConfigurationSupport#defaultSockJsTaskScheduler

org.springframework.web.socket.config.annotation.WebSocketConfigurationSupport#defaultSockJsTaskScheduler

@Bean
@Nullable
public TaskScheduler defaultSockJsTaskScheduler() {
	if (initHandlerRegistry().requiresTaskScheduler()) {
		ThreadPoolTaskScheduler threadPoolScheduler = new ThreadPoolTaskScheduler();
		threadPoolScheduler.setThreadNamePrefix("SockJS-");
		threadPoolScheduler.setPoolSize(Runtime.getRuntime().availableProcessors());
		threadPoolScheduler.setRemoveOnCancelPolicy(true);
		this.scheduler = threadPoolScheduler;
	}
	return this.scheduler;
}

If this condition is not satisfied, it's going to create an instance(NullBean(org.springframework.beans.factory.support.NullBean)) of TaskScheduler here.
So we're going to rely on spring-boot-starter-quartz:

org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration#taskScheduler

@Bean
@ConditionalOnBean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
@ConditionalOnMissingBean({ SchedulingConfigurer.class, TaskScheduler.class, ScheduledExecutorService.class })
public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) {
	return builder.build();
}

But due to the existence of the Nullbean the above method is impracticable, neither for the creation of a new workable Taskscheduler, but this problem can be tackled in this way:

@Bean
public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) {
    return builder.build();
}

Or implement WebSocketConfigurer to solve it.
Although we can use the above ways to settle the errors, but they are only temporary .In my opinion,the root cause for the problem is the bug of spring-websocket and so that cause the wrong existence of Nullbean
I think we can use these ways to deal with:

  • Change logical order of the two procedures, that is to put the spring-boot-starter-quartz before the instantiation
  • In spring-websocket, conditionally include TaskScheduler
  • Always create a TaskScheduler Bean without if{}
  • In spring-websocket, org.springframework.web.socket.config.annotation.WebSocketConfigurationSupport#defaultSockJsTaskScheduler no longer as a Spring Bean

The above mentioned are my immature thoughts ,may be you can solve the errors in a better way,thanks for your attention

Metadata

Metadata

Assignees

No one assigned

    Labels

    for: external-projectFor an external project and not something we can fix

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions