Running background scheduled tasks in Spring MVC

1- Spring @Scheduled Annotation

Sometimes in an application you need to create a scheduled task to run in the background. For example, creating sitemaps file, sending email periodically,...
@Scheduled is an annotation used to configure a schedule, it is annotated on a method, and this method will be run according to schedule configured by @Scheduled.
public @interface Scheduled {
    String cron() default "";
    String zone() default "";
    long fixedDelay() default -1;
    String fixedDelayString() default "";
    long fixedRate() default -1;
    String fixedRateString() default "";
    long initialDelay() default -1;
    String initialDelayString() default "";

Attribute Description
cron A cron-like expression, extending the usual UN*X definition to include triggers on the second as well as minute, hour, day of month, month and day of week. e.g. "0 * * * * MON-FRI" means once per minute on weekdays (at the top of the minute - the 0th second).
  • @return an expression that can be parsed to a cron schedule
zone A time zone for which the cron expression will be resolved. By default, this attribute is the empty String (i.e. the server's local time zone will be used).
fixedDelay Execute the annotated method with a fixed period in milliseconds between the end of the last invocation and the start of the next.
  • @return the delay in milliseconds
fixedDelayString Execute the annotated method with a fixed period in milliseconds between the end of the last invocation and the start of the next.
  • @return the delay in milliseconds as a String value, e.g. a placeholder
fixedRate Execute the annotated method with a fixed period in milliseconds between invocations.
  • @return the period in milliseconds
fixedRateString Execute the annotated method with a fixed period in milliseconds between invocations.
  • @return the period in milliseconds as a String value, e.g. a placeholder
initialDelay Number of milliseconds to delay before the first execution of a fixedRate() or fixedDelay() task.
  • @return the initial delay in milliseconds
initialDelayString Number of milliseconds to delay before the first execution of a fixedRate() or fixedDelay() task.
  • @return the initial delay in milliseconds as a String value, e.g. a placeholder

2- Configure Maven & web.xml

<project xmlns="" xmlns:xsi=""
  <name>SpringMVCSchedule Maven Webapp</name>
            <!-- Servlet Library -->
        <!-- -->

        <!-- Spring dependencies -->
        <!-- -->

        <!-- -->

        <!-- -->
          <!-- Config: Maven Tomcat Plugin -->
          <!-- -->
              <!-- Config: contextPath and Port (Default: /SpringMVCSchedule : 8080) -->

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi=""
 id="WebApp_ID" version="3.0">

 <display-name>Spring MVC Schedule</display-name>

3- Configure Spring MVC
package org.o7planning.springmvcschedule.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

public class ApplicationContextConfig {

    @Bean(name = "viewResolver")
    public InternalResourceViewResolver getViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        return viewResolver;

package org.o7planning.springmvcschedule.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.servlet.DispatcherServlet;

public class SpringWebAppInitializer implements WebApplicationInitializer {

    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher",
                new DispatcherServlet(appContext));

package org.o7planning.springmvcschedule.config;

import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

public class WebMvcConfig extends WebMvcConfigurerAdapter {

   private static final Charset UTF8 = Charset.forName("UTF-8");

   // Config UTF-8 Encoding.
   public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
       StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
       stringConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8)));

       // Add other converters ...

