The Spring Framework provides abstractions for asynchronous execution and scheduling of tasks with the TaskExecutor
and TaskScheduler interfaces, respectively.
Introduction
In this post we will learn how to schedule jobs and perform asynchronous task execution with Spring.
How to Complete this Guide
Download and unzip the source repository
for this guide, or clone it using Git: git clone https://github.com/juliuskrah/spring-schedular-example.git
This is a Spring-Boot based project and we are going to add the following dependencies to our pom.xml:
Task Sheduler
Sometimes you will want to perform an unsupervised task at a future time. For example you have a social media site
and will want to remove all users who have been inactive for three months. You want this job to be performed at
midnight each day.
To illustrate this, we will build a simple scheduled task that removes all users from an embedded h2 database
with a status of false.
The scheduledTask() method will run 30 seconds past each minute. This method is annotated with @Scheduled which
tells the Spring Framework to run it repeatedly.
The cron property takes a cron expression. In our situation it is an expression to run
30 seconds past each minute.
The @Scheduled annotation can be added to a method along with trigger metadata. For example, the following method
would be invoked every 5 seconds with a fixed delay, meaning that the period will be measured from the completion time
of each preceding invocation.
If a fixed rate execution is desired, simply change the property name specified within the annotation. The following
would be executed every 5 seconds measured between the successive start times of each invocation.
For fixed-delay and fixed-rate tasks, an initial delay may be specified indicating the number of milliseconds to wait
before the first execution of the method.
Notice that the methods to be scheduled must have void returns and must not expect any arguments. If the method needs
to interact with other objects from the Application Context, then those would typically have been provided through
dependency injection
To enable support for @Scheduled annotation add @EnableScheduling to one of your @Configuration classes:
Using the @EnableScheduling Spring will by default be searching for an associated scheduler definition: either a
unique org.springframework.scheduling.TaskScheduler bean in the context, or a TaskScheduler bean named
"taskScheduler" otherwise; the same lookup will also be performed for a
java.util.concurrent.ScheduledExecutorService bean. If neither of the two is resolvable, a local single-threaded
default scheduler will be created and used within the registrar.
We will create a Bean of type TaskScheduler named taskScheduler. The name of this bean will serve as the thread name prefix (taskScheduler-) of the thread created by the framework to handle the scheduled jobs.
Putting it all together for the scheduling we have:
Sometimes you would want to perform a long running operation and you would not want to wait for the operation to
return control before proceeding. You would rather prefer to carry on with other operations and be notified once
this long-running operation has returned at which point you would do other things with it.
In a scenario like this you would want to perform this operation asynchronously and this is where Spring’s Task
Execution comes into picture.
In this example we will make a batch insert of one million records and record the execution time:
The @Async annotation can be provided on a method so that invocation of that method will occur asynchronously. In
other words, the caller will return immediately upon invocation and the actual execution of the method will occur in a
task that has been submitted to a Spring TaskExecutor. In the simplest case, the annotation may be applied to a
void-returning method.
Unlike the methods annotated with the @Scheduled annotation, these methods can expect arguments, because they will be
invoked in the “normal” way by callers at runtime rather than from a scheduled task being managed by the container. For
example, the following is a legitimate application of the @Async annotation.
Even methods that return a value can be invoked asynchronously. However, such methods are required to have a Future
typed return value. This still provides the benefit of asynchronous execution so that the caller can perform other
tasks prior to calling get() on that Future.
To enable support for @Async annotation add @EnableAsync to one of your @Configuration classes:
Using the @EnableAsnc Spring will by default be searching for an associated thread pool definition: either a unique
org.springframework.core.task.TaskExecutor bean in the context, or an java.util.concurrent.Executor bean named
"taskExecutor" otherwise. If neither of the two is resolvable, a
org.springframework.core.task.SimpleAsyncTaskExecutor will be used to process async method invocations.
We will create a Bean of type TaskExecutor named taskExecutor. The name of this bean will serve as the thread name
prefix (taskExecutor-) of the thread created by the framework to handle the async jobs:
When you run this code you should get an output similar to the following:
Conclusion
In this post we learned how to Schedule and Execute jobs leveraging the abstraction of the Spring Framework.
As usual you can find the full example to this guide in the github repository. Until the next post, keep doing cool things .