How to Build a REST API using Dropwizard?
Hello everyone, today we will discuss how to build RESTful API using Dropwizard with the help of one simple example.
Dropwizard is an open-source Java framework for the expeditious development of REST APIs.Dropwizard allows a developer to build an initial project very expeditious. This avails the application to be packaged in a way that allows it to be facilely installed on the production environment as a stand-alone service.
Dropwizard comes with the fundamental package of components or libraries needed to develop RESTful web services, so you don't require to include and configure each of them discretely:
Libraries included inside Dropwizard
- Jetty: Dropwizard utilizes the Jetty HTTP library to embed an HTTP server directly into our project.
- Jersey: It provides support for JAX-RS APIs and serves as a JAX-RS Reference Implementation.
- Jackson: Jackson is a high-performance JSON processor for Java.
- Guava: Google's utility library that gives us a large number of classes to speed up development in Java.
- Liquidbase: To keep our database schema in check throughout our development and release cycle.
- Apache HTTPClient: Provides the ability to interact with other web services.
- JDBI: Database access classes that have Hibernate support.
- Freemarker and Mustache: Templating engine.
- Logback and SLF4j: Used for logging
- Hibernate Validator: To express and validate application constraints.
Let's start to build RESTful API with Dropwizard
Project Directory:
Maven Dependencies[pom.xml]
<?xml version="1.0" encoding="UTF-8"?>
<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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.knf.dev</groupId>
<artifactId>dropwizard-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Dropwizard Hello World application</name>
<properties>
<dropwizard.version>2.0.0</dropwizard.version>
<junit.version>5.7.0</junit.version>
<logback.version>1.2.3</logback.version>
<slf4j.version>1.7.30</slf4j.version>
<skip.tests>false</skip.tests>
<main.class>
com.knowledgefactory.dev.DemoApplication
</main.class>
</properties>
<dependencies>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>${dropwizard.version}</version>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-jackson</artifactId>
<version>${dropwizard.version}</version>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-testing</artifactId>
<version>${dropwizard.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>4.3.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.6.28</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.18.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<finalName>app</finalName>
<createDependencyReducedPom>false
</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.
resource.ServicesResourceTransformer" />
<transformer
implementation="org.apache.maven.plugins.shade.
resource.ManifestResourceTransformer">
<mainClass>${main.class}</mainClass>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<outputDirectory />
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<forkCount>8</forkCount>
<reuseForks>true</reuseForks>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
Create REST Application Class[DemoApplication.class]
package com.knowledgefactory.dev;
import com.knowledgefactory.dev.resources.HelloResource;
import io.dropwizard.Application;
import io.dropwizard.setup.Environment;
public class DemoApplication
extends Application<DemoApplicationConfiguration> {
public static void main(String[] args) throws Exception {
new DemoApplication().run(args);
}
@Override
public void run(DemoApplicationConfiguration configuration,
Environment environment) {
environment.jersey().register(new HelloResource
(configuration.getDefaultName()));
}
}
Create REST Resource and APIs[HelloResource.class]
package com.knowledgefactory.dev.resources;
import java.util.Optional;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import com.knowledgefactory.dev.api.Message;
@Path("/hello")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class HelloResource {
private final String defaultName;
public HelloResource(final String defaultName) {
this.defaultName = defaultName;
}
@GET
public Message get(@QueryParam("name") Optional<String> name) {
Message hello = new Message();
hello.setMessage(("Hello " + name.orElse(defaultName) +
" welcome to dropwizard"));
return hello;
}
}
Data transfer object[Message]
package com.knowledgefactory.dev.api;
public class Message {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
DemoApplicationConfiguration.class
package com.knowledgefactory.dev;
import io.dropwizard.Configuration;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.validation.constraints.NotEmpty;
public class DemoApplicationConfiguration extends Configuration {
@NotEmpty
private String defaultName;
@JsonProperty
public String getDefaultName() {
return defaultName;
}
@JsonProperty
public void setDefaultName(String name) {
this.defaultName = name;
}
}
dev_config.yml
server:
applicationConnectors:
- type: http
port: 9080
logging:
level: INFO
loggers:
com.knowledgefactory.dev: DEBUG
defaultName: sibin
Verify REST APIs
Build application jar file: mvn clean package
Start application in jetty server: java -jar target/app.jar server dev_config.yml