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

DefaultManagedTaskExecutor throws java.lang.UnsupportedOperationException: isShutdown when rejecting tasks #34514

Closed
DavidCerny2737 opened this issue Feb 28, 2025 · 2 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Milestone

Comments

@DavidCerny2737
Copy link

I migrated old SpringBoot application running on Websphere Application Server to SpringBoot 3.2.5 running on WebSphere Liberty and I have encountered an issue with DefaultManagedTaskExecutor. I am connecting DefaultManagedTaskExecutor to jndi managedExecutorService defined on Liberty server:

Bean definition:

@Bean(name = "appTaskExecutor")    
@Primary    
    TaskExecutor appJndiTaskExecutor() {
        DefaultManagedTaskExecutor executor = new DefaultManagedTaskExecutor();
        executor.setResourceRef(true);
        executor.setJndiName("concurrent/appTask");
        return executor;
    }

server.xml

<managedExecutorService jndiName="concurrent/appTask">    
    <concurrencyPolicy max="2" maxQueueSize="5" runIfQueueFull="false" maxWaitForEnqueue="0" />    
</managedExecutorService>

I am then using appTaskExecutor in @Async annotation to run periodically scheduled async task. Problem happens when managedExecutorService task queue gets full and starts to reject new tasks. We are handeling such case with our logic triggering on TaskRejectedException throwing from TaskExecutorAdapter. Unfortunatelly this exception will be never thrown, indead we are expiriencing this:

java.lang.IllegalStateException: java.lang.UnsupportedOperationException: isShutdown
	at com.ibm.ws.concurrent.internal.ManagedExecutorServiceImpl.isShutdown(ManagedExecutorServiceImpl.java:710) ~[?:?]
	at org.springframework.core.task.TaskRejectedException.executorDescription(TaskRejectedException.java:72) ~[spring-core-6.1.6.jar:6.1.6]
	at org.springframework.core.task.TaskRejectedException.<init>(TaskRejectedException.java:66) ~[spring-core-6.1.6.jar:6.1.6]
	at org.springframework.core.task.support.TaskExecutorAdapter.submit(TaskExecutorAdapter.java:132) ~[spring-core-6.1.6.jar:6.1.6]
	at org.springframework.scheduling.concurrent.ConcurrentTaskExecutor$ManagedTaskExecutorAdapter.submit(ConcurrentTaskExecutor.java:221) ~[spring-context-6.1.6.jar:6.1.6]
	at org.springframework.scheduling.concurrent.ConcurrentTaskExecutor.submit(ConcurrentTaskExecutor.java:172) ~[spring-context-6.1.6.jar:6.1.6]
	at org.springframework.aop.interceptor.AsyncExecutionAspectSupport.$sw$original$doSubmit$m32m8m3(AsyncExecutionAspectSupport.java:297) ~[spring-aop-6.1.6.jar:6.1.6]
...

The problem lies in impelmentation of TaskRejectedException in executorDescription method method where executorService.isShutdown() gets called which is illegal in jakarta concurrent specification - chapter 3.1.6.1 in case when executorService is not managed by application itself but it is managed on server:

The lifecycle of a ManagedExecutorService is managed by an application server. All lifecycle operations on the ManagedExecutorService interface will throw a java.lang.IllegalStateException exception. This includes the following methods that are defined in the java.util.concurrent.ExecutorService interface: awaitTermination(), isShutdown(), isTerminated(), shutdown(), and shutdownNow().

It looks like this behaviour is part of jakarta concurrent specification going all the way back to the first edition of concurrency utilities for Java EE.. I have discussed this topic on StackOverflow and accepted workaround by using JndiObjectFactoryBean exposing only Executor interface via proxy to ConcurrentTaskExecutor, but it is still a workaround. In open liberty ManagedExecutorServiceImpm can be seen isShutdown() implementation and it follows jakarta concurrency specification. To be frank I am not sure what would be the right thing to fix this. In StackOverflow discussion came up an idea to open feature request on jakarta concurrency for a new version specification, but first I would like to open this topic here.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 28, 2025
@jhoeller jhoeller added type: bug A general bug 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 labels Feb 28, 2025
@jhoeller jhoeller self-assigned this Feb 28, 2025
@jhoeller jhoeller added this to the 6.2.4 milestone Feb 28, 2025
@jhoeller jhoeller added the for: backport-to-6.1.x Marks an issue as a candidate for backport to 6.1.x label Feb 28, 2025
@github-actions github-actions bot added status: backported An issue that has been backported to maintenance branches and removed for: backport-to-6.1.x Marks an issue as a candidate for backport to 6.1.x labels Feb 28, 2025
@jhoeller
Copy link
Contributor

This is effectively a regression caused by #27090 in 6.1. I'll address this through catching an exception coming out of isShutdown, falling back to Executor.toString() instead in that case.

jhoeller added a commit that referenced this issue Feb 28, 2025
@jhoeller
Copy link
Contributor

This revision is available in the latest 6.2.4 snapshot as well as the upcoming 6.1.18 snapshot. Please give it an early try if you have the chance...

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) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants