Implementación de una API REST completa (Parte II)

En esta segunda parte, Marco Naranjo nos enseña otros métodos que nos permitirán lograr una API REST completa. En concreto, profundizaremos acerca de PUT, PATCH y DELETE. Juntos, podremos ir aplicándolo a la práctica y terminaremos la API. ¿Os animáis?

    Artículo elaborado por:

    Marco Naranjo

    Software Engineer

    Analista Programador especializado en Java y Python. Apasionado de los gráficos 3D y con gran interés en Machine Learning e Inteligencia Artificial.

Introducción

En la primera parte de este artículo, cubrimos los métodos GET y POST en la implementación de una API REST, y explicamos cómo se utilizan para obtener recursos y enviar datos al servidor. Si aún no has leído esa parte, te recomendamos hacerlo antes de continuar, ya que allí establecimos las bases para lo que cubriremos a continuación.

En esta segunda parte, continuaremos donde lo dejamos y exploraremos otros métodos importantes en la implementación de una API REST completa. En particular, nos enfocaremos en los métodos PUT, PATCH y DELETE, que se utilizan para actualizar y eliminar recursos en el servidor.

El método DELETE

El método DELETE se utiliza para eliminar información al servidor. Dentro de la petición tenemos que tener en cuenta varios aspectos importantes:

  • El método no tiene payload, solo tiene los parámetros necesarios para encontrar el recurso a borrar.
  • Se utiliza para eliminar recursos, por tanto, se debe tener mucho cuidado con su uso.
  • Se debe tener cuidado pues una vez borrado el recurso no se puede recuperar.

Implementación del método DELETE

Para crear una implementación que siga la especificación indicada, vamos a seguir unos pasos similares al GET mediante ID. Primero buscamos el usuario por el ID indicado, si no está lanzamos excepción y si está lo borramos, quedaría así:

Implementación de una API REST completa (Parte II)
Primera implementación del método DELETE

Hay que darse cuenta del @DeleteMapping y del @PathVariable para que reciba mediante la URL el ID. Esta implementación casi sigue la especificación que queremos, lo único que nos faltaría sería devolver un 204 en lugar de un 200 cuando consigamos borrar el usuario, esto se consigue de forma muy sencilla añadiendo @ResponseStatus a la petición.

Implementación de una API REST completa (Parte II)
ResponseStatus añadido al método

La petición a realizar sería:

Implementación de una API REST completa (Parte II)
Petición DELETE y su respuesta

Como se puede observar, devuelve un 204 como debería sin contenido en el body, perfecto.

El método PUT

El método PUT se utiliza para actualizar al completo un recurso en el servidor. Dentro de la petición tenemos que tener en cuenta varios aspectos importantes:

  • El método tiene payload y este debe ser el recurso completo a actualizar.
  • Se utiliza para actualizar recursos al completo, es decir, se actualiza todo el recurso con los datos que se pasan.
  • Hay que tener cuidado pues si se pasa un id erróneo el recurso se creará.
  • No se debe confundir con PATCH

Implementación del método PUT

Para implementar el PUT, tenemos que utilizar @PutMapping y tenemos que pasar el id como @PathVariable, por otro lado, en el body tenemos que enviar el usuario a actualizar.

Implementación de una API REST completa
Encabezado del método

Con esto podríamos buscar el usuario por ID, si existe lo actualizamos y si no, lo insertamos.

Implementación de una API REST completa (Parte II)
En función de si es un usuario nuevo o no, el funcionamiento es distinto

Por último, filtramos y devolvemos el usuario.

Implementación de una API REST completa (Parte II)
Filtramos y devolvemos el usuario

Sin embargo, nos faltaría responder con los estados correctamente tal y como se indica en la especificación, pues debemos responder con 201 cuando lo creamos (tal y como lo hacíamos en el POST) y con 200 (o 204) cuándo actualicemos. Para ello vamos a cambiar el objeto que devolvemos a ResponseEntity de MappingJacksonValue, puesto que es un cambio sencillo, os lo mostramos directamente.

Implementación de una API REST completa (Parte II)
Añadimos los filtros y hacemos que devuelva 200 o 201 en función de si se actualiza o se inserta

Podríamos llevar el filtro a una función pues lo estamos usando en varios de los métodos pero por claridad, ya que estamos viendo función a función, preferimos dejarlo así.

