How To: Create Dropwizard Tasks.
27 May 2014We’re big fans of the Dropwizard framework. It’s straightforward approach to services allows us to create fast and highly available systems very easily. While we’ve used a number of different Java frameworks when building out our platform, Dropwizard is quickly becoming our de-facto standard for all new services.
As we built out our new market data service, we found a need to add a task. Dropwizard’s documentation is fantastic, encompassing everything from application structure to internals and semantics, but tasks aren’t covered particularly well. We’ve submitted a pull request to improve the docs, but opted to document our learnings here as well.
The Task
is defined as an abstract class that you must subclass. The main thing to point out is the execute
method which is called when the task is invoked. Let’s define a sample task to see how it works. For this example, we’ll create a task called TruncateDatabaseTask
. First, we’ll define the class:
package com.myapp.tasks;
import io.dropwizard.servlets.tasks.Task;
public class TruncateDatabaseTask extends Task {
}
Dropwizard requires that each task have a name. The name has a special purpose as it’s also used to compose the path that the task is accessible from within Dropwizard. The Task
defines a basic constructor that we can use, but let’s define it explicity via a constructor of our own (more on this later). We’ll also implement the execute
method even though we’re not doing anything yet.
package com.myapp.tasks;
import io.dropwizard.servlets.tasks.Task;
public class TruncateDatabaseTask extends Task {
public TruncateDatabaseTask() {
super("truncate")
}
@Override
public void execute(ImmutableMultimap<String, String> parameters, PrintWriter output) throws Exception {
}
}
At this point, we have a fully composed Dropwizard task. Now we just need to add it to our application:
public void run(MyAppConfiguration config, Environment env) throws Exception {
// tasks
env.admin().addTask(new TruncateDatabaseTask());
}
Start your application, and you’ll see that the task is now registered alongside the garbage collection task that Dropwizard adds automatically
INFO [2014-05-16 19:15:35,564] io.dropwizard.setup.AdminEnvironment: tasks =
POST /tasks/gc (io.dropwizard.servlets.tasks.GarbageCollectionTask)
POST /tasks/truncate (com.myapp.tasks.TruncateDatabaseTask)
Let’s make this a more practical example. The value of defining a constructor is that we can dependency inject anything we need into the task from our Dropwizard application:
package com.myapp.tasks;
import io.dropwizard.servlets.tasks.Task;
public class TruncateDatabaseTask extends Task {
private Database database;
public TruncateDatabaseTask(Database database) {
super("truncate")
this.database = database;
}
@Override
public void execute(ImmutableMultimap<String, String> parameters, PrintWriter output) throws Exception {
this.database.truncate();
}
}
Most of our Dropwizard tasks look a lot like the one above. We found these tasks valuable as schedulable components of our application without building custom scripts to tie back to the current runtime. If you use Sinatra or Express to build service APIs definitely check out Dropwizard.
This post has been cross-posted to the Tradier Developer Blog, for more posts like this, you may want to follow our posts there as well!