POC con Dropwizard

Desde que publiqué mi primer post en el blog, POC con Spring Boot, tenía pensado escribir uno similar con Dropwizard, y ahora que además lo estoy usando en mi actual proyecto, es el mejor momento para verlo 🙂

Concepto

Dropwizard es una especie de framework o librería para poder desarrollar rápidamente una aplicación web, muy al estilo de lo que nos aporta Spring Boot:
– Servidor «embebido», los famosos fat jars.
– Conjunto de librerías ya probadas y perfectamente compatibles entre sí.
– Simplicidad en la configuración.
Para mi la principal diferencia con Spring Boot, es que Dropwizard no usa ninguna librería de Spring. Su «stack» de tecnologias / librerías principales es la siguiente:
Maven
Jersey (implementación JAX-RS)
Jetty como servidor embebido.
Jackson, para todo el procesamiento y parseo de jsons.
Metrics, librería muy sencilla de usar para métricas, healtchecks, etc.
– Otras librerías secundarias: Guava, Logback, Hibernate Validator…

Vamos a ver un ejemplo de como montar desde cero un proyecto Dropwizard, con un endpoint «/helloworld».

Entorno usado:
Java JDK 1.8
Maven 3.3.9
Git 2.6.3
IDE Intellij 2016.1.2 Ultimate version

Pasos:

1. Crearemos un proyecto maven con el típico quick-start de maven (ver los 4 primeros pasos del post sobre Spring Boot). Yo lo he hecho directamente con mi archetype de maven.

2. Añadimos la dependencia principal de Dropwizard a nuestro pom:

    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-core</artifactId>
        <version>0.9.2</version>
    </dependency>

Con esa dependencia es suficiente. A su vez tiene todas las dependencias necesarias así como las librerías que comenté antes.

3. Para nuestro ejemplo tendremos el siguiente bean:

package com.edwise.pocs.dropwizard.model;

public class Message {

    private final String message;

    public Message(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

4. Que será lo que devolveremos en el único endpoint de nuestro Resource, que será así:

package com.edwise.pocs.dropwizard.resource;

// imports...

@Path("/hello-world")
@Produces(MediaType.APPLICATION_JSON)
public class MessageResource {
    private static final String HELLO_WORLD_SENTENCE = "Hello world %s!";
    private static final String DEFAULT_NAME = "Nobody";

    @GET
    public Message getHelloWorldMessage(@QueryParam("name") String name) {
        return new Message(
                String.format(HELLO_WORLD_SENTENCE, name != null ? name : DEFAULT_NAME)
        );
    }
}

Con las anotaciones básicas de un servicio REST JAX-RS. Lo único que hacemos es devolver un Message, con un mensaje construido a partir del nombre recibido como parámetro.
Con @Produces(MediaType.APPLICATION_JSON) el endpoint del resource devolverá un json. Jackson se encargará de manera trasparente de parsear la clase a json.

5. Creamos una clase de configuración. Dropwizard necesita que creemos una clase extendiendo de Configuration:

package com.edwise.pocs.dropwizard.config;

import io.dropwizard.Configuration;

public class DropwizardConfig extends Configuration {
}

En nuestro caso no añadiremos nada a la clase, dado que el ejemplo quiero que sea lo más simple posible, pero lo normal es añadir aquí cualquier parámetro de configuración necesario para el proyecto. En un próximo post seguramente lo veamos.

6. Y creamos nuestra clase ‘main’. Es muy similar a Spring Boot:

package com.edwise.pocs.dropwizard;

// imports...

public class DropwizardApplication extends Application<DropwizardConfig> {

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

    @Override
    public void run(DropwizardConfig dropwizardConfig, Environment environment) {
        environment.jersey().register(new MessageResource());
    }
}

Tenemos que extender la clase Application y parametrizandola con nuestra clase de configuración.
Además, es necesario implementar el método ‘run’, y en este caso lo único que hacemos en él es registrar en el entorno nuestro resource como componente Jersey. Como vemos, si necesitáramos usar algún parámetro de configuración al crear nuestros componentes aquí, podríamos hacerlo ya que el método ‘run’ recibe la clase de configuración como parámetro.

7. Ya solo nos falta añadir dos plugins a nuestro pom.xml de maven, son los siguientes:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.4.3</version>
        <configuration>
            <createDependencyReducedPom>true</createDependencyReducedPom>
            <filters>
                <filter>
                    <artifact>*:*</artifact>
                    <excludes>
                        <exclude>META-INF/*.SF</exclude>
                        <exclude>META-INF/*.DSA</exclude>
                        <exclude>META-INF/*.RSA</exclude>
                    </excludes>
                </filter>
            </filters>
        </configuration>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.edwise.pocs.dropwizard.DropwizardApplication</mainClass>
                        </transformer>
                    </transformers>
                </configuration>
            </execution>
        </executions>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
            <archive>
                <manifest>
                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                </manifest>
            </archive>
        </configuration>
    </plugin>

El maven-shade-plugin se encarga de que el jar generado sea un «fat jar», o jar con todas las librerías necesarias para ejecutarse solo. En el plugin le indicamos nuestra clase ‘main’.
El maven-jar-plugin se suele usar para la generación del nombre del jar, según versiones y demás.

8. Vamos a arrancar ya nuestro proyecto dropwizard. Podemos hacerlo directamente desde una consola desde la raiz del proyecto ejecutando lo siguiente:

java -jar target/dropwizard-example-1.0.0-SNAPSHOT.jar server

O en Intellij podemos crear fácilmente un «Run configuration» de tipo Application con nuestra clase DropwizardApplication como MainClass y «server» como Program Arguments:

ScreenClip

Si ahora accedemos a http://localhost:8080/hello-world?name=edwise el servicio nos devolverá algo como esto:

{"message": "Hello world edwise!"}

Y aquí terminamos nuestro pequeño POC con Dropwizard. Quizá en próximos post explique alguna otra característica sobre Dropwizard.
Tenéis como siempre el proyecto completo en mi github, con el nombre dropwizard-example.