Nuevo proyecto personal: elitedangerous-api :)

Retomo el blog después de prácticamente un año sin postear, para contar brévemente un pequeño proyecto personal que he empezado estas últimas semanas.

El proyecto lo podéis encontrar en mi github, como siempre.

La idea principal del proyecto es crear una aplicación Spring Boot con la que poder jugar con los datos que provee la web eddb.io. Esta web es una especie de base de datos con información actualizada casi en tiempo real sobre los sistemas estelares, estaciones, facciones, etc del videojuego Elite: Dangerous.

Esa web, eddb.io, proporciona ya varias funcionalidades de búsqueda, pero yo quería ir un poco más allá y crear unas búsquedas algo más complejas, y es lo que estoy intentando hacer en mi proyecto personal.

Entrando un poco más en detalle respecto a la arquitectura, librerías, etc, os comento aquí en forma de puntos:

  • Es un proyecto Spring Boot, con Maven y Java, usando la última versión de Spring Boot que no está aun en versión final, la 2.0.0. La iré actualizando según actualicen.
  • Es un proyecto en Java 9. Esto ahora mismo me provoca algún que otro problemilla con alguna librería que me gustaría usar y no puedo por que todavía no lo soportan.
  • Por ahora, la idea es descargar los jsons principales de eddb.io nada más arrancar, y dejarlos en memoria para consultar.
  • Para acceder, en principio estoy haciendo un api REST.

Si tenéis alguna sugerencia o duda sobre el proyecto, son bienvenidas. Quizá en próximos posts explique alguna de las funcionalidades / cambios / etc del proyecto.

Mi Codemotion 2016

Este año he repetido otra vez apuntándome a Codemotion. Y al igual que el año pasado, lo he disfrutado bastante 🙂

codemotionColgante.png

Codemotion 2016

En esta ocasión la entrada nos la ha pagado mi empresa, TapTap Networks, cosa que es de agradecer, no todas lo hacen.Y esta vez, por asuntos personales, no he podido estar los dos dias completos, el viernes llegue a eso de las 13:30.

Aún asi, comento aquí un poco por encima las charlas a las que he asistido:

Viernes:

  • Métricas: lo bueno, lo feo y lo malo: hablaron de métricas a nivel teórico, que uso tienen, ventajas, etc. No preste mucha atención, la verdad, acababa de hacer el check in y me metí en esta por meterme en alguna 😛
  • Como hacer optimo un proyecto Big Data y no morir en el intento: interesante charla, sobre Big Data un poco en general, y contando experiencias, consejos, etc. Me gusto, tanto como introducción, como por los consejos y demás.
  • Big Data para Javeros con Apache Flink: charla muy introductoria de lo que es Flink, resaltando mucho que esta pensado para Java (no Scala, como casi todas las librerías Big Data).
  • De cero a cien con Kotlin: Charla sobre Kotlin, en plan contando las palabras reservadas, etc. No era una maravilla, pero bueno, como introducción, no estaba mal.

Sabado:

  • Lo que deberías saber sobre testing para irte de cañas con @pedro_g_s y no empezar con resaca: típica charla sobre testing. Nada nuevo para mi, pero interesante.
  • Akka persistence, CQRS/ES y otras siglas del montón: charla intermedia e incluso avanzada sobre Akka persistence. Muy interesante. Para el que este un poco verde de Akka, CQRS, DDD, quizá se perdería cosas, pero es bueno que no todas las charlas sean en plan introductorias.
  • Microservicios, en qué lío me he metido: charla sobre microservicios, impartida por un excolega mio, @ehdez73 y un compañero suyo, contando experiencias y problemas que se han ido encontrando en su empresa (Packlink) para migrar su sistema a microservicios. Muy recomendable.
  • Time to grow up: charla muy amena sobre hacia donde esta yendo nuestro mundillo, consejos, experiencias. Me gusto mucho, de las mejores.
  • Real-time Learning with Spark: más Big Data, esta vez Spark. No estuvo nada mal, con código de ejemplo, etc.
  • Docker4Developers: charla introductoria de docker, explicando un ejemplo básico. Si no controlas de Docker, muy interesante y bien explicada.
  • ¿Con 40+ y programando? Sácale provecho a tu experiencia: charla de las que me gustan, hablando de experiencias y consejos para seguir programando teniendo ya una edad en la que muchos se meten ya en gestión y demás.
  • MongoDB: Mejora el rendimiento de tu aplicación: charla algo pesada, pero muy interesante y con muchas estrategias sobre mejora de mongo. Recomendable también.

