Considering developing RESTful web services there are many options available for Java. To name a few one may consider Spring, writing them for a Java EE container with JAX-RS or even using something like Play Framework. Most of these are (heavier or thinner) integrated solutions though. When you step into one of these you buy it with the whole inventory of things they come with, not neccesserily targeted into developing RESTful web services.

Another approach would be to collect just what is needed to write such a service and glue them together in the project. The downside is, it takes usually some boring code to write integrating all of it into working solution (bootstraping, handling configuration files, etc.). And that is the reason I find Dropwizard helpful - it's more or less a collection of software for writing RESTful web services (Jetty, Jersey, Jackson), that takes boring stuff away and permits to jump ahead into writing the service.

But there is one problem with the tutorial they have on their website though as it's aimed at developers with a knowledge of putting such Java project together (Maven, JAX-RS concepts etc.). Having worked with developers with no such prior knowledge I see a need to write a guide covering more basics to help them.

Sources for this tutorial to get you started are available here on GitHub

Installing SDK

You need to install Java SE 7 JDK from Oracle website. Contrary to JRE it, among other things, provides Java compiler to compile your sources. Add it to the PATH, you should be able to run javac anywhere from console. For Ubuntu users there is a tutorial for that.

Creating Maven project

Maven is a tool for automating building and packaging of Java software and you can get it from their website (get version from 2.x branch). Add it to the PATH as well, you should be able to run mvn anywhere from the console. Ubuntu users can do sudo apt-get install maven2.

Maven project has some default directory structure, so you need to create it:

dropwizard-example
 |-- src
 |    |-- main
 |    |    |-- java 
 |    |    +-- resources    
 |    +-- test
 |         +-- java
 +-- pom.xml

To make it handled by Maven you need to create pom.xml and put it just under dropwizard-example (a.k.a. project root). The file contents:

<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>

    <name>dropwizard-example</name> 

    <groupId>eu.kielczewski.example</groupId> 
    <artifactId>dropwizard</artifactId>
    <version>1.0-SNAPSHOT</version>

</project>

Every Maven project is identified by <groupId>, <artifactId>, <version> fields and we have it set here. <name> is not really important. By default the project will be compiled with language version 1.3 and packaged as jar.

Most IDEs out there should take you up to this point simply by choosing File -> New Project -> Maven module or something like that.

Maven build lifecycle

