in JEE, RestTemplate, Spring, Uncategorized

Consumindo servicio REST con RestTemplate

Breve

Hace unas semanas atrás, toco realizar una asesoría, una de las funcionalidades fue consumir una API del tipo RESTFul, el requisito tenía que ser dentro de una aplicación Spring. Surgió la idea, de hacer algo bastante simple; gracias a la gente de icndb.com  que tuvieron una idea muy nerd cool; crearon “The Internet Chuck Norris Database” que provee una sencilla api para obtener bromas del famoso y todopoderoso personaje.

Representando un objeto de respuesta.

Las bromas están disponibles en https://api.icndb.com, para consumirlas tenemos diferentes opciones y formas, una de ellas es realizar una llamada vía GET a la URI ; el resultado es una o mas bromas en formato JSON(por defecto), cuya estructura de datos será como la siguiente:

{
  "type": "success",
  "value": {
    "id": 355,
    "joke": "In the X-Men movies, none of the X-Men super-powers are done with special effe             cts. Chuck Norris is the stuntman for every character.",
    "categories": []
  }
}

El type será “success” cuando logremos obtener una broma, y alguna otra cosa rara exception cuando algo salga mal… Podemos ver que el elemento value es una array, contiene 3 elementos, el primero es el id del tipo numérico,  el segundo llamado joke, contiene la broma, y el tercer elemento es una lista de categories[nerdy,explicit] con esta estructura, ya podemos construir nuestro objeto que representará  una respuesta.

JokeResponse.java clase que representa una respuesta, contiene un type y una lista de l tipo Joke.

public class JokeResponse {

  private String type;
  private List<Joke> value;

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }

  public List<Joke> getValue() {
    return value;
  }

  public void setValue(List<Joke> value) {
    this.value = value;
  }
}

Joke.java  contiene, el id, la broma y una lista de categorias.

public class Joke {
  private int id;
  private String joke;
  private List<?> categories;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getJoke() {
    return joke;
  }

  public void setJoke(String joke) {
    this.joke = joke;
  }

  public List<?> getCategories() {
    return categories;
  }

  public void setCategories(List<?> categories) {
    this.categories = categories;
  }
}
Invocando a la API

Para consultar a la api,utilizaremos el recurso /jokes en la URI   http://api.icndb.com/jokes quien nos proveerá la lista completa de jokes como se muestra a continuación:

curl -v http://api.icndb.com/jokes
*   Trying 104.31.82.58...
* Connected to api.icndb.com (104.31.82.58) port 80 (#0)
> GET /jokes HTTP/1.1
> Host: api.icndb.com
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 23 Sep 2016 03:22:48 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=d22b2ab51c27a3943acd083fdbc187db11474600968; expires=Sat, 23-Sep-17 03:22:48 GMT; path=/; domain=.icndb.com; HttpOnly
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET
< Server: cloudflare-nginx
< CF-RAY: 2e6adfd3e1d652a2-MIAs
{ "type": "success", "value": [ { "id": 1, "joke": "Chuck Norris uses ribbed condoms inside out, so he gets the pleasure.", "categories": ["explicit"] }, { "id": 2, "joke":....
.....
...

Podemos ver que en la cabecera de la respuesta, el tipo de contenido (Content-Type) es application/json ,lo que indica que esta en un formato JSON; aprovecharemos esta misma llamada, para ejemplificar con la clase RestTemplate, como podemos consumir este servicio.

La clase RestTemplate

RestTemplate es la clase principal para el acceso por parte del cliente a  los servicios REST. Conceptualmente es similar a otras clases del tipo Template de Spring, como JdbcTemplate y JmsTemplate.

Una de las ventajas de utilizar RestTemplate, es que esta clase proporciona un nivel de abstracción mayor, quiere decir, que nos provee métodos de nivel superior para poder utilizar los principales métodos(GET,POST,PUT,DELETE,HEAD,OPTIONS) que posee el protocolo HTTP, esto permite que la invocación a los servicios RESTful se realice de manera mucho mas transparente y sencilla para el desarrollador, a continuación, métodos soportados por la version de spring 4.3.3.

HTTP Method RestTemplate Method
DELETE delete
GET getForObject
getForEntity
HEAD headForHeaders(String url, String… urlVariables)
OPTIONS optionsForAllow(String url, String… urlVariables)
POST postForLocation(String url, Object request, String… urlVariables)
postForObject(String url, Object request, Class<T> responseType, String… uriVariables)
PUT put(String url, Object request, String…urlVariables)
Utilizando RestTemplate

Se utilizó el framework de JUnit para realizar algunas pruebas, específicamente la clase RestClientTest.java , que contiene casos de prueba como el siguiente:

final static String BASE_API = "http://api.icndb.com/jokes";
RestTemplate restTemplate;
.... 
@Test
public void testAPI() {
    JokeResponse response = restTemplate.getForObject(BASE_API, JokeResponse.class);
    List<Joke> jokes = response.getValue();
    assertNotNull(response);
    assertEquals(response.getType(), "success");
    assertNotNull(jokes);
    assertTrue(jokes.size() > 0);
}

El metodo getForObject()  recupera y transforma la respuesta del servidor en una representación de la clase JokeReponse  después de haber realizado una llamada del método GET en la URL http://api.icndb.com/jokes, permitiendo obtener una lista de bromas  List<Joke> .

Pasando Variables a la URI

La api, nos permite obtener una lista de bromas aleatoria y desde una categoría especifica, para eso necesitamos acceder a la URI  /random/{limit}?limitTo=[{category}]en donde {limit} y {category} son los valores a reemplazar, utilizaremos el método getForObject() pasando un HashMap con los valores: getForObject(String url, Class<T> responseType, Map<String, ?> urlVariables)

@Test
public void testAPIQueryParams() {
    String query = "/random/{limit}?limitTo=[{category}]";

    HashMap<String, Object> params = new HashMap<>();
    params.put("limit", 10);
    params.put("category", "nerdy");

    JokeResponse response = restTemplate.getForObject(BASE_API + query, JokeResponse.class, params);
    List<Joke> jokes = response.getValue();
    assertNotNull(response);
    assertEquals(response.getType(), "success");
    assertNotNull(jokes);
    assertEquals(jokes.size(), 10);
}

Otra forma mas sencilla, es pasar valores en forma de objetos:  getForObject(String url, Class<T> responseType, Object... urlVariables en donde {limit} y {category}  son reemplazados por los valores 3 y “nerdy“, lo que permite obtener 3 listas de bromas aleatorias de la categoría nerdy.

@Test
public void testAPIQueryParams2() {
    String query = "/random/{limit}?limitTo=[{category}]";

    JokeResponse response = restTemplate.getForObject(BASE_API + query, JokeResponse.class, 3, "nerdy");
    List<Joke> jokes = response.getValue();
    assertEquals(jokes.size(), 3);
}

 

El código completo esta disponible en github

 

Write a Comment

Comment