En resumen, para mi, a la altura del año pasado (que no es poco). En cuanto a la organización, eso si, creo que ha mejorado bastante. La organización de las charlas y las salas ha sido mucho más acertada, las salas no solían estar tan a reventar como pasaba el año pasado. Incluso hasta en los desayunos han mejorado (el año pasado si llegabas tarde no te comías ni un triste bollo).

Espero repetir el año que viene también 🙂

Review: Java 8 in Action

Después de un pequeño parón en el blog, debido a vacaciones y temas varios, vuelvo esta vez con una pequeña reseña sobre un libro que terminé de leer hace poco, «Java 8 in Action», de la editorial Manning.

Aunque ya estaba bastante familiarizado con Java 8, por leer múltiples artículos y hacer pocs y demás, me compré hace varios meses este libro. Y hice muy bien  🙂 Es un libro de muy fácil lectura y no se hace largo ni pesado.

Trata principalmente todas las novedades de Java 8, centrándose en concreto en el «cambio» a programación funcional de Java, centrandose mucho en las lambdas y los streams.

Los autores son Raoul-Grabriel Urma, Mario Fusco y Alan Mycroft.

Java 8 in Action

Java 8 in Action

Partes

Consta de 4 grandes partes, con varios capítulos cada una:

  1. Fundamentals: introducción en la que habla de porque necesitaba Java esta actualización, con una pequeña introducción a las lambdas y streams, así como un capitulo tratando el concepto de «Behavior parameterization» (capitulo muy didáctico, y que viene muy bien para entender correctamente las lambdas). El último capitulo de esta parte introduce a fondo el concepto de lambda y su funcionamiento.
  2. Functional-style data processing: en esta parte se centra a saco en los streams, con varios capítulos. Desde una introducción básica, hasta el uso detallado de los collectors, etc. En concreto, en uno de los capitulos trata la paralelización, muy interesante, haciendo incluso una pequeña introducción del framework fork/join que se añadió en Java 7.
  3. Effective Java 8 programming: en esta parte empieza con un capitulo con consejos de refactoring de java a java 8, consejos de testing y debugging. El resto de capítulos trata otras novedades de Java 8:
    – Default methods
    – Optional
    – CompletableFuture (se me quedo un pelín corto, pero es una muy buena introducción)
    – New Date Time API
  4. Beyond Java 8: En esta parte se centran en explicar varios conceptos de programación funcional pura, de como usarlos con Java 8, etc. Termina con un capitulo comparando Java 8 con Scala (con una pequeña introducción a Scala, no está mal), y con otro comentando posibles mejoras (ya para Java 9) que consideran recomendables.

Por último tiene 4 apéndices:
Apéndice A Comenta algunos otros pequeños cambios de Java 8.
Apéndice B Enumera nuevos métodos en librerías ya existentes (collection, list, etc)
Apéndice C Apendice avanzado sobre como realizar múltiples operaciones en paralelo con Streams. Curioso cuanto menos.
Apéndice D Pequeño apéndice comentando como las lambdas son traducidas a bytecode.

En la web de Manning se puede descargar además todo el código de ejemplo que sale en todo el libro. Además, si te compras el libro y lo registras en la web, puedes descargartelo en pdf, epub, formato kindle, etc. Muy cómodo.

Opinión personal

Como comentaba cuando empecé a leerlo ya tenia un gran background sobre Java 8, e incluso lo estaba usando en mi trabajo desde Febrero (que es cuando me cambie de empresa), con lo que casi me lo compré más por capricho que por necesidad. Y aún así no me arrepiento 🙂

El libro me vino muy bien para asentar ciertos conceptos, y para entender ciertas movidas de los streams. Además que viene muy bien como libro de consulta para ciertas operaciones.

Y si no estás muy puesto en Java 8, es un libro perfecto para ponerte las pilas y muy fácil de leer. No se hace nada pesado, y trata todo lo necesario para manejarte con el mundillo de las lambdas y streams.

En mi experiencia, si eres programador Java, el paso a Java 8 y su programación funcional es una pasada. El código es mucho más legible, más resumido… Y además es que luego ya no hay vuelta atrás, jaja. Si ahora mismo tuviera que volver a trabajar en algún proyecto en Java 7 (o menos), no podría…

2 años de blog ya :)

