Spring WebSocket Simple Example - java.lang.IllegalStateException: Unexpected use of scheduler

五迷三道 提交于 2020-07-06 19:25:38

问题


I'm trying to implement a WebSocket server in Spring without STOMP, following this article: http://www.devglan.com/spring-boot/spring-websocket-integration-example-without-stomp

WebSocketConfig.java

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Autowired private WebSocketHandler webSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketHandler, "/app");
    }

}

WebSocketHandler

@Component
public class WebSocketHandler extends TextWebSocketHandler {

    private List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        sessions.add(session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        // ...
    }

}

However, I get this exception at startup:

java.lang.IllegalStateException: Unexpected use of scheduler.
at org.springframework.web.socket.config.annotation.WebSocketConfigurationSupport$NoOpScheduler.schedule(WebSocketConfigurationSupport.java:108) ~[spring-websocket-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleCronTask(ScheduledTaskRegistrar.java:414) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleTasks(ScheduledTaskRegistrar.java:352) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.scheduling.config.ScheduledTaskRegistrar.afterPropertiesSet(ScheduledTaskRegistrar.java:332) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:280) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:211) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:102) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:399) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:353) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:887) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:161) ~[spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:388) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1234) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at my.package.App.main(App.java:31) [main/:na]

How to make this simple WebSocket app work?


回答1:


https://github.com/spring-projects/spring-boot/issues/12814

"@EnableWebSocket with no further configuration might create a no op scheduler which will conflict with any other use of a task scheduler."

This should be added to the config:

@Bean
public TaskScheduler taskScheduler() {
    return new ConcurrentTaskScheduler(Executors.newSingleThreadScheduledExecutor());
}



回答2:


According your stack trace (ScheduledAnnotationBeanPostProcessor) you have somewhere in the application @EnableScheduling and that one tries to rely on the:

@Bean
public TaskScheduler defaultSockJsTaskScheduler() {
    return initTaskScheduler();
}

private TaskScheduler initTaskScheduler() {
    if (this.scheduler == null) {
        ServletWebSocketHandlerRegistry registry = initHandlerRegistry();
        if (registry.requiresTaskScheduler()) {
            ThreadPoolTaskScheduler threadPoolScheduler = new ThreadPoolTaskScheduler();
            threadPoolScheduler.setThreadNamePrefix("SockJS-");
            threadPoolScheduler.setPoolSize(Runtime.getRuntime().availableProcessors());
            threadPoolScheduler.setRemoveOnCancelPolicy(true);
            this.scheduler = threadPoolScheduler;
        }
        else {
            this.scheduler = new NoOpScheduler();
        }
    }
    return this.scheduler;
}

Where that NoOpScheduler is accepted but causes problems at the runtime for your scheduled tasks.

I suggest to provide a SchedulingConfigurer implementations and inject some TaskScheduler bean into the ScheduledTaskRegistrar. See @EnableScheduling JavaDocs:

 * <p>Implementing {@code SchedulingConfigurer} also allows for fine-grained
 * control over task registration via the {@code ScheduledTaskRegistrar}.
 * For example, the following configures the execution of a particular bean
 * method per a custom {@code Trigger} implementation:
 *
 * <pre class="code">
 * &#064;Configuration
 * &#064;EnableScheduling
 * public class AppConfig implements SchedulingConfigurer {
 *
 *     &#064;Override
 *     public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
 *         taskRegistrar.setScheduler(taskScheduler());
 *         taskRegistrar.addTriggerTask(
 *             new Runnable() {
 *                 public void run() {
 *                     myTask().work();
 *                 }
 *             },
 *             new CustomTrigger()
 *         );
 *     }
 *
 *     &#064;Bean(destroyMethod="shutdown")
 *     public Executor taskScheduler() {
 *         return Executors.newScheduledThreadPool(42);
 *     }
 *
 *     &#064;Bean
 *     public MyTask myTask() {
 *         return new MyTask();
 *     }
 * }</pre>

I found a couple JIRAs on the matter: https://jira.spring.io/browse/SPR-16189, https://jira.spring.io/browse/SPR-16705



来源:https://stackoverflow.com/questions/49742401/spring-websocket-simple-example-java-lang-illegalstateexception-unexpected-us

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!