Dropwizard is an open source Java framework for the rapid development of REST APIs. Dropwizard is kind of ecosystem which contains all the dependencies (such as Jersey, jackson or jetty) bundled into single package or can be added as separate module. If you are not using dropwizard, you will end up collecting all dependencies yourself and it often results into class loading issues due to version mismatch between various java libraries. Dropwizard solve this problem for you, and pulls together stable, mature libraries into a simple, light-weight package that lets you focus on getting things done. Let’s learn to use dropwizard to build REST APIs – step by step.
Table of Contents Libraries included inside dropwizard Setup dropwizard with maven Create REST Application Class Create REST Resource and APIs Build Resource Representations Request Validation Verify REST APIs
Libraries included inside dropwizard
Once you include dropwizard into your project, you get following libraries added to your classpath.
- Jersey – For building RESTful web applications.
- Jetty – Dropwizard uses the Jetty HTTP library to embed an HTTP server directly into your project.
- Jackson – For object to/from JSON conversion. It allows to export your domain models directly with JAXB annotations.
- Guava – highly optimized immutable data structures to speedup development.
- Logback and SLF4j – for performant and flexible logging.
- Hibernate Validator – an easy declarative framework for validating user input and generating helpful and i18n-friendly error messages.
- Apache HTTPClient – For both low- and high-level interaction with other web services.
- JDBI – the most straightforward way to use a relational database with Java.
- Liquidbase – to keep your database schema in check throughout your development and release cycle.
- FreeMarker – templating systems.
- Mustache – simple templating systems for more user-facing applications.
- Joda Time – very complete and sane library for handling dates and times.
Setup dropwizard with maven
Our project will be based on the maven-archetype-quickstart archetype. You can create the project either using command prompt or use eclipse to create simple maven java project.
mvn archetype:generate -DgroupId=com.howtodoinjava.demo -DartifactId=DropWizardExample -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Generated project will have pom.xml
file as well. Add dropwizard dependency there.
<properties> <dropwizard.version>1.0.0</dropwizard.version> </properties> <dependencies> <dependency> <groupId>io.dropwizard</groupId> <artifactId>dropwizard-core</artifactId> <version>${dropwizard.version}</version> </dependency> </dependencies>
This will download all jar files and add them into your classpath. To add build and package support to our project, we will use the maven-shade plugin, which will allow us to package our project completely, along with its dependencies, into a single standalone JAR file (Fat/Uber JAR) that can be distributed and executed as is.
Complete pom.xml file look like this.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd; <modelVersion>4.0.0</modelVersion> <groupId>com.howtodoinjava.demo</groupId> <artifactId>DropWizardExample</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>DropWizardExample</name> <url>http://maven.apache.org</url> <properties> <dropwizard.version>1.0.0</dropwizard.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>io.dropwizard</groupId> <artifactId>dropwizard-core</artifactId> <version>${dropwizard.version}</version> </dependency> </dependencies> <build> <finalName>DropWizardExample-${version}</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.howtodoinjava.rest.App</mainClass> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
Create REST Application Class
Application class is entry point for any dropwizard application. It needs to extend the io.dropwizard.Application
class and implement the initialize(Bootstrap<Configuration>)
and run(Configuration, Environment)
methods. They prepare the runtime environment of the application.
To invoke the run method, you will need to have public static void main(String[] args) {}
method, which will invoked by java -jar
command when you run the application as jar file.
package com.howtodoinjava.rest; import io.dropwizard.Application; import io.dropwizard.Configuration; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.howtodoinjava.rest.controller.EmployeeRESTController; public class App extends Application<Configuration> { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); @Override public void initialize(Bootstrap<Configuration> b) { } @Override public void run(Configuration c, Environment e) throws Exception { LOGGER.info("Registering REST resources"); e.jersey().register(new EmployeeRESTController(e.getValidator())); } public static void main(String[] args) throws Exception { new App().run(args); } }
For executing the JAR file, we add the server argument to the command which starts the embedded HTTP Server (Jetty) to run our service.
java -jar target\DropWizardExample.jar server
Dropwizard’s embedded Jetty server will try to bind to ports 8080 and 8081 by default. Port 8080 is used by the server in order to serve incoming HTTP requests to the application, while 8081 is used by Dropwizard’s administration interface.
We have also imported the necessary Logger
and LoggerFactory
classes in order to construct a Logger instance we could use for our logging needs.
Create REST Resource and APIs
Now when you have added Application bootstrap class, you can now add REST resources containing REST APIs. In this example, I have created and employee management application – so it has APIs for create/update/delete employee records. This class will be responsible for handling HTTP requests and generating JSON responses.
As we have Jersey in our classpath, we will use it to build REST APIs.
package com.howtodoinjava.rest.controller; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import com.howtodoinjava.rest.dao.EmployeeDB; import com.howtodoinjava.rest.representations.Employee; @Path("/employees") @Produces(MediaType.APPLICATION_JSON) public class EmployeeRESTController { private final Validator validator; public EmployeeRESTController(Validator validator) { this.validator = validator; } @GET public Response getEmployees() { return Response.ok(EmployeeDB.getEmployees()).build(); } @GET @Path("/{id}") public Response getEmployeeById(@PathParam("id") Integer id) { Employee employee = EmployeeDB.getEmployee(id); if (employee != null) return Response.ok(employee).build(); else return Response.status(Status.NOT_FOUND).build(); } @POST public Response createEmployee(Employee employee) throws URISyntaxException { // validation Set<ConstraintViolation<Employee>> violations = validator.validate(employee); Employee e = EmployeeDB.getEmployee(employee.getId()); if (violations.size() > 0) { ArrayList<String> validationMessages = new ArrayList<String>(); for (ConstraintViolation<Employee> violation : violations) { validationMessages.add(violation.getPropertyPath().toString() + ": " + violation.getMessage()); } return Response.status(Status.BAD_REQUEST).entity(validationMessages).build(); } if (e != null) { EmployeeDB.updateEmployee(employee.getId(), employee); return Response.created(new URI("/employees/" + employee.getId())) .build(); } else return Response.status(Status.NOT_FOUND).build(); } @PUT @Path("/{id}") public Response updateEmployeeById(@PathParam("id") Integer id, Employee employee) { // validation Set<ConstraintViolation<Employee>> violations = validator.validate(employee); Employee e = EmployeeDB.getEmployee(employee.getId()); if (violations.size() > 0) { ArrayList<String> validationMessages = new ArrayList<String>(); for (ConstraintViolation<Employee> violation : violations) { validationMessages.add(violation.getPropertyPath().toString() + ": " + violation.getMessage()); } return Response.status(Status.BAD_REQUEST).entity(validationMessages).build(); } if (e != null) { employee.setId(id); EmployeeDB.updateEmployee(id, employee); return Response.ok(employee).build(); } else return Response.status(Status.NOT_FOUND).build(); } @DELETE @Path("/{id}") public Response removeEmployeeById(@PathParam("id") Integer id) { Employee employee = EmployeeDB.getEmployee(id); if (employee != null) { EmployeeDB.removeEmployee(id); return Response.ok().build(); } else return Response.status(Status.NOT_FOUND).build(); } }
For imitating the DB, I have created EmployeeDB
class which store employee records and updates in memory.
package com.howtodoinjava.rest.dao; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import com.howtodoinjava.rest.representations.Employee; public class EmployeeDB { public static HashMap<Integer, Employee> employees = new HashMap<>(); static{ employees.put(1, new Employee(1, "Lokesh", "Gupta", "India")); employees.put(2, new Employee(2, "John", "Gruber", "USA")); employees.put(3, new Employee(3, "Melcum", "Marshal", "AUS")); } public static List<Employee> getEmployees(){ return new ArrayList<Employee>(employees.values()); } public static Employee getEmployee(Integer id){ return employees.get(id); } public static void updateEmployee(Integer id, Employee employee){ employees.put(id, employee); } public static void removeEmployee(Integer id){ employees.remove(id); } }
Build Resource Representations
Representation is what holds the data and serialized into JSON. It’s model for RESTful application. When using Jersey with Jackson, all you need to build a resource representation is – a simple POJO following java bean standards. Jackson constructs the JSON string recursively according to the getter methods of each class and their return type.
java.util.List
type will be converted to a JSON array.package com.howtodoinjava.rest.representations; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotBlank; public class Employee { @NotNull private Integer id; @NotBlank @Length(min=2, max=255) private String firstName; @NotBlank @Length(min=2, max=255) private String lastName; @Pattern(regexp=".+@.+\\.[a-z]+") private String email; public Employee(){ } public Employee(Integer id, String firstName, String lastName, String email) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.email = email; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "Emplyee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]"; } }
If required in some cases, you can prevent a property from being a part of the JSON representation by adding the @JsonIgnore
annotation to its getter.
Request Validation
When accepting PUT
and POST
requests, you will need to validate user submitted entity content in request body. Dropwizard uses hibernate validator for this purpose. Adding validation requires following steps.
-
Add validation annotations in representation class
@NotNull private Integer id; @NotBlank @Length(min=2, max=255) private String firstName; @NotBlank @Length(min=2, max=255) private String lastName; @Pattern(regexp=".+@.+\\.[a-z]+") private String email;
-
Inject Environment.getValidator() in REST resource from Application
-
Use validator in REST resource
public class EmployeeRESTController { private final Validator validator; public EmployeeRESTController(Validator validator) { this.validator = validator; } @POST public Response createEmployee(Employee employee) throws URISyntaxException { Set<ConstraintViolation<Employee>> violations = validator.validate(employee); Employee e = EmployeeDB.getEmployee(employee.getId()); if (violations.size() > 0) { ArrayList<String> validationMessages = new ArrayList<String>(); for (ConstraintViolation<Employee> violation : violations) { validationMessages.add(violation.getPropertyPath().toString() + ": " + violation.getMessage()); } return Response.status(Status.BAD_REQUEST).entity(validationMessages).build(); } //Create Employee code here } }
@Override public void run(Configuration c, Environment e) throws Exception { LOGGER.info("Registering REST resources"); e.jersey().register(new EmployeeRESTController(e.getValidator())); }
Verify REST APIs
Now when we have created and added validations for REST APIs, let’s test this out.
Build application uber jar file
> mvn clean package
Start application in jetty server
> java -jar target\DropWizardExample-0.0.1-SNAPSHOT.jar server
Access URI http://localhost:8080/employees
This will return employees collection and related response headers.

Access URI http://localhost:8080/employees/1
This will return employee’s record with id 1.

Sent HTTP PUT http://localhost:8080/employees/1 with invalid request data
You will get validation messages.

Sent HTTP PUT http://localhost:8080/employees/1 with correct data
Employee record will be updated successfully.

In same way, you can test other APIs and scenarios.
Let me know your questions in comments section.
Happy Learning !!
Leave a Reply