An introduction to JobRunr, a distributed background job scheduler

Share
  • February 23, 2022

About JobRunr

JobRunr is a library that you can embed in your existing application to enable the scheduling of background jobs. A job can be a short or long-lived process that runs in a background thread. A typical use case is to offload a long-running process from a web request to a background thread resulting in a better experience for the end user.

Some JobRunr features

JobRunr analyzes and serializes all your jobs as readable JSON to either a SQL or NoSQL database. If too many background jobs are created, you can scale horizontally by spinning up more instances of your application. As the jobs are stored as JSON in a central database, the workload can be spread over multiple JVM’s. As soon as a new instance of your application is started, JobRunr automatically starts processing jobs. To make sure that the same job is not being processed multiple times, it makes use of optimistic locking. Nobody likes cleaning, that’s why JobRunr is also self-maintaining – all succeeded jobs will automatically be deleted after a configurable amount of time.

Sometimes you don’t want to run a job immediately – you need it to run tomorrow (e.g. a day after a user registered) or you might want to run a recurring job. All of this is supported out-of-the-box.

Life doesn’t always go perfect and things go down – if a background job fails (e.g. due to a dependent API that is down), it is automatically retried by means of a smart backoff policy.

JobRunr also comes with a built-in dashboard that allows you to monitor all jobs.

SEE ALSO: Safer Internet Day 2022: A view from the experts

How to create a job

You can create background jobs easily:

  • by means of a Java 8 lambda where you can reuse any of your existing services
  • or by means of a JobRequest and a JobRequestHandler

In this article, you will learn how to schedule a simple background job by means of a Java 8 lambda and a JobRequest.

Setup

To use JobRunr in Spring, you first need to add the dependency to the `jobrunr-spring-boot-starter` in the Maven pom.xml.

Maven dependency

<dependency>
    <groupId>org.jobrunr</groupId>
    <artifactId>jobrunr-spring-boot-starter</artifactId>
    <version>4.0.8</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.6.1</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>2.1.210</version>
</dependency>

Here, you’re adding 3 dependencies:

  • the `jobrunr-spring-boot-starter` that enables the integration between JobRunr and Spring Boot.
  • the `spring-boot-starter-data-jpa` is not really necessary, but it helps as it automatically creates a DataSource for you.
  • the `h2` database that you will be using to store all the job state

JobRunr configuration

JobRunr by defaults only enables the job scheduler. As the background job server and the dashboard are opt-in only, you need to add some properties to the Spring `application.properties`:

 

org.jobrunr.background-job-server.enabled=true
org.jobrunr.dashboard.enabled=true

The first property tells JobRunr to enable the background job server so that jobs will actually be processed. The second property enables the JobRunr dashboard.

Job Storage

By default, JobRunr will try to use your existing `javax.sql.DataSource` or any of the supported NoSQL clients to store all job-related information. As you’ve added the dependency to `spring-boot-starter-data-jpa`, a DataSource has been automatically created, so you’re all set.

Usage

By means of a Job Lambda

To use JobRunr with a Job Lambda, you first need to inject some Spring Beans:

@Inject
private JobScheduler jobScheduler;

@Inject
private SampleJobService sampleJobService;

The <code>`JobScheduler`</code> is a bean provided by JobRunr and allows you to enqueue or schedule new jobs.

The <code>`SampleJobService`</code> can be any Spring bean on which you want to invoke a method that can take some time to process. It can also be a method where you want to add some extra resilience as JobRunr will automatically retry the method in case of an exception.

Now, you can easily create a job:

 

jobScheduler.enqueue(() -> sampleJobService.executeSampleJob());

Passing arguments is also possible:

jobScheduler.enqueue(() -> sampleJobService.executeSampleJob("Hello! I will be executed in a Background process, perhaps even a different JVM"));

The above two calls will make sure that JobRunr analyses the given lambda, it will be stored in the database and the next available dedicated worker will process it.

By means of a JobRequest and a JobRequestHandler

You can also create a job by means of a JobRequest. This will involve the creation of a `JobRequest` a `JobRequestHandler` and enqueueing the actual job.

 

public class SampleJobRequest implements JobRequest {

    private final String input;

    // needed for deserialization by Jackson
    protected TestJobRequest() {
        this(null);
    }

    public TestJobRequest(String input) {
        this(input);
    }

    @Override
    public Class<SampleJobRequestHandler> getJobRequestHandler() {
        return SampleJobRequestHandler.class;
    }

    public String getInput() {
        return input;
    }
}

Here, you first create a `SampleJobRequest` that can take arguments you have available when you create the job. The `JobRequest` also needs to implement one method called `getJobRequestHandler`. This method must return the class that will contain your actual business logic / background job.

Next, you need to create a `SampleJobRequestHandler` that will contain your actual background job and business logic. To do so, one `run` method must be implemented. When the background job runs, it is provided with the input you created above.

 

@Service
public static class SampleJobRequestHandler implements JobRequestHandler<SampleJobRequest> {

    @Override
    public void run(SampleJobRequest jobRequest) {
        System.out.println("Running sample job request in background: " + jobRequest.getInput());
    }
}

Now there is only one thing left: enqueueing the job. You can do this as follows:

@Inject
private JobRequestScheduler jobRequestScheduler;

...
        
jobRequestScheduler.enqueue(new SampleJobRequest("Hello")); 

SEE ALSO: Evolving Java Runtimes for a Cloud-Centric World

Dashboard

JobRunr comes with a built-in dashboard that allows you to monitor all your jobs.

Conclusion

After completing this article, you have created your first background job using Spring Boot and JobRunr. The important detail here is that you can create a background job with a minimal amount of code that can even run in a different JVM than where you scheduled it. Here, we only briefly touched one feature of JobRunr, however, it offers a lot more, like scheduled jobs, recurring jobs, and more.

The complete source code for this article is available on Github.

To learn more, visit JobRunr on Github.

The post An introduction to JobRunr, a distributed background job scheduler appeared first on JAXenter.

Source : JAXenter