Hoy cumplo ya 2 añitos escribiendo el blog. El ritmo más o menos sigo manteniéndolo, así que estoy contento 🙂

Este verano estoy algo más vago y entre las vacaciones y que estoy liado con alguna serie y algún juego llevo ya más de un mes sin escribir, pero para septiembre vuelvo a saco a por ello, con algun post más de dropwizard, quizá también una pequeña review de un libro que estoy terminando y lo que se me vaya ocurriendo.

Gracias por leerme, un abrazo!

Dropwizard series: clase Configuration

Comienzo otra serie de post, esta vez sobre Dropwizard, para el que ya hice un poc en un post previo. En este caso explicaré como cargar fácilmente un archivo yaml como configuración en Dropwizard, directamente en su clase Configuration, y como usarlo.

Concepto

Como vimos en el anterior post sobre Dropwizard, montar un proyecto con él consta de unos pocos pasos, entre ellos tener una clase Application, que es la clase principal que arranca nuestro servidor. Esta clase debe estar parametrizada con la clase de configuración Configuration. En el ejemplo anterior la dejamos vacía, pero en este caso vamos a ver como añadir fácilmente parámetros de configuración a nuestra aplicación.

Vamos a añadirle un par de parámetros de configuración a nuestro poc, los cuales usaremos desde nuestro resource hello-world.

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

Pasos:

1. Usaremos como base el mismo proyecto del anterior post de dropwizard, podéis descargarlo de aquí.

2. Añadimos en nuestra clase de configuración dos atributos nuevos:

package com.edwise.pocs.dropwizardseries.configurationclass.config;

// imports...

public class DropwizardConfig extends Configuration {

  @NotEmpty
  private String host;

  private String defaultName;

  public String getHost() {
  return host;
  }

  public void setHost(String host) {
  this.host = host;
  }

  public String getDefaultName() {
  return defaultName;
  }

  public void setDefaultName(String defaultName) {
  this.defaultName = defaultName;
  }
}

Tendremos 2 parámetros, uno con el host y otro con un nombre por defecto para el mensaje de «hello world».
Como vemos. para añadir parámetros a nuestra configuración basta con añadir atributos en nuestra clase Configuration, y crearle sus getters y setters. Jackson se encarga del parseo, de manera trasparente.
En el caso del host, por ejemplo, hemos puesto que sea un parámetro obligatorio (con el @NotEmpty de hibernate validations). Si nuestra configuración no tiene valor para ese parámetro, dará error el arranque.

3. Añadimos nuestro yaml con los dos parámetros de configuración, bajo el directorio ‘src/main/resources’ (puede ser en cualquier otro directorio, no es obligatorio):

host: localhost
defaultName: Nobody

Con esto ya automáticamente dropwizard cargará esos datos en nuestra clase Configuration.

4. Ahora vamos a usar los parámetros desde la aplicación: en nuestro MessageResource le añadimos un constructor que reciba esos dos datos, y cambiamos el formato del mensaje que devolvemos:

package com.edwise.pocs.dropwizardseries.configurationclass.resource;

import com.edwise.pocs.dropwizardseries.configurationclass.model.Message;

// imports...

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

  private final String host;
  private final String defaultName;

  public MessageResource(String host, String defaultName) {
  this.host = host;
  this.defaultName = defaultName;
  }

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

En el mensaje mostraremos tanto el nombre recibido (o el nombre por defecto si no) como el host.

5. En nuestra clase Application de dropwizard, modificamos el punto donde registramos el resource, pasándole los datos desde la clase Configuration:

package com.edwise.pocs.dropwizardseries.configurationclass;

// 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(dropwizardConfig.getHost(),
  dropwizardConfig.getDefaultName()));
  }
}

El objeto ‘dropwizardConfig’ recibido como parámetro en el método ‘run’ contiene ya los datos recogidos del yaml. Se los pasamos como parámetro al resource, y listo.

6. Solo falta arrancar y probar. Pero para que dropwizard procese el yaml, tenemos que pasárselo como parámetro al arrancar, de la siguiente manera:

java -jar target/dropwizard-series-configuration-class-1.0.0-SNAPSHOT.jar server src/main/resources/config.yaml

Si tenemos configurado un ‘Run configuration’ en Intellij para arrancarlo, también debemos añadir la ruta del yaml como segundo parámetro, de la misma manera.

7. Si ahora lanzamos una petición GET http://localhost:8080/hello-world contra nuestro servidor nos devolverá algo como esto:

