Getting started

If you are just getting started with Spring Cloud Task, you should read this section. Here, we answer the basic “what?”, “how?”, and “why?” questions. We start with a gentle introduction to Spring Cloud Task. We then build a Spring Cloud Task application, discussing some core principles as we go.

Introducing Spring Cloud Task

Spring Cloud Task makes it easy to create short-lived microservices. It provides capabilities that let short-lived JVM processes be executed on demand in a production environment.

System Requirements

You need to have Java installed (Java 17 or better).

Database Requirements

Spring Cloud Task uses a relational database to store the results of an executed task. While you can begin developing a task without a database (the status of the task is logged as part of the task repository’s updates), for production environments, you want to use a supported database. Spring Cloud Task currently supports the following databases:

  • DB2

  • H2

  • HSQLDB

  • MySql

  • Oracle

  • Postgres

  • SqlServer

Developing Your First Spring Cloud Task Application

A good place to start is with a simple “Hello, World!” application, so we create the Spring Cloud Task equivalent to highlight the features of the framework. Most IDEs have good support for Apache Maven, so we use it as the build tool for this project.

The spring.io web site contains many Getting Started” guides that use Spring Boot. If you need to solve a specific problem, check there first. You can shortcut the following steps by going to the Spring Initializr and creating a new project. Doing so automatically generates a new project structure so that you can start coding right away. We recommend experimenting with the Spring Initializr to become familiar with it.

Creating the Spring Task Project using Spring Initializr

Now we can create and test an application that prints Hello, World! to the console.

To do so:

  1. Visit the Spring Initialzr site.

    1. Create a new Maven project with a Group name of io.spring.demo and an Artifact name of helloworld.

    2. In the Dependencies text box, type task and then select the Task dependency with the Spring Cloud label.

    3. In the Dependencies text box, type h2 and then select the H2 dependency with the SQL label.

    4. Click the Generate Project button

  2. Unzip the helloworld.zip file and import the project into your favorite IDE.

Writing the Code

To finish our application, we need to update the generated HelloworldApplication with the following contents so that it launches a Task.

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.task.configuration.EnableTask;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableTask
public class HelloworldApplication {

	@Bean
	public ApplicationRunner applicationRunner() {
		return new HelloWorldApplicationRunner();
	}

	public static void main(String[] args) {
		SpringApplication.run(HelloworldApplication.class, args);
	}

	public static class HelloWorldApplicationRunner implements ApplicationRunner {

		@Override
		public void run(ApplicationArguments args) throws Exception {
			System.out.println("Hello, World!");

		}
	}
}

While it may seem small, quite a bit is going on. For more about Spring Boot specifics, see the Spring Boot reference documentation.

Now we can open the application.properties file in src/main/resources. We need to configure two properties in application.properties:

  • application.name: To set the application name (which is translated to the task name)

  • logging.level: To set the logging for Spring Cloud Task to DEBUG in order to get a view of what is going on.

The following example shows how to do both:

logging.level.org.springframework.cloud.task=DEBUG
spring.application.name=helloWorld

Task Auto Configuration

When including Spring Cloud Task Starter dependency, Task auto configures all beans to bootstrap it’s functionality. Part of this configuration registers the TaskRepository and the infrastructure for its use.

In our demo, the TaskRepository uses an embedded H2 database to record the results of a task. This H2 embedded database is not a practical solution for a production environment, since the H2 DB goes away once the task ends. However, for a quick getting-started experience, we can use this in our example as well as echoing to the logs what is being updated in that repository. In the Configuration section (later in this documentation), we cover how to customize the configuration of the pieces provided by Spring Cloud Task.

When our sample application runs, Spring Boot launches our HelloWorldApplicationRunner and outputs our “Hello, World!” message to standard out. The TaskLifecycleListener records the start of the task and the end of the task in the repository.

The main method

The main method serves as the entry point to any java application. Our main method delegates to Spring Boot’s SpringApplication class.

The ApplicationRunner