   // Static Resource Config
   // equivalents for <mvc:resources/> tags
   public void addResourceHandlers(ResourceHandlerRegistry registry) {

   // Equivalent for <mvc:default-servlet-handler/> tag
   public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {

Configuration allows you to use Schedule:
package org.o7planning.springmvcschedule.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

public class SchedulerConfig {
    // Declaring the beans are related to the schedule here if necessary.


4- fixedDelay and fixedRate

This is the simplest example using @Schedule and fixedDelay attribute. In this example, the task will print out the current time Console and it will stop fixedDelay second after the task is finished to perform the task again.
package org.o7planning.springmvcschedule.schedule;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

public class WriteCurrentTimeSchedule {

  private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss sss");

  // 2 second.
  @Scheduled(fixedDelay = 2 * 1000)
  public void writeCurrentTime() {
      Date now = new Date();
      String nowString = df.format(now);
      System.out.println("Now is: "+ nowString);

You can configure delay time for the first run (initialDelay), after start application, the task only is performed until when the delay time is up.
// miliseconds.
@Scheduled(fixedDelay = 2 * 1000, initialDelay = 30 * 1000)
public void writeCurrentTime() {
   // Do something ..


fixedDelay so với fixedRate

You can only use either fixedDelay or fixedRate in @Schedule annotation but you cann't use both simultaneously.
  • fixedDelay is the rest period when the task is completed. After the rest time, it will perform the next task.
  • fixedRate is the period that is between the start time to perform the previous task and the start time to perform the next task, it doesn't depend on whether the previous task is completed or not.

5- Cron expression and zone

@Schedule allows you set up complex schedules, for example, perform tasks at every 12pm on Monday. To set up the complex schedules, you can use cron attribute.
cron expression is represented by six fields:
second, minute, hour, day of month, month, day(s) of week
"0 0 * * * *" // the top of every hour of every day.

"*/10 * * * * *" // every ten seconds.

"0 0 8-10 * * *" // 8, 9 and 10 o'clock of every day.

"0 0/30 8-10 * * *" // 8:00, 8:30, 9:00, 9:30 and 10 o'clock every day.

"0 0 9-17 * * MON-FRI" // on the hour nine-to-seventeen, and monday to friday

"0 0 0 25 12 ?" // every Christmas Day at midnight
Pattern Meaning
* means match any
*/X means "every X"
? ("no specific value") - useful when you need to specify something in one of the two fields in which the character is allowed, but not the other. For example, if I want my trigger to fire on a particular day of the month (say, the 10th), but don't care what day of the week that happens to be, I would put "10" in the day-of-month field, and "?" in the day-of-week field.

"0 0 0 25 12 ?":

At 12 midnight (0 hours) on Christmas Day (on 25th December), you don't mind which day it is.
'zone' attribute specified the time zone. Default value is empty, which means using the time zone of the Server.
@Scheduled(cron="0 1 1 * * *", zone="Europe/Istanbul")

public void doScheduledWork() {
    // Do something here
The following table contains a list of time zones supported by Oracle Real-Time Collaboration
Internal Name External User Visible Name
Pacific/Pago_Pago (-11:00) Pago Pago
Pacific/Honolulu (-10:00) Hawaii
America/Anchorage (-09:00) Alaska
America/Vancouver (-08:00) Canada Pacific Time
America/Los_Angeles (-08:00) US Pacific Time
America/Tijuana (-08:00) Tijuana
America/Edmonton (-07:00) Canada Mountain Time
America/Denver (-07:00) US Mountain Time
America/Phoenix (-07:00) Arizona
America/Mazatlan (-07:00) Mazatlan
America/Winnipeg (-06:00) Canada Central Time
America/Regina (-06:00) Saskatchewan
America/Chicago (-06:00) US Central Time
America/Mexico_City (-06:00) Mexico City
America/Guatemala (-06:00) Guatemala
America/El_Salvador (-06:00) El Salvador
America/Managua (-06:00) Managua
America/Costa_Rica (-06:00) Costa Rica
America/Montreal (-05:00) Canada Eastern Time
America/New_York (-05:00) US Eastern Time
America/Indianapolis (-05:00) East Indiana
America/Panama (-05:00) Panama
America/Bogota (-05:00) Bogota
America/Lima (-05:00) Lima
America/Halifax (-04:00) Canada Atlantic Time
America/Puerto_Rico (-04:00) Puerto Rico
America/Caracas (-04:00) Caracas
America/Santiago (-04:00) Santiago
America/St_Johns (-03:30) Newfoundland
America/Sao_Paulo (-03:00) Sao Paulo
Atlantic/Azores (-01:00) Azores
Etc./UTC (00:00) Universal Time
UTC (00:00) Universal Time
Atlantic/Reykjavik (00:00) Reykjavik
Europe/Dublin (00:00) Dublin
Europe/London (00:00) London
Europe/Lisbon (00:00) Lisbon
Africa/Casablanca (00:00) Casablanca
Africa/Nouakchott (00:00) Nouakchott
Europe/Oslo (+01:00) Oslo
Europe/Stockholm (+01:00) Stockholm
Europe/Copenhagen (+01:00) Copenhagen
Europe/Berlin (+01:00) Berlin
Europe/Amsterdam (+01:00) Amsterdam
Europe/Brussels (+01:00) Brussels
Europe/Luxembourg (+01:00) Luxembourg
Europe/Paris (+01:00) Paris
Europe/Zurich (+01:00) Zurich
Europe/Madrid (+01:00) Madrid
Europe/Rome (+01:00) Rome
Africa/Algiers (+01:00) Algiers
Africa/Tunis (+01:00) Tunis
Europe/Warsaw (+01:00) Warsaw
Europe/Prague (+01:00) Prague Bratislava
Europe/Vienna (+01:00) Vienna
Europe/Budapest (+01:00) Budapest
Europe/Sofia (+02:00) Sofia
Europe/Istanbul (+02:00) Istanbul
Europe/Athens (+02:00) Athens
Asia/Nicosia (+02:00) Nicosia
Asia/Beirut (+02:00) Beirut
Asia/Damascus (+02:00) Damascus
Asia/Jerusalem (+02:00) Jerusalem
Asia/Amman (+02:00) Amman
Africa/Tripoli (+02:00) Tripoli
Africa/Cairo (+02:00) Cairo
Africa/Johannesburg (+02:00) Johannesburg
Europe/Moscow (+03:00) Moscow
Asia/Baghdad (+03:00) Baghdad
Asia/Kuwait (+03:00) Kuwait
Asia/Riyadh (+03:00) Riyadh
Asia/Bahrain (+03:00) Bahrain
Asia/Qatar (+03:00) Qatar
Asia/Aden (+03:00) Aden
Africa/Khartoum (+03:00) Khartoum
Africa/Djibouti (+03:00) Djibouti
Africa/Mogadishu (+03:00) Mogadishu
Asia/Dubai (+04:00) Dubai
Asia/Muscat (+04:00) Muscat
Asia/Yekaterinburg (+05:00) Yekaterinburg
Asia/Tashkent (+05:00) Tashkent
Asia/Calcutta (+05:30) India
Asia/Novosibirsk (+06:00) Novosibirsk
Asia/Almaty (+06:00) Almaty
Asia/Dacca (+06:00) Dacca
Asia/Krasnoyarsk (+07:00) Krasnoyarsk
Asia/Bangkok (+07:00) Bangkok
Asia/Saigon (+07:00) Vietnam
Asia/Jakarta (+07:00) Jakarta
Asia/Irkutsk (+08:00) Irkutsk
Asia/Shanghai (+08:00) Beijing, Shanghai
Asia/Hong_Kong (+08:00) Hong Kong
Asia/Taipei (+08:00) Taipei
Asia/Kuala_Lumpur (+08:00) Kuala Lumpur
Asia/Singapore (+08:00) Singapore
Australia/Perth (+08:00) Perth
Asia/Yakutsk (+09:00) Yakutsk
Asia/Seoul (+09:00) Seoul
Asia/Tokyo (+09:00) Tokyo
Australia/Darwin (+09:30) Darwin
Australia/Adelaide (+09:30) Adelaide
Asia/Vladivostok (+10:00) Vladivostok
Australia/Brisbane (+10:00) Brisbane
Australia/Sydney (+10:00) Sydney Canberra
Australia/Hobart (+10:00) Hobart
Asia/Magadan (+11:00) Magadan
Asia/Kamchatka (+12:00) Kamchatka
Pacific/Auckland (+12:00) Auckland
In the example below, the task is performed at 1h20' on Monday, Tuesday, Wednesday and Thursday.
"0 20 1 * * MON-THU"
package org.o7planning.springmvcschedule.schedule;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

public class CronSchedule {

    @Scheduled(cron = "0 20 1 * * MON-THU")
    public void doSomething() {

        System.out.println("Do some thing");