{
  "message": "Hello world Nobody, from localhost!"
}

Todo el código de este post lo tenéis en mi github, proyecto dropwizard-series-configuration-class.

Java 8 tips: métodos default en la interfaz funcional Function

Como vimos en mi anterior post de Java 8, la interfaz Predicate nos ofrece varios métodos ‘default’ que pueden ser muy útiles. El resto de FuntionalInterface de Java 8 también tiene otros. En el caso de la interfaz Function, tiene alguno interesante, vamos a verlo en este post.

Concepto

Continuando con el post sobre métodos ‘default’ en la interfaz Predicate, vamos a ver aquí que otros métodos aporta la interfaz Function.

La interfaz Function representa una función, que acepta un parámetro y devuelve otro. Es una interfaz muy genérica, que se puede usar para muchos casos, e incluso es extendida por otras interfaces funcionales, como UnaryOperator (es igual que Function, pero los párametros de entrada y de salida son del mismo tipo).

Además, tiene varías implementaciones similares, como son BiFunction (como Function, pero con 2 parámetros de entrada).

Su implementación básica es la siguiente:

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);
}

Su método de interfaz funcional, ‘apply‘, recibe el parámetro y devuelve el resultado.

Pero, al igual que Predicate, tiene unos métodos ‘default’ extra, así como un método estático:

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
   ...
}

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    ...
}

static <T> Function<T, T> identity() {
    ...
}

Ejemplo:

Al igual que en el anterior post, todos los ejemplos los haremos sobre un List de BookCharacter:

public class BookCharacter {
    private final String name;
    private final Integer age;
    private final Weapon mainWeapon;
    private final boolean human;

    public BookCharacter(String name, Integer age, Weapon mainWeapon, boolean human) {
        this.name = name;
        this.age = age;
        this.mainWeapon = mainWeapon;
        this.human = human;
    }

    public enum Weapon {SWORD, AXE, BOW, STAFF, RING}

    // getters, toString, equals and hashCode
}
...
List<BookCharacter> bookCharacters = Arrays.asList(
        new BookCharacter("Gandalf", Integer.MAX_VALUE, Weapon.STAFF, false),
        new BookCharacter("Aragorn", 88, Weapon.SWORD, true),
        new BookCharacter("Gimli", 140, Weapon.AXE, false),
        new BookCharacter("Legolas", 2931, Weapon.BOW, false),
        new BookCharacter("Boromir", 41, Weapon.SWORD, true),
        new BookCharacter("Frodo", 51, Weapon.RING, false),
        new BookCharacter("Sam", 33, Weapon.SWORD, false)
);

Tanto el método ‘compose‘ como el ‘andThen‘ hacen exactamente lo mismo, que es realizar una composición de funciones. Lo único que los diferencia es el orden en el que lo hacen. Dependiendo de cual nos guste o encaje más (principalmente en legibilidad) elegiremos una u otra.

Imaginemos que tenemos definidas estas dos funciones:

    public static Function<List<BookCharacter>, BookCharacter> findFirstSwordsman() {
        return list ->
                list.stream()
                    .filter(bookChar -> Weapon.SWORD.equals(bookChar.getMainWeapon()))
                    .findFirst()
                    .orElse(new BookCharacter("NOBODY", 0, Weapon.SWORD, true));
    }

    public static Function<BookCharacter, String> characterToCode() {
        return bookCharacter ->
                bookCharacter.getName() + "::" + bookCharacter.getMainWeapon() + "::" +
                        (bookCharacter.isHuman() ? "human" : "nonHuman");
    }

La primera nos devuelve el primer BookCharacter espadachín de un List de BookCharacter (devolviendo un ‘NODOBY’ si no encontrará ninguno).
La segunda nos devuelve un String formado a partir de un BookCharacter.

Vamos a crear otra función que sea una composición de esas dos funciones, usando los métodos ‘andThen’ y ‘compose’:

        Function<List<BookCharacter>, String> andThenFunction =
                findFirstSwordsman().andThen(characterToCode());

        Function<List<BookCharacter>, String> composeFunction =
                characterToCode().compose(findFirstSwordsman());

Esas dos funciones, tal cual las hemos definido hacen lo mismo. La diferencia, como comenté antes, es el orden.
En el primer caso, con el método ‘andThen‘ primero se ejecuta la función sobre la que llamamos a andThen, y sobre el resultado de esta, se llama a la función pasada como parámetro.
En el segundo caso, con el método ‘compose‘, primero es ejecutada la función pasada como parámetro, y sobre el resultado de esta, se llama a la función sobre la que llamamos a compose.

