9

I have a very simple web application for testing the @Scheduled annotation. The method read() in the class RetrievePrices is annotated with @Scheduled . After deploying the war on Tomcat, I was expecting that the read method should be executed every 5 seconds, but nothing is displayed in the Tomcat console.

The Main SpringBoot class

package com.aaaa.main;

import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
public class BatchMain {

    public static void main(String[] args) {

        SpringApplication.run(BatchMain.class, args);
    }

}

The Class whith a method annotated with @Scheduled

package com.aaaa.schedule;

import org.springframework.scheduling.annotation.Scheduled;

public class RetrievePrices {

    @Scheduled(fixedRate = 5000)
    public void read() {

        System.out.println(" *************  Scheduled(fixedRate = 5000) ");
}

A very simple Spring Configuration Class

package com.aaaa.config;

@Configuration
@ComponentScan("com.aaaa")
@EnableScheduling
public class MyConfiguration {
}

The POM

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
    </parent>
    <artifactId>batch</artifactId>
    <name>Batch processes</name>
    <packaging>war</packaging>

    <properties>
        <java.version>1.8</java.version>
        <Postgres.version>9.4-1200-jdbc41</Postgres.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>    
</project>

The updated class RetrievePrices

package com.aaaa.schedule;

import javax.annotation.PostConstruct;

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

@Component
public class RetrievePrices {

    @Scheduled(fixedRate = 5000)
    public void read() {

        System.out.println(" *************  into @Scheduled(fixedRate = 5000) ");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println(" *************  postConstruct ************** ");
    }
}
user2023141
  • 895
  • 5
  • 17
  • 36
  • 1
    your `RetrievePrices` class is not a spring bean. Add `@Component` on the class – pvpkiran Feb 10 '18 at 12:19
  • 2
    Move your `BatchMain` to the `com.aaaa` package (this is the recommended approach). Put the `@EnableScheduling` on the `BatchMain` class next to `@SpringBootApplication`. Delete your `MyConfiguration` and put `@Component` on your `RetrievePrices`. Then run the application. – M. Deinum Feb 11 '18 at 10:50
  • None of above suggestions solves the issue. It seems that Spring doesn't pick up the class "RetrievePrices" which is annotated with Component. I added a method "postConstruct()" which is annotated with PostConstruct, but this method is never called. – user2023141 Feb 12 '18 at 14:45

4 Answers4

8

Your RetrievePrices class does not have any sort of annotation to get picked up by the Spring scanning. Add @Component annotation for example and it should run fine.

Example:

@SpringBootApplication(scanBasePackages = { "com.aaaa" })
@EnableScheduling
public class BootApplication {

//
} 
Urosh T.
  • 3,336
  • 5
  • 34
  • 42
  • I've added @Component on the class RetrievePrices , but nothing is displayed on console yet. – user2023141 Feb 10 '18 at 12:25
  • Well, looking at my config, only thing different that I have is that my `@EnableScheduling` annontation is on my BootClass instead on my ConfigClass but if you scan your packages properly, it shouldn't be a problem. Try doing that and make sure you are scanning everything inside the root package. I will update the answer with an example – Urosh T. Feb 10 '18 at 12:46
  • I added @EnableScheduling on the class BatchMain. But still nothing is displayed on the Console. – user2023141 Feb 10 '18 at 12:50
  • And have you added the scanning part as well? Because your boot class is in a different package than your scheduler class. And by default it will only scan what is in it's own package and subpackages – Urosh T. Feb 10 '18 at 12:59
  • Well then you will have to debug it yourself and get your hands dirty because it is really strange. I suggest autowiring a bean in the scheduler class and see if it creates (which will pinpoint the problem - is it package scanning or something else) or moving the boot class to root package or try using springboot 1.5.9 and so on and so forth. Good luck and be sure to post the solution back once you have it! – Urosh T. Feb 10 '18 at 13:22
5

Creating a Simple Scheduler in SpringBoot (Working Code)

  1. Application Class

    package com.springboot.test;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @EnableScheduling
    @SpringBootApplication
    public class TestApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
    }
    
  2. Controller Class

    package com.springboot.test;
    
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class SchedulerTest {
    
        @Scheduled(fixedRate=2000)
        public void name() {
        System.out.println("HI");   
            }
    }
    
  3. pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.springboot</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    
    <name>test</name>
    <description>Demo project for Spring Boot</description>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    </project>
    

This Simple test code is Working for me.

Pradeep Naik
  • 51
  • 1
  • 2
5

If you use springBoot 2.4.x (Spring 5 version), to get @Scheduled to work, you will have to define its method in a seperate file class from the @SpringBootApplication file annotated class. The new class must be a component, so must be annotated with @Component, also add the annotation @EnableScheduling at the same class level, for the all thing to work. Hope this helped.

lyrio
  • 268
  • 1
  • 5
  • 13
2

I encountered a similar issue and I felt like I should mention what worked for me, it might help someone else.

I added @EnableScheduling, the component scan was fine, sources checked out fine but there was one issue, the project was an inherited groovy project and I did not know that I needed to mark my project source folder as 'sources root' in intellij, this is not necessary in java projects in intellij. So if you have done everything you might need to check your build tool or IDE to make sure that your sources root is marked appropriately.

Kinglee
  • 53
  • 1
  • 8