Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DefaultManagedTaskScheduler created manually now throws a NPE if the scheduled executor is not configured #31751

Closed
fullopt opened this issue Nov 25, 2023 · 11 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Milestone

Comments

@fullopt
Copy link

fullopt commented Nov 25, 2023

After upgrading from 3.1.5 to 3.2.0 my application fails:

org.springframework.context.ApplicationContextException: Failed to start bean 'simpleBrokerMessageHandler'

The reason:

Caused by: java.lang.NullPointerException: Cannot invoke "java.util.concurrent.ScheduledExecutorService.scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit)" because "this.scheduledExecutor" is null
        at org.springframework.scheduling.concurrent.ConcurrentTaskScheduler.scheduleWithFixedDelay(ConcurrentTaskScheduler.java:262) ~[spring-context-6.1.1.jar:6.1.1]
        at org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.startInternal(SimpleBrokerMessageHandler.java:271) ~[spring-messaging-6.1.1.jar:6.1.1]
        at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.start(AbstractBrokerMessageHandler.java:210) ~[spring-messaging-6.1.1.jar:6.1.1]
        at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:284) ~[spring-context-6.1.1.jar:6.1.1]

Can you please help me to fix it?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 25, 2023
@philwebb
Copy link
Member

Can you please help me to fix it?

Not without more information I'm afraid. Could you please provide a sample application that reproduces the problem.

@philwebb philwebb added the status: waiting-for-feedback We need additional information before we can continue label Nov 25, 2023
@szolen
Copy link

szolen commented Dec 1, 2023

I had the same problem with version 3.2.0. I suspect that the problem is caused by the websocket (MessageBroker). If I comment the following lines in the WebSocketMessageBrokerConfigurer implementation, the problem is solved.

@Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/public", "/private").setHeartbeatValue(new long[] { HEART_BEAT, HEART_BEAT }).setTaskScheduler(new DefaultManagedTaskScheduler());
        config.setUserDestinationPrefix("/user");
    }

In my case, this is shown in the log:

[2023.12.01 10:57:12] [ERROR] [SpringApplication.java:839] Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'simpleBrokerMessageHandler'
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:287)
	at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:467)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:256)
	at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:201)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:965)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:619)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1342)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1331)
	at hu.prolan.prorisdiag.psb.webservice.PSBDiagWebService.main(PSBDiagWebService.java:20)
Caused by: java.lang.NullPointerException: Cannot invoke "java.util.concurrent.ScheduledExecutorService.scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit)" because "this.scheduledExecutor" is null
	at org.springframework.scheduling.concurrent.ConcurrentTaskScheduler.scheduleWithFixedDelay(ConcurrentTaskScheduler.java:262)
	at org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.startInternal(SimpleBrokerMessageHandler.java:271)
	at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.start(AbstractBrokerMessageHandler.java:210)
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:284)
	... 13 common frames omitted

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Dec 1, 2023
@szolen
Copy link

szolen commented Dec 1, 2023

The problem in my case is solved by not setting the DefaultManagedTaskScheduler in the MessageBrokerRegistry, but by registering a custom TaskScheduler:

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
    config.enableSimpleBroker("/public", "/private")
    .setHeartbeatValue(new long[] { HEART_BEAT, HEART_BEAT })
    .setTaskScheduler(heartBeatScheduler());
    
    config.setUserDestinationPrefix("/user");
}

@Bean
public TaskScheduler heartBeatScheduler() {
    return new ThreadPoolTaskScheduler();
}

@fullopt
Copy link
Author

fullopt commented Dec 3, 2023

This helped, thanks!

@philwebb
Copy link
Member

philwebb commented Dec 4, 2023

I think this might be a result of #27914.

The following code is enough to trigger the exception.

DefaultManagedTaskScheduler scheduler = new DefaultManagedTaskScheduler();
scheduler.scheduleWithFixedDelay(() -> {}, Duration.ofSeconds(1));

I'm not sure if this is a bug or not. The same code with the previous version of Spring would create a ScheduledExecutorService but it wouldn't be from the JNDI context because afterPropertiesSet wasn't ever called.

@philwebb
Copy link
Member

philwebb commented Dec 4, 2023

@bclozel Could you please transfer this to the Framework issue tracker so that someone from that team can make an assessment?

@bclozel bclozel transferred this issue from spring-projects/spring-boot Dec 4, 2023
@snicoll

This comment was marked as outdated.

@snicoll snicoll self-assigned this Dec 7, 2023
@snicoll
Copy link
Member

snicoll commented Dec 7, 2023

@fullopt can you confirm you're also using DefaultManagedTaskScheduler ? As far as I can see, that only happens if you opt-in for that scheduler and you don't create it as a managed object (bean).

@fullopt
Copy link
Author

fullopt commented Dec 7, 2023

@fullopt can you confirm you're also using DefaultManagedTaskScheduler ? As far as I can see, that only happens if you opt-in for that scheduler and you don't create it as a managed object (bean).

Exactly, I used DefaultManagedTaskScheduler() what caused the issue. So far I changed for bean option proposed by @szolen and it works as expected.

@snicoll snicoll changed the title Since 3.2.0: Application falis: java.lang.NullPointerException: Cannot invoke "java.util.concurrent.ScheduledExecutorService.scheduleWithFixedDelay DefaultManagedTaskScheduler created manually now throws a NPE if the scheduled executor is not configured Dec 8, 2023
@snicoll snicoll added type: regression A bug that is also a regression in: core Issues in core modules (aop, beans, core, context, expression) and removed status: waiting-for-triage An issue we've not yet triaged or decided on status: feedback-provided Feedback has been provided labels Dec 8, 2023
@snicoll snicoll added this to the 6.1.2 milestone Dec 8, 2023
@snicoll snicoll closed this as completed in b78aed9 Dec 8, 2023
@snicoll
Copy link
Member

snicoll commented Dec 8, 2023

@szolen and @fullopt for the record DefaultManagedTaskScheduler should be used if you want to lookup the executor via JNDI. We're wondering if you've used this class thinking that it was the "default scheduler" given its name, can you let us know? If you used it thinking it was the default scheduler, ThreadPoolTaskScheduler is probably what you should be using.

As for creating the scheduler as a bean, this should have been done in the first place as the context needs that in order to honor the lifecycle, both during the startup phase, and the shutdown phase. Creating such a class manually is not the expected behavior.

As such the use cases above will still throw an exception, a different one though now.

@szolen
Copy link

szolen commented Dec 8, 2023

@szolen and @fullopt for the record DefaultManagedTaskScheduler should be used if you want to lookup the executor via JNDI. We're wondering if you've used this class thinking that it was the "default scheduler" given its name, can you let us know?

As for creating the scheduler as a bean, this should have been done in the first place as the context needs that in order to honor the lifecycle, both during the startup phase, and the shutdown phase. Creating such a class manually is not the expected behavior.

As such the use cases above will still throw an exception, a different one though now.

Yes, I thought from the name that this was the default scheduler.

However, on the configuration class I used an @Order annotation: @Order(Ordered.HIGHEST_PRECEDENCE) but it seems that was insufficient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

5 participants