Important concept of Maven is build lifecycle. There are phases that project goes through when being build. Most interesting (I took liberty of skipping a few) are, in order:

  • clean - the project is clean of all artifacts that came from previous compilations
  • compile - the project is compiled into /target directory of project root
  • test - unit tests are run
  • package - compiled sources are packaged into archive (JAR by default)
  • install - packaged archive is copied into local maven repository (located in your system user's home directory, in /.m2)</

You can trigger build up to chosen phase, i.e. by issuing mvn install from the console all of the previous phases up to and including install will be executed in this order, except for clean, which must be called directly.

Adding Dropwizard as dependency

Maven has ability to download project dependencies for you (i.e. libraries you want to use). It does that by looking them up in your local repository, and online in Maven Central Repository. You can search Maven Central to locate packages you need and then add them to your pom.xml to be used by the project. In case of Dropwizard you need to add the following section to your to pom.xml:

<dependencies>
    <dependency>
        <groupId>com.yammer.dropwizard</groupId>
        <artifactId>dropwizard-core</artifactId>
        <version>0.6.2</version>
    </dependency>
</dependencies>

Setting language level

By default, Maven2 compiles all the sources using Java language version 1.3. That's not good enough, so it should be switched to 1.7 to use annotations and other modern language features. Hopefully the bahaviour of Maven can be modified or extended by plugins. There is maven-compiler-plugin that hooks into compile phase of build lifecycle. it's used by adding the following section into pom.xml

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.0</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
            </configuration>
        </plugin>
    </plugins>
</build>

Creating configuration file

Dropwizard supports configuration files, so any application properties can be set at run time. it's generally a good idea to use it, so create the configuration.yml file in the project root, with the following content:

messages:
  hello: Hello world!

As you can see the YAML file has a messages section with a property greeting set to "Hello world!". We will use this property to customize the greeting message that will be shown by our web service.

Creating classes to access configuration

Dropwizard will map the contents of your configuration.yml to a plain old Java object (POJO). But youll need to write it first. To do so, navigate todropwizard-example/main/javaand using your IDE add a package there and name iteu.kielczewski.example.config. In this package create a fileExampleServiceConfiguration.java`:

import com.yammer.dropwizard.config.Configuration;

import javax.validation.Valid;

public class ExampleServiceConfiguration extends Configuration {

    @Valid
    private MessagesConfiguration messages;

    public MessagesConfiguration getMessages() {
        return messages;
    }

    public void setMessages(MessagesConfiguration messages) {
        this.messages = messages;
    }
}

This represents our configuration file configuration.yml and it extends from Configuration class provided by Dropwizard. As you remember, in this file we created messages section, and every section is mapped to separate object, like MessagesConfiguration that we will create at the moment. Additionaly we have provided getter and setter.

Notice the @Valid annotation from javax.validation package. It says that to consider the configuration valid, the messages section should be valid.

Time to create MessageConfiguration, in the same package eu.kielczewski.example.config:

import javax.validation.constraints.NotNull;

public class MessagesConfiguration {

    @NotNull
    private String hello;

    public String getHello() {
        return hello;
    }

    public void setHello(String hello) {
        this.hello = hello;
    }
}

It is just a plain old Java object and it doesn't need to extend Configuration anymore. The @Valid annotation from javax.validation.constraints package says that to consider the configuration valid, the hello property should not be null.

If you ever had a need to put something in configuration.yml and access it, all it takes is to add some properties to ExampleServiceConfiguration.

Writing main service class

Now we will add a class that will represent our service. it's main responsibility is just setting things up. Create it in eu.kielczewski.example package:

import com.yammer.dropwizard.Service;
import com.yammer.dropwizard.config.Bootstrap;
import com.yammer.dropwizard.config.Environment;
import eu.kielczewski.example.config.ExampleServiceConfiguration;

public class ExampleService extends Service<ExampleServiceConfiguration> {

    public static void main(String[] args) throws Exception {
        new ExampleService().run(args);
    }

    @Override
    public void initialize(Bootstrap<ExampleServiceConfiguration> bootstrap) {
        bootstrap.setName("dropwizard-example");
    }

    @Override
    public void run(ExampleServiceConfiguration conf, Environment env) throws Exception {
        // we will add resource classes here
    }

}

Things to notice:

  • It extends from generic class Service provided by Dropwizard that takes our ExampleServiceConfiguration as a class parameter,
  • it has static main() method that will be invoked when we run the application - it escapes static context and executes run(String[] arguments) method of the parent class,
  • it overrides initialize() - service name is set there,
  • it overrides run(), which gets ExampleServiceConfiguration filled from configuration.yml as a parameter and Environment as well. We will use that to add resource classes later.

Writing resource class

In REST the web resource is anything that can be mapped to and URI and be manipulated by GET, POST, PUT and DELETE methods, provides it makes any sense at all ;) Regardless, we will create a resource that will respond to GET on URI /hello with a message taken from configuration.yml. For that purpose Dropwizard comes with Jersey, which is implementation of JAX-RS API - a standard API for RESTful web services in Java. The main concept of this API is that REST web resources are handled by public methods in resource classes. So, let's create such a class - HelloResource in package eu.kielczewski.example.hello

import eu.kielczewski.example.config.MessagesConfiguration;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path(value = "/hello")
public class HelloResource {

    private final MessagesConfiguration conf;

    public HelloResource(MessagesConfiguration conf) {
        this.conf = conf;
    }

    @GET
    public String sayHello() {
        return conf.getHello();
    }

}

Things to notice:

  • it's a POJO, it doesn't extend anything,
  • it takes our MessageConfiguration as a constructor parameter so we can get a hello message from it,
  • it is annotated with @Path annotation from javax.ws.rs package (JAX-RS) - it says that it is indeed a web resource and it will handle requests on /hello path,
  • it has public method sayHello() that returns string from MessageConfiguration,
  • sayHello() is annotated with @GET annotation - it means that it will be executed when GET request on /hello will be received
  • nothing here cares about response format, sayHello() just returns String (and can return any object), creating proper web response out of it is handled entirely by Jersey.

Adding resource to Environment

Now we should add our HelloResource to Environment in run() method of main service class - ExampleService, so it will look like this:

@Override
public void run(ExampleServiceConfiguration conf, Environment env) throws Exception {
    env.addResource(new HelloResource(conf.getMessages()));
}

Executing the service

We need some way to run the service we just created. In development environment one way would be to use Maven for that too. There is exec-maven-plugin for that purpose. All it takes is to add the following section to your pom.xml under <build><plugins>:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.2.1</version>
    <configuration>
        <mainClass>eu.kielczewski.example.ExampleService</mainClass>
        <arguments>
            <argument>server</argument>
            <argument>configuration.yml</argument>
        </arguments>
    </configuration>
</plugin>

This plugin adds custom build phase exec:java that can be used to run our service. In <mainClass> section it points to our main service class with static method run(). The <arguments> section specifies two arguments that are needed to run our service:

  • server - it tells Dropwizard to run in server mode
  • configuration.yml - it tells Dropwizard to parse configuration.yml we created

All that was left now is to navigate into project root and execute maven from the console:

mvn compile exec:java

And you should see the service starting up. Now point your browser to http://localhost:8080/hello to see your service in action.

Summary and references

This part covers developing a very basic RESTful web service using Dropwizard. A follow-up tutorial is going to showcase some more advanced use cases.

Things to check out:

This site uses cookies. By continuing to browse the site, you are agreeing to our use of cookies. Find out more in Privacy and Cookies Policy.