Running Background Tasks In DropWizard with Guava

panos Feb. 13, 2015

Recently, I wrote a RESTful web service in Java 8 using Dropwizard. I like Dropwizard's simple, lightweight, getting-things-done attitude. In this post I will demonstrate how to combine Dropwizard's Managed objects with Guava's concurrency primitives to write simple background tasks for your service

The Specifics

Guava provides com.google.common.util.concurrent.AbstractScheduledService, an abstraction for a periodic task that runs on its own background thread at user-defined intervals and can be started and stopped from the main thread. Here is one that logs to the console every 5 seconds

package com.kountanis.dwex1.core;

import com.google.common.util.concurrent.AbstractScheduledService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

public class ConsoleLoggingScheduledTask extends AbstractScheduledService {

    private final Logger LOGGER = LoggerFactory.getLogger(ConsoleLoggingScheduledTask.class);

    @Override
    protected void runOneIteration() throws Exception {
        LOGGER.info("runOneIteration");
    }

    @Override
    protected AbstractScheduledService.Scheduler scheduler() {
        return AbstractScheduledService.Scheduler.newFixedRateSchedule(0, 5, TimeUnit.SECONDS);
    }
}

Dropwizard provides the Managed interface for objects that need to be started and stopped when the application instance is started or stopped. It is easy to create a container/adapter for an AbstractScheduledService subclass like the one above and have it managed by Dropwizard.

package com.kountanis.dwex1.core;

import com.google.common.util.concurrent.AbstractScheduledService;
import io.dropwizard.lifecycle.Managed;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ManagedPeriodicTask implements Managed {

    private final Logger LOGGER = LoggerFactory.getLogger(ManagedPeriodicTask.class);
    private final AbstractScheduledService periodicTask;

    public ManagedPeriodicTask(AbstractScheduledService periodicTask) {
        this.periodicTask = periodicTask;
    }

    @Override
    public void start() throws Exception {
        periodicTask.startAsync().awaitRunning();
    }

   @Override
   public void stop() throws Exception {
       periodicTask.stopAsync().awaitTerminated();
   }
}

Then on the run method of our Application subclass, we can do the following

package com.kountanis.dwex1;

import io.dropwizard.Application;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import com.kountanis.dwex1.core.ConsoleLoggingScheduledTask;
import com.kountanis.dwex1.core.ManagedPeriodicTask;
import io.dropwizard.lifecycle.Managed;

public class DwGuavaBackgroundTasksApplication extends Application<DwGuavaBackgroundTasksConfiguration> {

    public static void main(final String[] args) throws Exception {
        new DwGuavaBackgroundTasksApplication().run(args);
    }

    @Override
    public String getName() {
        return "DwGuavaBackgroundTasks";
    }

    @Override
    public void initialize(final Bootstrap<DwGuavaBackgroundTasksConfiguration> bootstrap) {
        // TODO: application initialization
    }

    @Override
    public void run(final DwGuavaBackgroundTasksConfiguration configuration,
                    final Environment environment) {
        final ConsoleLoggingScheduledTask periodicTask = new ConsoleLoggingScheduledTask();
        final Managed managedImplementer = new ManagedPeriodicTask(periodicTask);
        environment.lifecycle().manage(managedImplementer);
    }

}

So, there you have it! A simple way to create background (semi) periodic tasks that are managed (started and stopped) by dropwizard, for usages such as gossip protocols, consensus or asynchronous tasks like emailing and logging.

Back to homepage