Por último, Function nos provee de un método estático llamado ‘identity‘. Este método devuelve la llamada función ‘identidad’, que no es más que un Function que devuelve exactamente lo mismo que ha recibido como parámetro.
Por ejemplo, si a partir de nuestro List de BookCharacter queremos obtener un Map, con los nombres como claves y los BookCharacter como valores, haríamos lo siguiente:

        Map<String, BookCharacter> characterMap =
                bookCharacters.stream()
                              .collect(Collectors.toMap(BookCharacter::getName,
                                      bookChar -> bookChar));

Como vemos, usamos el método ‘toMap‘ de Collectors que recibe dos funciones, una para obtener la clave, y otra para el valor. En nuestro caso, el valor es exactamente el objeto recibido, luego tenemos ese ‘bookChar -> bookChar’.

Podemos en lugar de eso usar la función identidad de Function:

        Map<String, BookCharacter> characterMap =
                bookCharacters.stream()
                              .collect(Collectors.toMap(BookCharacter::getName,
                                      Function.identity()));

¿Sirve para algo usar la función identidad en lugar de lo anterior? No especialmente. Quizá por legibilidad nos guste más usar la función identidad, o quizá no… al gusto de cada uno 🙂

Tenéis en mi github todo el código usado en este post, en el proyecto java8-function-methods-example.

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.

Java 8 tips: métodos default en la interfaz funcional Predicate

Hace poco descubrí que las interfaces funcionales añadidas en Java 8 (Predicate, Function, etc) no solo tienen su correspondiente método abstracto, sino que además incluye unos métodos ‘default‘ muy útiles. Vamos a ver aquí en concreto los de la interfaz Predicate.

Concepto

Uno de las más importantes novedades en Java 8 son las lambdas. Para poder usarlas fácilmente, se han añadido varias interfaces funcionales (FunctionalInterface) para no tener que implementarlas nosotros, como son Function, Consumer, Supplier, Predicate

Estas interfaces, al ser FunctionalInterface solo tienen un único método. La interfaz Predicate, por ejemplo:

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

La interfaz Predicate sirve para evaluar una condición, devolviendo un booleano, y recibiendo un objeto como parámetro.
Su único método es el método ‘test‘, que realiza esa evaluación.

Pero si vemos el código de la interfaz Predicate veremos que también tiene varios métodos ‘default‘, que son los siguientes:

default Predicate<T> and(Predicate<? super T> other) {
    ...
}

default Predicate<T> negate() {
    ...
}

default Predicate<T> or(Predicate<? super T> other) {
    ...
}

Aunque quizá en principio no los necesitemos, en algunos casos pueden ser útiles, sobre todo a la hora de tener un código más legible. Vamos a ver un ejemplo de cómo podríamos usar esos métodos.

Ejemplo

Todos los ejemplos los haremos sobre un List de BookCharacter:

public class BookCharacter {
    private final String name;
    private final Integer age;
    private final Weapon mainWeapon;
    private final boolean human;

    public BookCharacter(String name, Integer age, Weapon mainWeapon, boolean human) {
        this.name = name;
        this.age = age;
        this.mainWeapon = mainWeapon;
        this.human = human;
    }

    public enum Weapon {SWORD, AXE, BOW, STAFF, RING}

    // getters, toString, equals and hashCode
}
...
List<BookCharacter> bookCharacters = Arrays.asList(
        new BookCharacter("Gandalf", Integer.MAX_VALUE, Weapon.STAFF, false),
        new BookCharacter("Aragorn", 88, Weapon.SWORD, true),
        new BookCharacter("Gimli", 140, Weapon.AXE, false),
        new BookCharacter("Legolas", 2931, Weapon.BOW, false),
        new BookCharacter("Boromir", 41, Weapon.SWORD, true),
        new BookCharacter("Frodo", 51, Weapon.RING, false),
        new BookCharacter("Sam", 33, Weapon.SWORD, false)
);

Si quisiéramos filtrar de nuestra lista los personajes que son jóvenes y que además lleven espada, haríamos algo así:

List<BookCharacter> youngsAndSwords =
        bookCharacters.stream()
                      .filter(bChar -> bChar.getAge() < 90 && Weapon.SWORD.equals(bChar.getMainWeapon()))
                      .collect(Collectors.toList());

