Running Background Tasks In DropWizard with Guava
panos Feb. 13, 2015Recently, 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.
Kountanis