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.


Monday 15 May 2017

Using @Value annotation in Spring

Hi guys today in one of the projects that I working on, I had to inject a value into one of the bean properties.
So I decided to use @Value annotation. Sharing the experience I have had.

I am using Spring 4.3.7.RELEASE. Here are the dependencies in my pom.xml

  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.7.RELEASE</version>
      </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>


spring-context depends up spring-beans, spring-core, spring-aop, spring-expression and commons-logging. So you do not have to worry about adding those. They will be automatically be added to your Maven dependencies in eclipse.
Go to the Dependencies Hierarchy tab, you will be able to clearly see the hierarchy.
 
Here is the class defining Java configuration.

@Configuration
@PropertySource("classpath:config/config.properties")
public class AppConfig {

    @Bean
    public Person getPerson(){
       
        return new Person();
    } 

}



@Configuration annotation is necessary here to indicate that this class will defined java configuration.
@PropertySource provides a convenient and declarative mechanism for adding a PropertySource to Spring's Environment. To be used in conjunction with @Configuration.

Have created config folder in resources folder of my Maven project and added a file called config.properties to it.

Config.properties
person.name=Rizwan

Here is the Person bean
public class Person {

    @Value("${person.name}")
    private String name;
    private int age;


//..getter and setters

}
 The ${propertyname} syntax tells the Spring container to search for the specified  propertyname in Spring's property sources. 

Here is the complete project structure.


Thats it, test it.

public class App
{
    public static void main( String[] args )
    {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Person person = context.getBean(Person.class);
        System.out.println("Hello " + person.getName());
        ((AnnotationConfigApplicationContext)context).close();
    }
}


Output:
Hello Rizwan

In my next post, will try to add few more tips and tricks about @Value annotation, like working with default values and reading from System environment variables.