o así:

List<BookCharacter> youngsAndSwords =
        bookCharacters.stream()
                      .filter(bChar -> bChar.getAge() < 90)
                      .filter(bChar -> Weapon.SWORD.equals(bChar.getMainWeapon()))
                      .collect(Collectors.toList());

La recomendada y más ‘clean code’ es la segunda manera, para separar los filtros.

Esta es la manera común de implementar las lambdas, pero en algunos casos nos puede interesar tener nuestras lambdas definidas en una variable, atributo o incluso una clase, para reutilizarla en más sitios. Algo como esto:

package com.edwise.pocs.java8predicatemethods;

// imports

public class BookCharacterPredicate {
    public static Predicate<BookCharacter> isYoung() {
        return bChar -> bChar.getAge() < 90;
    }

    public static Predicate<BookCharacter> useSword() {
        return bChar -> BookCharacter.Weapon.SWORD.equals(bChar.getMainWeapon());
    }

    public static Predicate<BookCharacter> isHuman() {
        return BookCharacter::isHuman;
    }

    public static Predicate<BookCharacter> isValid() {
        return bChar -> bChar.getName() != null &&
                bChar.getAge() > 0 &&
                bChar.getMainWeapon() != null;
    }
}

De esa manera, podríamos reescribir nuestro stream así:

List<BookCharacter> youngsAndSwords =
        bookCharacters.stream()
                      .filter(isYoung())
                      .filter(useSword())
                      .collect(Collectors.toList());

o así:

List<BookCharacter> youngsAndSwords =
        bookCharacters.stream()
                      .filter(isYoung().and(useSword()))
                      .collect(Collectors.toList());

En el segundo caso usamos el método ‘and‘ de Predicate, que acepta otro Predicate, y, por supuesto, hace un and lógico sobre los dos.

Si queremos filtrar los que no usan espada:

List<BookCharacter> notUseSword =
        bookCharacters.stream()
                      .filter(useSword().negate())
                      .collect(Collectors.toList());

Usamos el método ‘negate‘ que lo que hace es devolver la negación lógica de nuestro Predicate.

Y si queremos un filtro algo retorcido que nos devuelva los que no son humanos o usan espada:

List<BookCharacter> notHumanOrSwords =
        bookCharacters.stream()
                      .filter(isHuman().negate().or(useSword()))
                      .collect(Collectors.toList());

Aquí, además de ‘negate’, usamos el método ‘or‘, que hace un OR lógico con los dos Predicates.

Otra manera de usar nuestros Predicate podría ser tener un método que recibe, entre otras cosas, ese Predicate, por ejemplo:

public class BookCharacterChecker {

    public void doSomeStuffIfThisAndValid(BookCharacter bChar,
                                          Predicate<BookCharacter> predicate) {
        if (predicate.and(BookCharacterPredicate.isValid()).test(bChar)) {
            // do some stuff
            System.out.println("doing stuff with result true");
        } else {
            // do other stuff
            System.out.println("doing stuff with result false");
        }
    }
}

...

BookCharacter gandalf =
        new BookCharacter("Gandalf", Integer.MAX_VALUE, Weapon.STAFF, false);
BookCharacterChecker bookCharacterChecker = new BookCharacterChecker();

bookCharacterChecker.doSomeStuffIfThisAndValid(gandalf, bChar -> bChar.getAge() > 90);

En este caso, recibimos la lambda como parámetro, un Predicate, realizamos un and con otro Predicate y hacemos una cosa u otra según se cumpla.

Bonus: método estático isEqual

La interfaz Predicate tiene también un método static ‘isEqual‘, que devuelve un Predicate. Nos sirve para crear Predicates para comprobar igualdad. Por ejemplo:

BookCharacter aragorn = new BookCharacter("Aragorn", 88, Weapon.SWORD, true);
Predicate<BookCharacter> equalToAragorn = Predicate.isEqual(aragorn);

List<BookCharacter> allExceptAragorn =
        bookCharacters.stream()
                      .filter(equalToAragorn.negate())
                      .collect(Collectors.toList());

Aquí creamos con el método ‘isEqual‘ un Predicate que evalúe si un objeto es igual al personaje Aragorn. Luego filtramos nuestro stream negándolo, luego el List resultante debería devolver todos excepto Aragorn.

Hasta aquí por hoy, todo el código del post está en mi github, proyecto java8-predicate-methods-example.