Evaluate your SIEM
Get the guideComplete visibility for DevSecOps
Reduce downtime and move from reactive to proactive monitoring.
May 8, 2017
Dropwizard is an open source Java Framework which was designed to develop high-performing RESTful web services. Dropwizard can be especially useful when building Java microservices. The framework is comprised of tried-and-tested libraries from Java into a single package to enable the developer to focus on developing functionality. The framework provides:
To demonstrate how easy it is to get started with Dropwizard, this post walks through the creation of a simple web service. The Dropwizard website has a great getting started example, which creates a Hello World example based on the Maven build system. Let’s go in a different direction, and create a service which returns the shipping cost for a package based on weight. We’ll use Gradle as our build system. The source code for this example can be viewed at https://github.com/echovue/dropwizard_shipping_service.
Open your favorite IDE, and create a new Gradle project, I’ll be using IntelliJ Community Edition for this example, but the steps should apply to any editor. Once you have your project created, open the build.gradle file, and add a dependency for the Dropwizard core library. At the time of writing, the current version is 1.1.0. The dependency line to include is: compile(‘io.dropwizard:dropwizard-core:1.1.0’)
There are two key parts to a Dropwizard-based microservice. A YAML based configuration, and a Configuration class. Let’s first look at the YAML configuration. By convention, this file should be created in the root folder of your application and should be named after the service itself. The file specifies connection specifications for the web service and defines the logging protocols. The file can also be used to define SSL connection properties, and specify the location of metrics collection tools. This example provides additional properties which you may want to include. I’ve named this file shippingservice.yaml.
server: applicationConnectors: - type: http port: 8080 adminConnectors: - type: http port: 8081 logging: level: INFO loggers: com.echovue.shippingservice: DEBUG appenders: - type: console - type: file threshold: INFO logFormat: "%-6level [%d{HH:mm:ss.SSS}] [%t] %logger{5} - %X{code} %msg %n" currentLogFilename: /tmp/application.log archivedLogFilenamePattern: /tmp/application-%d{yyyy-MM-dd}-%i.log.gz archivedFileCount: 7 timeZone: UTC maxFileSize: 10MB
As mentioned previously, the second essential configuration component is the configuration class, which extends the Configuration class. This class is passed into the Application class. If you have specific objects you want to populate for use by your application, this class is a good place to instantiate them, but for our purposes, we’ll leave it in its simplest form. Here’s the ShippingServiceConfiguration Class.
package com.echovue.shippingservice.config;
import io.dropwizard.Configuration;
public class ShippingServiceConfiguration extends Configuration {
}
The application class is where our main method lives. This class extends the Dropwizard Application object, and initialized it with the Configuration class we defined previously in the initialize method, which we override.
The run method of the parent class is also overridden, and this is where we declare our various resources and register them with the application. We’re going to instantiate and register the ShippingServiceResource which will be the next class we create.
package com.echovue.shippingservice;
import com.echovue.shippingservice.config.ShippingServiceConfiguration;
import com.echovue.shippingservice.resource.ShippingServiceResource;
import io.dropwizard.Application;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
public class ShippingServiceApplication extends Application {
public static void main(String[] args) throws Exception {
new ShippingServiceApplication().run(args);
}
@Override
public void initialize(Bootstrap bootstrap) {
}
@Override
public void run(ShippingServiceConfiguration configuration,
Environment environment) throws Exception {
final ShippingServiceResource resource = new ShippingServiceResource();
environment.jersey().register(resource);
}
}
Our resource is created using the Javax.ws.rs package, which contains a collection of interfaces and annotations for the creation of RESTful web services. We’re going to define a get endpoint on the path of “/calculate” which will accept an optional parameter. Shipping package weight. If the weight parameter is present, we’ll create a new ShippingCost object with the weight, and then return the object.
The ShippingCost object contains a very basic cost calculation, and Jackson-based annotations to describe how to render the object in JSON format.
package com.echovue.shippingservice.resource;
import com.codahale.metrics.annotation.Timed;
import com.echovue.shippingservice.model.ShippingCost;
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 java.util.Optional;
@Path(“calculate”)
@Produces(MediaType.APPLICATION_JSON)
public class ShippingServiceResource {
public ShippingServiceResource() {}
@GET
@Timed
public ShippingCost calculateShipping(@QueryParam(“weight”) Optional weightOptional) {
if (weightOptional.isPresent()) {
ShippingCost cost = new ShippingCost(weightOptional.get());
return cost;
}
return null;
}
}
ShippingServiceResource Class
package com.echovue.shippingservice.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
public class ShippingCost {
@NotEmpty
private Double cost;
@NotEmpty
private Double weight;
public ShippingCost() {
}
public ShippingCost(double weight) {
this.weight = weight;
this.cost = 2.35 + (weight * 0.85);
}
@JsonProperty
public Double getCost() {
return cost;
}
@JsonProperty
public Double getWeight() {
return weight;
}
}
ShippingCost Class
So far we’ve created four very basic Java classes and included a single dependency in our build.gradle file. What we have now is a simple but functioning microservice. Let’s get it running.
Depending on your IDE, you may be able to right-click the main function in the Application class and run it as a Java application. If that works, you can skip the rest of this section; otherwise, we’ll briefly cover how to build an executable jar, and run it from the command line.
We’re going to need a few more lines in our build.gradle file to build our jar. There are many ways to accomplish this in Java, but the plugin located at https://github.com/rholder/gradle-one-jar is one of the easiest to implement.
Update your build.gradle file to include the additional plugin definition for ‘gradle-one-jar’, the buildscript section, and the packageJar task. Ensure that the group name at the top of the file, and the mainClass parameter in the packageJar task match the group and main application class for your application.
group 'com.echovue'
version '1.0-SNAPSHOT'
apply plugin: ‘java’
apply plugin: ‘gradle-one-jar’
sourceCompatibility = 1.8
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath ‘com.github.rholder:gradle-one-jar:1.0.4’
}
}
repositories {
mavenCentral()
}
dependencies {
compile(‘io.dropwizard:dropwizard-core:1.1.0’)
}
task packageJar(type: OneJar) {
mainClass = ‘com.echovue.shippingservice.ShippingServiceApplication’
}
ShippingCost Class
Open a terminal window on your workstation, and execute the following command from the root folder for your project:
Windows gradlew clean build packageJar
MacOS / Linux
./gradlew clean build packageJar
Gradle will create a jar for the application in build/libs, and also create a fat jar which contains all the dependencies for the application to run. The fat jar will have the suffix of -standalone
To start the application. Run the following command from the root folder of your application:
Windows
java -jar build\libs\shippingservice-1.0-SNAPSHOT-standalone.jar server shippingservice.yaml
MacOS / Linux
java -jar ./build/libs/shippingservice-1.0-SNAPSHOT-standalone.jar server shippingservice.yaml
Open your browser of choice, and navigate to http://localhost:8080/calculate?weight=100.2
The result should be a JSON object similar to:
{
"cost":87.52,
"weight":100.2
}
Resources to Learn More
This simple example shows the ease with which you can create a working microservice using the Dropwizard framework. As stated at the beginning of this article, the biggest benefit to using Dropwizard is the collection of tools and libraries within Dropwizard to provide a framework on which to build your application.
If you would like to know more, the Dropwizard website is an excellent source of examples and documentation to get you started and take your application to the next level. One of the most exciting parts of the framework is the metrics library, which allows you to provide full-stack visibility into your application.
Reduce downtime and move from reactive to proactive monitoring.
Build, run, and secure modern applications and cloud infrastructures.
Start free trial