Spring ThreadPoolTaskScheduler vs ThreadPoolTaskExecutor - spring

It is mentioned in the Spring documentation that:
ThreadPoolTaskScheduler actually implements Spring's TaskExecutor interface as well, so that a single instance can be used for asynchronous execution as soon as possible as well as scheduled, and potentially recurring, executions.
So which are the scenarios where we would want to use ThreadPoolTaskExecutor instance over ThreadPoolTaskScheduler instance?
I am using currently using Spring XML. I am creating bean of ThreadPoolTaskScheduler as follows:
<task:scheduler id="myScheduler" pool-size="1"/>
while bean of ThreadPoolTaskExecutor instance can be created as
<task:executor id="executor" pool-size="10"/>

ThreadPoolTaskExecutor is a specialized class for executing tasks.
ThreadPoolTaskScheduler is a specialized class for scheduling tasks.
The sentence you quoted in the Spring documentation is only saying that you can use a scheduler to execute tasks, but that it is not its main purpose. A ThreadPoolTaskExecutor provides fine-grained configuration over the thread pool through its corePoolSize, maxPoolSize, keepAliveSeconds and queueCapacity properties. A scheduler such as ThreadPoolTaskScheduler does not provide such configuration.
As such, choosing between the two comes down the following question: do I need to execute or schedule execution of tasks?

Related

Is there any valid reason for declaring a Quartz Job as a spring bean?

By looking at some examples of running quartz jobs in a spring boot app, I see many of them are actually declaring the Job with the #Component annotation :
Baeldung example
Dzone example
Medium example
It seems to be completly useless as the job factory will create a new instance every time the job is triggered.
I can see in my app that the method SpringBeanJobFactory.createJobInstance is called each time the job is executed. I removed the #Component annotation and it works perfectly, so is there any advantage of declaring a Job as a spring bean ?

What implementation is used when Autowiring the scheduler interface in Quartz Scheduler?

#Autowired
private Scheduler scheduler;
I found multiple implementations implementing the Scheduler interface (like RemoteScheduler, stdScheduler). So which one is actually being used in Spring?
When I printed out the scheduler class using
scheduler.getClass();
I saw stdScheduler. I'm wondering in what way Quartz is setting up which implementation to use.

Default TaskExecutor implementation for Async event listeners

I am using an annotation-based event listener which I have also tagged as #Async. (See Asynchronous Listeners).
Which TaskExecutor implementation is Spring using to serve these requests? The documentation reads:
By default, when specifying #Async on a method, the executor that is used is the one configured when enabling async support, i.e. the “annotation-driven” element if you are using XML or your AsyncConfigurer implementation, if any.
The problem is that I haven't done any configuration for this at all, so I am not sure what my AsyncConfigurer implementation is to begin with.
My guess is that we're dealing a SimpleAsyncTaskExecutor.
I found the answer in the documentation for EnableAsync:
By default, Spring will be searching for an associated thread pool definition: either a unique TaskExecutor bean in the context, or an Executor bean named "taskExecutor" otherwise. If neither of the two is resolvable, a SimpleAsyncTaskExecutor will be used to process async method invocations.
So, it's the SimpleAsyncTaskExecutor.

How to make spring manage the thread of anonymous class

I understand that if I do following I can make spring manage the thread
#Component
#Scope("prototype")
public class ATask implements Runnable{....}
ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor) context.getBean("taskExecutor");
ATask aTask1 = (ATask) ctx.getBean("aTask");
taskExecutor.execute(aTask1);
What I don't understand is what is the difference between
taskExecutor.execute(aTask1);
and
taskExecutor.execute(new ATask("A task 1"));
My guess is in second case, creation of thread is not managed by spring by execution is.
Second question,
For below code,
this.taskExecutor.execute(new Runnable() {
#Override
public void run() {...}});
Does spring manage/control the number of threads run simultaneously?
How do I make it work same as a thread with #Component and #Scope("prototype")? - One option is to move the code to a different class, but we are trying to avoid that as we have many small such methods.
Answer to your first question - there is no difference between first and second, in both the cases thread pool management will be handed by Spring because you are calling execute method on Spring's ThreadPoolTaskExecutor, if you were calling it on java.util.concurrent.ThreadPoolExecutor then thread pool management would not be handled by Spring.
Answer to your second question - if you are using Spring's ThreadPoolTaskExecutor then thread pool management will be handled by Spring. You are read about core pool size, max pool size and queue capacity to understand how to control number of thread running simultaneously.
Overall I think you are confused between the fact that Spring is fundamentally a IOC container and Spring provides ThreadPoolTaskExecutor for thread pool management (which is nothing but Spring's version of Java's java.util.concurrent.ThreadPoolExecutor).
Understand it this way: when you do taskExecutor.execute(aTask1); then thread pool management will be handled by Spring because you are using Spring's ThreadPoolTaskExecutor, ALSO bean management will be handled by Spring because aTask1 is object of Spring bean. And when you do taskExecutor.execute(new ATask("A task 1")); then thread pool management will be handled by Spring because you are using Spring's ThreadPoolTaskExecutor, BUT this time bean management will not be done by Spring because you are using new to create object yourself.

Using Spring AOP with Quartz scheduler

I am using Quartz scheduler for scheduling purposes in my project. I need to gather statistics like when, for how long, and how many times a job was run. I want to use Spring AOP for the same. For this, I am making Job classes spring-managed beans. Spring creates a Proxy class for each of the Job classes. But now when Quartz tries to execute this spring-managed Job, I am getting InstantiationException for the Proxy class created for the Job by Spring.
org.quartz.SchedulerException: Problem instantiating class '$Proxy6'
[See nested exception: java.lang.InstantiationException: $Proxy6]
Can anybody please suggest a solution for this problem?
If you use quarz directly (not via Spring Schedule annotation), you can ask quarz directly for the statistics. -- Many of them are already implemented in quarz.
Because Quartz Job class is managed by Quartz container not Spring container, Spring AOP can not achieve your goal. For your purpose, there are 2 ways that you can work on this:
Quartz has listener mechanism builtin, you can use a global listener to do want you want, as the AOP works. For more information about listener, refer to: Quartz document.
If you insist on Spring AOP, you have to customize the job class instantiation process, so that the job class is managed by Spring Container. One approach is write your own JobFactory, which extends SpringBeanJobFactory then override the createJobInstance() method. If you want more things about this, please comment on this, I will write more detail on this.

Resources