Saturday 20 May 2017


Scheduling in Spring.

 

Pure annotation based approach.

Let us use pure Java based configuration. No web.xml. No Spring configuration xml.
I am going to use maven to create a project for me eclipse.

Here are my dependencies from pom.xml
      <dependencies>
                   <dependency>
                             <groupId>org.springframework</groupId>
                             <artifactId>spring-webmvc</artifactId>
                             <version>4.3.7.RELEASE</version>
                   </dependency>
                   <dependency>
                             <groupId>javax.servlet</groupId>
                             <artifactId>javax.servlet-api</artifactId>
                             <version>3.1.0</version>
                   </dependency>
                   <dependency>
                             <groupId>junit</groupId>
                             <artifactId>junit</artifactId>
                             <version>3.8.1</version>
                             <scope>test</scope>
                   </dependency>
          </dependencies>
Set the packaging as war
          <packaging>war</packaging>
Since there is going to be no web.xml, we need to tell this to maven, so that maven generates the war file for us regardless of the present of deployment descriptor file. So set <failOnMissingWebXml> to false in maven-war-plugin configuration.
      <build>
                   <finalName>springscheduler</finalName>
                   <plugins>
                             <plugin>
                                      <groupId>org.apache.maven.plugins</groupId>
                                      <artifactId>maven-war-plugin</artifactId>
                                      <version>2.5</version>
                                      <configuration>
                                                <failOnMissingWebXml>false</failOnMissingWebXml>
                                      </configuration>
                             </plugin>
                     </plugins>
          </build>
@Configuration
@ComponentScan(basePackages="com.rizwan.test")
@EnableScheduling
public class AppConfig {

}
@EnableScheduling annotation enables Spring's scheduled task execution capability, similar to functionality found in Spring's <task:*> XML namespace. To be used on @Configuration classes. Without @EnableScheduling @Schedule annotation would have no effect. It is the xml equivalent of <task:annotation-driven />. Just as without <task:annotationdriven /> scheduling wont happen, similarly without @EnableScheduling scheduling won’t happen.

The Java configuration class decorated with @Configuration annotation. This class eliminates the need for spring configuration.
Taken straight from Javadoc of @Configuration annotation: @Configuration Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.

The AppConfig class here is empty. Note the presence of @ComponentScan annotation. It configures component scanning for use with @Configuration. Thus for classes annotated with @Service, @Controller, @Component, @RESTController, @Repository, etc, a bean will be created automatically and registered in the spring application context.

public interface Work {

          public void work();
}

@Component("synch")
public class SynchWorker implements Work {

          public void work() {

                   System.out.println("Doing some work");
          }
}

Work interface and its implementation represents a Spring component for doing any work.
@Service
public interface RefreshTokenService {

          public void refreshToken();
}


@Service
public class RefreshTokenServiceImpl implements RefreshTokenService {

          @Autowired
          @Qualifier("synch")
          private SynchWorker worker;

          public SynchWorker getWorker() {
                   return worker;
          }

          public void setWorker(SynchWorker worker) {
                   this.worker = worker;
          }

          /*
             * fixedDelay - Execute the annotated method with a fixed period in
             * milliseconds between the end of the last invocation and the start of the
             * next.
             *
             * fixedRate - Execute the annotated method with a fixed period in
             * milliseconds between invocations.
             *
             * initialDelay - Number of milliseconds
             * to delay before the first execution of a fixedRate() or fixedDelay()
             * task.
             */

          @Scheduled(fixedDelay = 1000, initialDelay = 1000)
          public void refreshToken() {
                  
                   worker.work();
          }
}

Note that method decorated with @Scheduled annotation must return void and must not accept any arguments.

Here the scheduling is happening synchronously. This means unless the previous task is completed, next run of the task won’t start. It will simply wait for the previous task to complete.

In the asynchronous scheduling next task will start irrespective of whether previous task has finished. Next task will be typically started in a new thread.
For asynchronous scheduling, use the @Async annotation.

        @Scheduled(fixedDelay = 1000, initialDelay = 1000)
        @Async
          public void refreshToken() {
                  
                   worker.work();
          }
@Scheduled and @Async annotations can be applied on both refreshToken method of Service class as well as work method of the Worker component.


No comments:

Post a Comment