Scheduled Guide

Modern applications often need to run specific tasks periodically. In this guide, you learn how to schedule periodic tasks.

Prerequisites

To complete this guide, you need:

  • less than 10 minutes

  • an IDE

  • JDK 1.8+ installed with JAVA_HOME configured appropriately

  • Apache Maven 3.5.3+

Architecture

In this guide, we create a straightforward application accessible using HTTP to get the current value of a counter. This counter is periodically (every 10 seconds) incremented.

Architecture

Solution

We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.

Clone the Git repository: git clone https://github.com/quarkusio/quarkus-quickstarts.git, or download an archive.

The solution is located in the scheduling-periodic-tasks directory.

Creating the Maven project

First, we need a new project. Create a new project with the following command:

mvn io.quarkus:quarkus-maven-plugin:0.15.0:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=scheduling-periodic-tasks \
    -DclassName="org.acme.scheduling.CountResource" \
    -Dpath="/count" \
    -Dextensions="scheduler"

It generates:

  • the Maven structure

  • a landing page accessible on http://localhost:8080

  • example Dockerfile files for both native and jvm modes

  • the application configuration file

  • an org.acme.scheduling.CountResource resource

  • an associated test

The Maven project also imports the Quarkus scheduler extension.

Creating a scheduled job

In the org.acme.scheduling package, create the CounterBean class, with the following content:

package org.acme.scheduling;

import java.util.concurrent.atomic.AtomicInteger;
import javax.enterprise.context.ApplicationScoped;
import io.quarkus.scheduler.Scheduled;

@ApplicationScoped              // (1)
public class CounterBean {

    private AtomicInteger counter = new AtomicInteger();

    public int get() {
        return counter.get();
    }

    @Scheduled(every="10s")     // (2)
    void increment() {
        counter.incrementAndGet();
    }

}
  1. Declare the bean in the application scope

  2. Use the @Scheduled annotation to instruct Quarkus to runs this method every 10 seconds

The code is pretty straightforward. Every 10 seconds, the counter is incremented. The get() method allows retrieving the current value.

Note
Cron-like expressions are also supported. The syntax is currently based on Quartz Cron Trigger. For example a method annotated with @Scheduled(cron="0 15 10 * * ?") is executed at 10:15am every day.

Updating the resource and the test

Edit the CountResource class, and update the content to:

package org.acme.scheduling;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/count")
public class CountResource {

    @Inject
    CounterBean counter;            // (1)


    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "count: " + counter.get();  // (2)
    }
}
  1. Inject the CounterBean

  2. Send back the current counter value

We also need to update the tests. Edit the CountResourceTest class to match:

package org.acme.scheduling;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;

@QuarkusTest
public class CountResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/count")
          .then()
             .statusCode(200)
             .body(containsString("count")); // (1)
    }

}
  1. Ensure that the response contains count

Package and run the application

Run the application with: ./mvnw compile quarkus:dev. In another terminal, run curl localhost:8080/count to check the counter value. After a few seconds, re-run curl localhost:8080/count to verify the counter has been incremented.

As usual, the application can be packaged using ./mvnw clean package and executed using the -runner.jar file. You can also generate the native executable with ./mvnw clean package -Pnative.