-
Notifications
You must be signed in to change notification settings - Fork 38.1k
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
WebSocketMessageBrokerStats.getExecutorStatsInfo() throws exception if Executor is not a ThreadPoolExecutor #27209
Comments
Hi @leandrodalbo, Thanks for submitting your first issue for the Spring Framework!
The expected However, I can see that an exception could be thrown if the For the sake of clarity, could you please provide the stack trace you encountered when the exception was thrown? |
Have you overridden the |
I didn't override any of those beans when I discovered this. I was using a simple configuration class in combination with netty-reactor and netty-all libraries. I haven't got access to the code right now but it was simple Message broker configuration with stomp relay. When I was debugging it was using ThreadPoolTaskExecutor but because of the "P" instead "p" you get a -1 in the substring() method. |
Overriding the the stats bean and using str.toLowercase() is a quick fix but maybe not the best option. |
I already have a fix in place locally, but I'd appreciate if you could supply the stack trace once you get a chance, since that will give us a better idea of what exactly went wrong, possibly allowing us to provide a more intelligent fix. |
Exception
Configuration Class@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
private static final int BROKER_HEARTBEAT_INTERVAL_MILLIS = 20000;
@Autowired
private Environment env;
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
if (Boolean.parseBoolean(env.getProperty("myprops.rabbitmq.enabled"))) {
registry.setApplicationDestinationPrefixes("/cantsayit");
registry.enableStompBrokerRelay("/topic/", "/queue/")
.setClientLogin(env.getProperty("myprops.rabbitmq.username"))
.setClientPasscode(env.getProperty("myprops.rabbitmq.password"))
.setSystemLogin(env.getProperty("myprops.rabbitmq.username"))
.setSystemPasscode(env.getProperty("myprops.rabbitmq.password"))
.setRelayHost(env.getProperty("myprops.rabbitmq.hostname"))
.setRelayPort(Integer.parseInt(env.getProperty("myprops.rabbitmq.port")))
.setSystemHeartbeatSendInterval(BROKER_HEARTBEAT_INTERVAL_MILLIS)
.setAutoStartup(true);
} else {
registry.setApplicationDestinationPrefixes("/cantsayit")
.enableSimpleBroker("/queue", "/topic");
}
}
} Dependencies <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
</dependencies> Using the |
Thanks for providing the feedback! The exception stack trace is as I expected. It indicates that the I tried to reproduce the error using the configuration you supplied, but I unfortunately was not able to reproduce the failure scenario. In any case, I can fix the bug to ensure that a Having said that, I would still like to reproduce the bug using your application in order to see if there is anything better we can do (for example, to support stats for other types of As a side note, adding the following bean to the @Bean
public TaskExecutor clientInboundChannelExecutor() {
SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
executor.setThreadNamePrefix("clientInboundChannel-");
return executor;
} |
@leandrodalbo, I fixed this in 42edef0. So please feel free to try this out in the upcoming 5.3.10 snapshot. If you are able to provide us a minimal example that reproduces the error you encountered in your application, we will consider reopening this issue to investigate further options. |
Hi, can't provide the app because it is not mine, but I think I found what is overriding the bean. @Configuration
@EnableScheduling
@EnableAsync( mode = AdviceMode.ASPECTJ )
public class SchedulerConfiguration
{
@Bean
@Primary
public TaskScheduler taskScheduler()
{
ThreadPoolTaskScheduler lThreadPoolTaskScheduler = new ThreadPoolTaskScheduler();
lThreadPoolTaskScheduler.setPoolSize( 4 );
return lThreadPoolTaskScheduler;
}
} I am not sure, I would need to debug it a bit more, anyway what you have done fixes the problem.
Thanks a lot. |
Granted, depending on the format of the text returned by
You're welcome! |
Prior to this commit, if the TaskExecutor configured in WebSocketMessageBrokerStats for the inboundChannelExecutor or outboundChannelExecutor was not a ThreadPoolTaskExecutor, a StringIndexOutOfBoundsException was thrown when attempting to parse the results of invoking toString() on the executor. The reason is that ThreadPoolTaskExecutor delegates to a ThreadPoolExecutor whose toString() implementation generates text containing "pool size = ...", and WebSocketMessageBrokerStats' getExecutorStatsInfo() method relied on the presence of "pool" in the text returned from toString(). This commit fixes this bug by ensuring that the text returned from toString() contains "pool" before parsing the text. If "pool" is not present in the text, getExecutorStatsInfo() now returns "unknown" instead of throwing a StringIndexOutOfBoundsException. Closes gh-27209
Prior to this commit, if the TaskExecutor configured in WebSocketMessageBrokerStats for the inboundChannelExecutor or outboundChannelExecutor was not a ThreadPoolTaskExecutor, a StringIndexOutOfBoundsException was thrown when attempting to parse the results of invoking toString() on the executor. The reason is that ThreadPoolTaskExecutor delegates to a ThreadPoolExecutor whose toString() implementation generates text containing "pool size = ...", and WebSocketMessageBrokerStats' getExecutorStatsInfo() method relied on the presence of "pool" in the text returned from toString(). This commit fixes this bug by ensuring that the text returned from toString() contains "pool" before parsing the text. If "pool" is not present in the text, getExecutorStatsInfo() now returns "unknown" instead of throwing a StringIndexOutOfBoundsException. Closes spring-projectsgh-27209
spring-framework/spring-websocket/src/main/java/org/springframework/web/socket/config/WebSocketMessageBrokerStats.java
Line 209 in d034a1f
Hardcoded "pool" doesn't work, the class name ThreadPoolExecutor contains capital "P" instead of "p".
The text was updated successfully, but these errors were encountered: