Tired of Spring Overhead? Try Dropwizard for Your Next Java Microservice
You'll learn how to set up your first Dropwizard project, create a RESTful API, and run it with an embedded Jetty server — all using minimal boilerplate.
Join the DZone community and get the full member experience.
Join For FreeInstead of a monolith, build your first Java microservice with Dropwizard.
Hello, my fellow programmers! I’m positive you do not want to read another complex article on how to build Java microservices. We are going to take a look at Dropwizard today. It is fairly convenient as it has everything loaded in it, i.e., Jetty, Jersey, Jackson, etc., and also provides you with the ability to set your business logic without the boilerplates.
The Best Parts About Using Dropwizard for Microservices
Let’s be clear on a few things: Dropwizard is not a new framework that was made yesterday. It has already undergone testing. It's an impressive supplement that puts together many libraries. To put it another way: Imagine trying to build a race car.
You required welding parts, but some pre-tuned engines were given to you instead. That is exactly what Dropwizard is.
What’s good about Dropwizard:
- Everything you need is built into it: HTTP Server (Jetty), REST (Jersey) , JSON (Jackson), and everything else comes pre-installed and wired up.
- Your service will run like a fat JAR, with an embedded server, aka zero app server drama.
- You can deploy it anywhere Java is supported.
- You don’t have to rely on anyone to get it ready to use because it can come equipped with health checks, metrics, and logging — features that loyal Dropwizard fans have come to love.
In my experience, Dropwizard is always the best choice if you are looking for something to ship fast while keeping operations happy. From my experience, Dropwizard is particularly impressive when speed is critical and operational overhead needs to be minimal. There is no yak-shaving with dependency management, a-spring with XML configurations.
Prerequisite and Project Set up
Let's first verify something. Having Java 11+ (or the Dropwizard version you’re targeting) and Maven is a prerequisite. After that, you can do the following:
- My preferred way is to utilize the Maven Archetype. I believe this is the best way to scaffold a project because it does not require any manual arrangement of directories.
mvn archetype:generate \
-Dfilter=io.dropwizard.archetypes:java-simple
- Manual Maven project (for those who want to learn the insides): Create a standard Maven JAR project (eg, com.example:hello-world:1.0-SNAPSHOT).
Add the following to your pom.xml:
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>4.0.2</version>
</dependency>
That single dependency pulls in Jetty, Jersey, Jackson, Metrics, Logback, and more for you.
Uber JAR Packaging: Make sure you’re building a “fat JAR” so everything’s bundled. The archetype sets up Maven Shade for you, but if you’re doing it manually, add the Maven Shade Plugin under <build>
in your POM to merge dependencies into target/your-app.jar.
Once everything’s fine with Maven, we can take a look at the configuration.
Configuration: Your Configuration Class and YAML
Setting up Dropwizard applications is easier with YAML, which is preferred over XML. There are no nested structures here! Additionally, the program assumes config.yml
exists with a set of things like ports, log levels, database URL, and additional required configurations (Dropwizard Configuration Reference).
Below is a simple illustration:
server:
applicationConnectors:
- type: http
port: 8080
adminConnectors:
- type: http
port: 8081
logging:
level: INFO
Dropwizard integrates the aforementioned YAML within a Java class that has been defined previously, extending io.dropwizard.Configuration
. Even if custom configurations are not needed at the beginning, a stub would always be required:
public class HelloWorldConfiguration extends Configuration {
// Add @JsonProperty fields here as needed...
}
As you append details like databaseUrl and template, you will also add annotation fields with @JsonProperty
(and validation facets like @NotEmpty
) so that Dropwizard can transform the YAML into a POJO class automatically (Dropwizard Configuration Reference).
The Main Event: Other Application and Resource Classes
That’s alright, it’s time to put everything together and make things functional.
The Application Class
Your entry point extends: Application<T>:
public class HelloWorldApplication extends Application<HelloWorldConfiguration> {
public static void main(String[] args) throws Exception {
new HelloWorldApplication().run(args);
}
@Override
public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
// Add bundles or commands here if needed
}
@Override
public void run(HelloWorldConfiguration config, Environment env) {
env.jersey().register(new HelloWorldResource());
}
}
main
initiates Dropwizard.initialize
is where all of the bundles (once again, think of bundles as databases, migrations) get wired in.run
provides you withEnvironment
, allowing you to register additional resources. These can include:- Jersey components (
env.jersey().register(...)
) - Health check (
env.healthChecks().register(...)
) - Tasks, servlets, filters, etc
- Jersey components (
Example Resource
This is our “hello” endpoint.
@Path("/hello")
@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldResource {
@GET
public Map<String, String> sayHello() {
return Collections.singletonMap("message", "Hello, World!");
}
}
@Path
specifies what the endpoint path will be.@Produces
is how Dropwizard (using Jackson) instructs it to render JSON.- In this case, your method returns a Map. It is safe to assume that Jackson will take care of it TalentConnect.
If you want to customize the response even further, you could return a custom POJO that is stronger in type, such as HelloMessage.
Building, Running, and Testing
Now it's time to see everything in action.
mvn clean package
- This produces a JAR-like
target/hello-world-1.0-SNAPSHOT.jar
. - Config file: Create
config.yml
in your project root (or resources). You could leave it as anempty{}
as well, but personally, I prefer to specify ports because it makes everything predictable.
Run the service:
java -jar target/hello-world-1.0-SNAPSHOT.jar server config.yml
You will notice logs about Jetty starting on app port 8080 and admin port 8081. Stack Overflow JavaDoc.
Test with cURL or browser:
curl http://localhost:8080/hello
# {"message":"Hello, World!"}
-
For admin end points: You can go to http://localhost:8081/healthcheck and http://localhost:8081/metrics to view some ready-built health checks (including a deadlocks check) and metric data (Dropwizard Core).
If you need some automated testing, Dropwizard does ship with a dropwizard-testing module, so you could spin up your app in a random port and make HTTP calls to it with real requests made against it — super useful for integration tests (Testing Dropwizard).
Step Up: Health Checks, Databases, Metrics, and More
Basic functions are taken care of, but with real applications, there's more to do.
Database Connection
Dropwizard has modules for Hibernate, JDBI, and JDBC. For example, Load:
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-jdbi3</artifactId>
<version>${dropwizard.version}</version>
</dependency>
Then, set your data source in YAML and bootstrap a DBI in either initialize or run. It even wires a health check to ping your database automatically (dropwizard/dropwizard-health — GitHub).
Custom Health Checks
Want to make your own self-tests? Extend com.codahale.metrics.health.HealthCheck:
public class DatabaseHealthCheck extends HealthCheck {
private final Database db;
//...
@Override
protected Result check() throws Exception {
return db.ping() ? Result.healthy() : Result.unhealthy("DB unreachable");
}
}
Register where you need to within run()
:
- env.healthChecks().register("database", new DatabaseHealthCheck(db));
Viewing your custom checks, plus all defaults, is done through your admin port’s /healthcheck endpoint (Health Checks — Dropwizard Metrics).
Metrics and Monitoring
Measure, don't just log. With a MetricRegistry, count events, time methods, and track histograms. The admin /metrics endpoint serves JSON metrics that can be effortlessly piped into Prometheus or Graphite (Getting Started — Dropwizard).
Bundles and Extensions
Looking for templating, static assets, or authentication? Check out bundles for:
- Freemarker/Mustache templating
- OAuth and JWT auth
- Redis
- Liquibase
- Hibernate
With Dropwizard Bundles, plugins that hook into initialize, scattering your code with boilerplate, is avoided.
Security and HTTPS
Basic Authentication and OAuth can be configured with io.dropwizard.auth
modules. Also, confirm HTTPS connections with applicationConnectors
restrictions in YAML. It is as simple as the phrase ‘Plug-and-Play.’
From Hello World to Production-Ready: Now That’s a Wrap
So, what knowledge do we have now?
- Dropwizard glues together Jetty, Jersey, Jackson, Metrics, Logback, and more into a lean, coherent stack (Home — Dropwizard).
- YAML config + a Configuration subclass keeps setup clean and consistent (Dropwizard Configuration Reference).
- Your Application and resource classes handle wiring, while admin endpoints give you health and metrics out-of-the-box (Getting Started — Dropwizard, Dropwizard Core).
- It’s production-ready by default, yet flexible enough to grow with bundles, extensions, and custom tweaks.
Now that you’ve got a working Dropwizard service, I would recommend that you do the following:
- Persist data: With the ability to put a real CRUD implementation, bore down on Hibernate or JDBI.
- Custom checks: Set checks related to the health of services your API heavily relies on.
- Instrument: Track key focus spots regarding performance with the surface the set of
@Timed
,@Metered
, and@Counted
. - Secure: Depending on preference, enable basic auth, OAuth, and JWT for security.
Deploy: Use your preferred cloud for deployment, Dockerize your Fat Jar, and run it on Kubernetes.
Opinions expressed by DZone contributors are their own.
Comments