Trying a Hello World Job with Spring Batch 6 / Spring Boot 4, where the DB is no longer required by default
Previously we explained how to launch a Spring Batch job without using a DB on Spring Batch 5 / Spring Boot 3, but in Spring Batch 6 / Spring Boot 4 a DB is not required by default (link).
In this article we will re‑implement the Hello World job that was implemented in the previous article.
Note
This article was verified with Spring Batch 6.0.2 / Spring Boot 4.0.2.
Creating a Spring Boot Project
Create a Spring Batch project with the following command.
curl https://start.spring.io/starter.tgz \
-d type=maven-project \
-d artifactId=hello-spring-batch \
-d baseDir=hello-spring-batch \
-d packageName=com.example.hello \
-d dependencies=batch,native \
-d applicationName=HelloSpringBatchApplication | tar -xzvf -
cd hello-spring-batch
Defining the Job
Define the Job as follows. When a Tasklet is specified without setting a PlatformTransactionManager, a ResourcelessTransactionManager will be used.
cat <<EOF > src/main/java/com/example/hello/JobConfig.java
package com.example.hello;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.job.Job;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.Step;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.infrastructure.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class JobConfig {
private final Logger log = LoggerFactory.getLogger(JobConfig.class);
private final JobRepository jobRepository;
public JobConfig(JobRepository jobRepository) {
this.jobRepository = jobRepository;
}
@Bean
@StepScope
public Tasklet helloTasklet() {
return (contribution, chunkContext) -> {
log.info("Hello World!");
return RepeatStatus.FINISHED;
};
}
@Bean
public Step step1(Tasklet helloTasklet) {
return new StepBuilder("step1", jobRepository).tasklet(helloTasklet)
.build();
}
@Bean
public Job job1(Step step1) {
return new JobBuilder("job1", jobRepository).start(step1).build();
}
}
EOF
Execution
Build and run with the following commands.
./mvnw clean package -DskipTests
java -jar target/hello-spring-batch-0.0.1-SNAPSHOT.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v4.0.2)
2026-01-24T10:32:48.592+09:00 INFO 98071 --- [demo] [ main] c.e.hello.HelloSpringBatchApplication : Starting HelloSpringBatchApplication v0.0.1-SNAPSHOT using Java 25.0.1 with PID 98071 (/private/tmp/hello-spring-batch/target/hello-spring-batch-0.0.1-SNAPSHOT.jar started by toshiaki in /private/tmp/hello-spring-batch)
2026-01-24T10:32:48.594+09:00 INFO 98071 --- [demo] [ main] c.e.hello.HelloSpringBatchApplication : No active profile set, falling back to 1 default profile: "default"
2026-01-24T10:32:48.811+09:00 INFO 98071 --- [demo] [ main] c.e.hello.HelloSpringBatchApplication : Started HelloSpringBatchApplication in 0.359 seconds (process running for 0.532)
2026-01-24T10:32:48.813+09:00 INFO 98071 --- [demo] [ main] o.s.b.b.a.JobLauncherApplicationRunner : Running default command line with: []
2026-01-24T10:32:48.835+09:00 INFO 98071 --- [demo] [ main] o.s.b.c.l.s.TaskExecutorJobLauncher : Job: [SimpleJob: [name=job1]] launched with the following parameters: [{}]
2026-01-24T10:32:48.837+09:00 INFO 98071 --- [demo] [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [step1]
2026-01-24T10:32:48.840+09:00 DEBUG 98071 --- [demo] [ main] s.b.i.s.t.ResourcelessTransactionManager : Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2026-01-24T10:32:48.841+09:00 INFO 98071 --- [demo] [ main] com.example.hello.JobConfig : Hello World!
2026-01-24T10:32:48.841+09:00 DEBUG 98071 --- [demo] [ main] s.b.i.s.t.ResourcelessTransactionManager : Initiating transaction commit
2026-01-24T10:32:48.842+09:00 DEBUG 98071 --- [demo] [ main] s.b.i.s.t.ResourcelessTransactionManager : Committing resourceless transaction on [org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager$ResourcelessTransaction@58b71ceb]
2026-01-24T10:32:48.842+09:00 INFO 98071 --- [demo] [ main] o.s.batch.core.step.AbstractStep : Step: [step1] executed in 4ms
2026-01-24T10:32:48.843+09:00 INFO 98071 --- [demo] [ main] o.s.b.c.l.s.TaskExecutorJobLauncher : Job: [SimpleJob: [name=job1]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 5ms
It started successfully.
Running with GraalVM Native Image
Creating a native image is also straightforward. To run with GraalVM Native Image, build and execute with the following commands. On my machine (Mac M4 Max, 128 GB RAM) the build finished in about 20 seconds.
./mvnw native:compile -Pnative -DskipTests
./target/hello-spring-batch
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v4.0.2)
2026-01-24T10:35:01.048+09:00 INFO 98324 --- [demo] [ main] c.e.hello.HelloSpringBatchApplication : Starting AOT-processed HelloSpringBatchApplication using Java 25.0.1 with PID 98324 (/private/tmp/hello-spring-batch/target/hello-spring-batch started by toshiaki in /private/tmp/hello-spring-batch)
2026-01-24T10:35:01.048+09:00 INFO 98324 --- [demo] [ main] c.e.hello.HelloSpringBatchApplication : No active profile set, falling back to 1 default profile: "default"
2026-01-24T10:35:01.052+09:00 INFO 98324 --- [demo] [ main] c.e.hello.HelloSpringBatchApplication : Started HelloSpringBatchApplication in 0.01 seconds (process running for 0.019)
2026-01-24T10:35:01.052+09:00 INFO 98324 --- [demo] [ main] o.s.b.b.a.JobLauncherApplicationRunner : Running default command line with: []
2026-01-24T10:35:01.052+09:00 INFO 98324 --- [demo] [ main] o.s.b.c.l.s.TaskExecutorJobLauncher : Job: [SimpleJob: [name=job1]] launched with the following parameters: [{}]
2026-01-24T10:35:01.052+09:00 INFO 98324 --- [demo] [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [step1]
2026-01-24T10:35:01.052+09:00 DEBUG 98324 --- [demo] [ main] s.b.i.s.t.ResourcelessTransactionManager : Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2026-01-24T10:35:01.052+09:00 INFO 98324 --- [demo] [ main] com.example.hello.JobConfig : Hello World!
2026-01-24T10:35:01.052+09:00 DEBUG 98324 --- [demo] [ main] s.b.i.s.t.ResourcelessTransactionManager : Initiating transaction commit
2026-01-24T10:35:01.052+09:00 DEBUG 98324 --- [demo] [ main] s.b.i.s.t.ResourcelessTransactionManager : Committing resourceless transaction on [org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager$ResourcelessTransaction@7eb43831]
2026-01-24T10:35:01.052+09:00 INFO 98324 --- [demo] [ main] o.s.batch.core.step.AbstractStep : Step: [step1] executed in
2026-01-24T10:35:01.052+09:00 INFO 98324 --- [demo] [ main] o.s.b.c.l.s.TaskExecutorJobLauncher : Job: [SimpleJob: [name=job1]] completed with the following parameters: [{}] and the following status: [COMPLETED] in
This also ran without any issues.
We introduced how to create and run a Job without using a database in Spring Batch 6 / Spring Boot 4.
Many people may have wanted to use the Spring Batch framework but disliked handling the metadata DB, and therefore implemented batch processing with CommandLineRunner and similar approaches. This is good news for them. Spring Batch 6 brings major improvements to the infrastructure (though there are many breaking changes...).