Spring includes many ways to bootstrap an application’s logic. Spring Boot provides a convenient method of doing so in an organized manner through its *Runner interfaces (CommandLineRunner or ApplicationRunner). A well behaved task can bootstrap any logic by using one of these two runners.

The lifecycle of a task is considered from before the *Runner#run methods are executed to once they are all complete. Spring Boot lets an application use multiple *Runner implementations, as does Spring Cloud Task.

Any processing bootstrapped from mechanisms other than a CommandLineRunner or ApplicationRunner (by using InitializingBean#afterPropertiesSet for example) is not recorded by Spring Cloud Task.

Running the Example

At this point, our application should work. Since this application is Spring Boot-based, we can run it from the command line by using $ ./mvnw spring-boot:run from the root of our application, as shown (with its output) in the following example:

$ mvn clean spring-boot:run
....... . . .
....... . . . (Maven log output here)
....... . . .

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.1)

2024-01-04T10:07:01.102-06:00  INFO 18248 --- [helloWorld] [           main] i.s.d.helloworld.HelloworldApplication   : Starting HelloworldApplication using Java 21.0.1 with PID 18248 (/Users/dashaun/fun/dashaun/spring-cloud-task/helloworld/target/classes started by dashaun in /Users/dashaun/fun/dashaun/spring-cloud-task/helloworld)
2024-01-04T10:07:01.103-06:00  INFO 18248 --- [helloWorld] [           main] i.s.d.helloworld.HelloworldApplication   : No active profile set, falling back to 1 default profile: "default"
2024-01-04T10:07:01.526-06:00  INFO 18248 --- [helloWorld] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-01-04T10:07:01.626-06:00  INFO 18248 --- [helloWorld] [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:3ad913f8-59ce-4785-bf8e-d6335dff6856 user=SA
2024-01-04T10:07:01.627-06:00  INFO 18248 --- [helloWorld] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2024-01-04T10:07:01.633-06:00 DEBUG 18248 --- [helloWorld] [           main] o.s.c.t.c.SimpleTaskAutoConfiguration    : Using org.springframework.cloud.task.configuration.DefaultTaskConfigurer TaskConfigurer
2024-01-04T10:07:01.633-06:00 DEBUG 18248 --- [helloWorld] [           main] o.s.c.t.c.DefaultTaskConfigurer          : No EntityManager was found, using DataSourceTransactionManager
2024-01-04T10:07:01.639-06:00 DEBUG 18248 --- [helloWorld] [           main] o.s.c.t.r.s.TaskRepositoryInitializer    : Initializing task schema for h2 database
2024-01-04T10:07:01.772-06:00 DEBUG 18248 --- [helloWorld] [           main] o.s.c.t.r.support.SimpleTaskRepository   : Creating: TaskExecution{executionId=0, parentExecutionId=null, exitCode=null, taskName='helloWorld', startTime=2024-01-04T10:07:01.757268, endTime=null, exitMessage='null', externalExecutionId='null', errorMessage='null', arguments=[]}
2024-01-04T10:07:01.785-06:00  INFO 18248 --- [helloWorld] [           main] i.s.d.helloworld.HelloworldApplication   : Started HelloworldApplication in 0.853 seconds (process running for 1.029)
Hello, World!
2024-01-04T10:07:01.794-06:00 DEBUG 18248 --- [helloWorld] [           main] o.s.c.t.r.support.SimpleTaskRepository   : Updating: TaskExecution with executionId=1 with the following {exitCode=0, endTime=2024-01-04T10:07:01.787112, exitMessage='null', errorMessage='null'}
2024-01-04T10:07:01.799-06:00  INFO 18248 --- [helloWorld] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2024-01-04T10:07:01.806-06:00  INFO 18248 --- [helloWorld] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

....... . . .
....... . . . (Maven log output here)
....... . . .

The preceding output has three lines that are of interest to us here:

  • SimpleTaskRepository logged the creation of the entry in the TaskRepository.

  • The execution of our ApplicationRunner, demonstrated by the “Hello, World!” output.

  • SimpleTaskRepository logs the completion of the task in the TaskRepository.

A simple task application can be found in the samples module of the Spring Cloud Task Project here.