viernes, 3 de octubre de 2014

Consumiendo recurso JSON con Jersey + Jackson + Gradle

Esta semana empecé a trabajar con la herramienta de construcción Gradle y en esta ocasión quiero conmpartir mi experiencia con la herramienta gradle, más la deserialización de la respuesta Json a un modelo de objetos. Para consultar la configuración del cliente para el consumo del recurso REST ir a la entrada anterior.

Instalando gradle

Vamos a empezar instalando gradle. Para esto les comparto la liga que he utilizado para hacerlo en mi entorno de desarrollo. Una vez terminado el proceso verificamos nuestra versión instalada por medio del comando:

gradle -version

Creando la estructura del proyecto

Primero que nada Gradle espera que el código de nuestra aplicación se encuentre en la estructura src/main/java y el código de nuestras pruebas en src/test/java.

Además cualquier archivo colocado bajo src/main/resources será incluido en el archivo JAR como recurso y cualquie archivo colocado sobre src/test/resources será incluido en el classpath utilizado para correr las pruebas unitarias.

Todos los archivos de salida son colocados en el directorio de construción build/libs.

Bueno para empezar vamos a crear la siguiente estructura de directorios:

-- JerseyConsumer
  -- src
    -- main
   -- java
     -- mx
    -- org
      -- mi empresa
   -- resources
    -- test
   -- java
   -- resources

Listo ya tenemos la estructura requerida por gradle para la aplicación.

Creando el archivo de construcción gradle

Necesitamos ahora indicar la configuración de construcción para nuestra aplicación. Para eso vamos a crear los siguientes dos archivos en el directorio JerseyConsumer.

Archivos configuración gradle

Vamos a abrir el archivo build.gradle con nuestro editor favorito y agregamos el siguiente bloque de código:

apply plugin: 'java'

repositories {
 mavenCentral()
}

dependencies {
 compile group:'org.glassfish.jersey.core', name:'jersey-client', version:'2.11'
        compile group:'org.glassfish.jersey.media', name:'jersey-media-json-jackson', version:'2.11'
 compile group:'org.apache.commons', name:'commons-lang3', version:'3.1'
}

task execute(type:JavaExec) {
   main = 'mx.org.miempresa.RestConsumer'
   classpath = sourceSets.main.runtimeClasspath
}

Algunas notas importantes el archivo de configuración:

  • apply plugin. Indica que trabajaremos con el plugin de java para gradle. Viene con la instalación por default de gradle.
  • repositories. Indicamos que utilizaremos el repositorio central de dependencias de maven. Es una de las razones por las que me gusta gradle, que permite utilizar varios repositorios de dependencias.
  • dependencies. Indica las dependencias de la aplicación. En este caso jersey-client (consumo recursos), jackson (deserialización de json response), commons-lang3 (utilerías para el API java.lang)
  • task execute. En gradle podemos utilizar las tareas proporcionadas por el pluging o crear nuevas extendiendo las existentes. En este caso extendemos la tarea JavaExec para pasarle el parámetro main (clase con el método main) y el classpath donde encontrará las dependencias.

Vamos a abrir el archivo gradle.properties con nuestro editor favorito y agregamos la siguiente configuración:

org.gradle.java.home=C:\\Program Files (x86)\\Java\\jdk1.7.0.67

En este archivo indicamos el jdk de java a utilizar para compilar nuestra aplicación.

Consumiendo el recurso y deserializando JSON a objetos:

Vamos a crear la clase RestConsumer en el paquete mx.org.miempresa

package mx.org.miempresa;

import java.util.List;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.jackson.JacksonFeature;

public class RestConsumer 
{
    public static void main(String[] args) {
        int idCliente = 23;
        
        ClientConfig cc = new ClientConfig().register(new JacksonFeature());
        Client client = ClientBuilder.newClient(cc);
        WebTarget rootTarget = client
                .target("http://cmoralesflap:8080/MiServicio/");
        WebTarget pagosTarget = rootTarget.path("pagos").path("{idCliente}")
                .resolveTemplate("idCliente", idCliente);

        Invocation.Builder builder = pagosTarget.request(MediaType.TEXT_PLAIN);
        builder.accept(MediaType.APPLICATION_JSON);
        
        List<Pago> pagoResponse = 
                builder.get().readEntity(new GenericType<List<Pago>>(){});
        
        for(Pago pago : pagoResponse) {
            System.out.println("Pago " + pago);    
        }
        
        client.close();         
    }
}

Algunas notas importantes el archivo de configuración:

  • List pagoResponse. Ahora la respuesta esperada es una lista de objetos Pago.
  • readEntity(new GenericType<List<Pago>>(){}). Indicamos que esperamos una lista de objetos.

Nota. He modificado el recurso REST para que me devuelva una colección de Pagos. A continuación adjunto los cambios requeridos en el recurso publicado.

@Path("pagos/{idCliente}")
public interface IPagoResource {
    @GET
    @Produces("application/json")
    List getPagoByIdCliente(@PathParam("idCliente") int idCliente);
}

public class PagoResource implements IPagoResource {
    public List<Pago> getPagoByIdCliente(int idCliente) {
        List<Pago> pagos = new ArrayList<Pago>();
        pagos.add(new Pago (23, new BigDecimal("520.56")));
        pagos.add(new Pago (23, new BigDecimal("380.08")));
        return pagos;
    }
}


Ahora creamos la clase Pago en el paquete mx.org.miempresa

package mx.org.miempresa;

import java.math.BigDecimal;
import org.apache.commons.lang3.builder.ToStringBuilder;

public class Pago {
    private int id;
    private int idCliente;
    private BigDecimal cantidad;

    public Pago() {
    }

    public int getIdCliente() {
        return idCliente;
    }

    public void setIdCliente(int idCliente) {
        this.idCliente = idCliente;
    }

    public BigDecimal getCantidad() {
        return cantidad;
    }

    public void setCantidad(BigDecimal cantidad) {
        this.cantidad = cantidad;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
    
    @Override
    public String toString() {
        return new ToStringBuilder(this).append("idCliente", idCliente)
                .append("cantidad", cantidad).toString();
    }
}

Compilando la aplicación:

Para compilar la aplicación ejecutamos el siguiente comando:

gradle build

Ejecutando la aplicación:

Para ejecutar la aplicación ejecutamos el siguiente comando:

gradle execute
Ejecutando la aplicación

Bueno, hasta aquí terminamos el consumo del recurso REST. En la siguiente entrada veremos como crear filtros e interceptores.

No hay comentarios:

Publicar un comentario