Ahora cuando se crea un usuario responde con un 201.

Implementación de una API REST completa (Parte II)

Hemos creado un nuevo usuario con el PUT devuelve 201

Hay que tener en cuenta que el ID con el que se inserta lo decide JPA.

Y cuando se actualiza devuelve el 200 sin contenido:

Implementación de una API REST completa (Parte II)
Si actualizamos el usuario devuelve un 200

El método PATCH

El método PATCH se utiliza para actualizar parcialmente un recurso en el servidor. Dentro de la petición tenemos que tener en cuenta varios aspectos importantes:

  • El método tiene payload y este debe indicar cómo debe cambiar el recurso.
  • Hay principalmente dos maneras de implementarlo, utilizaremos el JSON Patch.

El objeto que se manda en el payload es un JSON Patch, que se compone de una lista de cambios a realizar.

Ejemplo del objeto:

[{«op»:»replace»,»path»:»/birth_date»,»value»:»1998-05-05″}]

Es una lista de operaciones a realizar. Las posibles operaciones son “add”, “remove”, “replace”, “move”, “copy” y “test”, creemos que se entienden por su nombre, si queréis saber más, revisad las fuentes del artículo.

Implementación del método PATCH

La implementación del método PATCH es algo especial pues en nuestro caso, tenemos que usar un content type distinto, este sería “application/json-patch+json”. Pero vamos a ir poco a poco.

Primero tenemos que añadir las dependencias, para poder implementar este patch necesitamos estas dependencias:

Implementación de una API REST completa (Parte II)
Dependencia para una implementación más sencilla de JSON Patch

Esta dependencia nos permitirá usar el objeto de patch de forma muy sencilla.

Implementación de una API REST completa (Parte II)
Dependencia para usar fechas dentro del JSON Patch

Esta dependencia nos permitirá utilizar fechas dentro de ese objeto, muy útil para cambiar la fecha de nacimiento del usuario, por ejemplo.

El header de la función sería así:

Implementación de una API REST completa (Parte II)
Encabezado del método PATCH

Como siempre indicamos el tipo de la petición con @PatchMapping y en este caso, además indicamos el Content Type en el consumes. Usamos el @PathVariable para indicar que usuario vamos a editar y en el body de la petición vamos a recibir un JsonPatch.

Ahora, como vamos a editar un usuario, tenemos que recogerlo para luego aplicarle los cambios del objeto JsonPatch.

Implementación de una API REST completa (Parte II)
Funcionamiento básico de la función

Aplicar el jsonPatch es sencillo gracias a las dependencias que hemos añadido:

Implementación de una API REST completa (Parte II)
Aplicamos la conversión usando las dependencias que hemos añadido

Es importante filtrar el usuario antes de aplicarle el filtro, también podéis aplicarle un filtro vacío si queréis.

Como queríamos que esa función quedase “limpia” hemos declarado junto al constructor el objectMapper, al cual le hemos añadido en el constructor el módulo de tiempo para que funcione con las fechas.

Implementación de una API REST completa (Parte II)
Configuración para que el ObjectMapper trabaje bien las fechas

La función “applyPatchToUser” nos devolverá el usuario con los cambios indicados ya aplicados, por tanto podemos centrarnos en actualizar el usuario con un “save”, filtrarlo y devolver un 200 con el usuario actualizado.

Implementación de una API REST completa (Parte II)
Actualizamos el usuario y lo filtramos

Os dejamos la función completa por aquí:

Implementación de una API REST completa (Parte II)
Método PATCH completo

Así se vería la petición y la respuesta:

Implementación de una API REST completa (Parte II)
Petición y respuesta del método

Conclusión

En conclusión, los métodos HTTP en una API REST son esenciales para interactuar con los recursos en un servidor. Cada uno de estos métodos tiene un propósito y funcionalidad específica, juntos permiten a los clientes interactuar de forma clara y efectiva.

Esperamos que tanto la explicación de los métodos como su breve implementación os sirvan de ayuda en vuestras próximas API REST.

Por último, os proponemos un mini reto, ¿podéis crear los métodos para recoger y añadir Posts a los usuarios? Si has implementado esta API, comparte fotos de tu trabajo en las redes sociales y etiquétanos (@edicomgroup_hr). ¡Nos encantaría ver lo que has logrado!

Podéis revisar el proyecto completo aquí.

Fuentes