Quarkus JBeret

The Quarkus JBeret Extension adds support for JSR-352 Batch Applications for the Java Platform. JBeret is an implementation of the JSR-352.

Installation

If you want to use this extension, you need to add the io.quarkiverse.jberet:quarkus-jberet extension first to your build file:

pom.xml
<dependency>
    <groupId>io.quarkiverse.jberet</groupId>
    <artifactId>quarkus-jberet</artifactId>
    <version>{project-version}</version>
</dependency>
build.gradle
implementation("io.quarkiverse.jberet:quarkus-jberet:{project-version}")

Recommended Quarkus version: 3.28.1 or higher

The Batch API and Runtime will be available out of the box. Please refer to the Java Batch documentation, or the JBeret documentation to learn more about Batch Applications.

Simplified Configuration

The Batch API requires the @BatchProperty annotation to inject the specific configuration from the batch definition file. Instead, you can use the @ConfigProperty annotation, which is used to inject configuration properties in Quarkus using the MicroProfile Config API and keep consistency:

@Inject
@BatchProperty(name = "job.config.name")
String batchConfig;

// This is equivalent to @BatchProperty injection
@ConfigProperty(name = "job.config.name")
Optional<String> mpConfig;

Although, there is a slight limitation: since job configuration is mostly dynamic and only injected on job execution, Quarkus may fail to start due to invalid configuration (cannot find the Job configuration values). In this case, configuration injection points with the @ConfigProperty annotation must set a default value or use an Optional.

CDI Beans

The Batch APIs JobOperator and JobRepository are available as CDI beans, so they can be injected directly into any code:

@Inject
JobOperator jobOperator;
@Inject
JobRepository jobRepository;

void start() {
    long executionId = jobOperator.start("batchlet", new Properties());
    JobExecution jobExecution = jobRepository.getJobExecution(executionId);
}

A specific Quarkus implementation is available in QuarkusJobOperator, which can be also injected directly:

@Inject
QuarkusJobOperator jobOperator;

void start() {
    Job job = new JobBuilder("programmatic")
            .step(new StepBuilder("programmaticStep")
                    .batchlet("programmaticBatchlet")
                    .build())
            .build();

    long executionId = jobOperator.start(job, new Properties());
    JobExecution jobExecution = jobOperator.getJobExecution(executionId);
}

With QuarkusJobOperator it is possible to define and start programmatic Jobs, with the JBeret Programmatic Job Definition.

It is possible to provide a Job definition via a CDI producer (instead of using XML):

@ApplicationScoped
public static class JobProducer {
    @Produces
    @Named
    public Job job() {
        return new JobBuilder("job")
                .step(new StepBuilder("step").batchlet("batchlet", new String[] {}).build())
                .build();
    }
}

A Job registered with CDI will be named by the @Named#value attribute or by the method name. The @Named annotation is required regardless. This is the named used by JobOperator to locate and execute a Job.

Scheduler

The JBeret Scheduler is integrated out of the box in this extension.

To schedule a Job execution, please refer to the quarkus.jberet.job."job-name".cron and quarkus.jberet.job."job-name".params."param-key" configurations.

A Job can also be scheduled programmatically, using the JobScheduler API and the Quarkus startup event:

@ApplicationScoped
public class Scheduler {
    @Inject
    JobScheduler jobScheduler;

    void onStart(@Observes StartupEvent startupEvent) {
        final JobScheduleConfig scheduleConfig = JobScheduleConfigBuilder.newInstance()
                .jobName("scheduler")
                .initialDelay(0)
                .build();

        jobScheduler.schedule(scheduleConfig);
    }
}

The JobScheduler does not support persistent schedules.

REST API

The JBeret REST is integrated as separate extension that can be easily added to your build file:

pom.xml
<dependency>
    <groupId>io.quarkiverse.jberet</groupId>
    <artifactId>quarkus-jberet-rest</artifactId>
    <version>{project-version}</version>
</dependency>
build.gradle
implementation("io.quarkiverse.jberet:quarkus-jberet-rest:{project-version}")

The JBeret REST API, provides REST resources to several operations around the Batch API: starting and stopping jobs, querying the status of a job, schedule a job, and more. The extension includes a REST client to simplify the REST API calls:

@Inject
BatchClient batchClient;

void start() throws Exception {
    JobExecutionEntity jobExecutionEntity = batchClient.startJob("batchlet", new Properties());
}

Example Applications

Example applications can be found inside the integration-tests folder:

  • chunk - A simple Job that reads, processes, and stores data from a file.

  • jdbc-repository - A Job that uses a jdbc datasource to store JBeret and Job metadata.

  • scheduler - Schedule a Job to run every 10 seconds

Or take a look into the World of Warcraft Auctions - Batch Application. It downloads the World of Warcraft Auction House data and provides statistics about items prices.

Native Image Limitations

The Quakus JBeret Extension fully supports the Graal VM Native Image with the following exceptions:

  • Scripting Languages. While Javascript should work, it is unlikely that other scripting languages will be supported in Graal via JSR-223.

Extension Configuration Reference

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property

Type

Default

A regex pattern of Job names to exclude.

Environment variable: QUARKUS_JBERET_JOBS_INCLUDES

list of Pattern

A regex pattern of Job names to include.

Environment variable: QUARKUS_JBERET_JOBS_EXCLUDES

list of Pattern

The repository type to store JBeret and Job data. A `jdbc`jdbc type requires a JDBC datasource.

Environment variable: QUARKUS_JBERET_REPOSITORY_TYPE

string

in-memory

The datasource name for the JBeret Repository.

Environment variable: QUARKUS_JBERET_REPOSITORY_JDBC_DATASOURCE

string

Custom DDL file resource for JBeret tables creation; if using custom table names please also set sql-filename property to propagate table names.

Environment variable: QUARKUS_JBERET_REPOSITORY_JDBC_DDL_FILE

string

Custom queries to be used to query JBeret tables; this is mandatory if custom table names are used in custom DDL filename.

Environment variable: QUARKUS_JBERET_REPOSITORY_JDBC_SQL_FILE

string

JBeret tables name prefix.

Environment variable: QUARKUS_JBERET_REPOSITORY_JDBC_DB_TABLE_PREFIX

string

IJBeret tables name suffix.

Environment variable: QUARKUS_JBERET_REPOSITORY_JDBC_DB_TABLE_SUFFIX

string

The maximum number of threads allowed to be executed.

Environment variable: QUARKUS_JBERET_MAX_ASYNC

int

The Job schedule in Cron format, see cron.

Environment variable: QUARKUS_JBERET_JOB__JOB__CRON

string

The Job parameters.

Environment variable: QUARKUS_JBERET_JOB__JOB__PARAMS__PARAMS_

Map<String,String>