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.