API REST 4. Calidad al implementar aplicacion Web

Contenido

Introducción

Existen 3 niveles para aplicar API REST en el desarrollo de una Aplicación Web.
Cumplir con estás nos garantiza las mejores practicas para su implementación, integración, estabilidad y escabilidad.
Para detalles se puede consultar  http://asiermarques.com/2013/conceptos-sobre-apis-rest/

Nivel 1. Uso correcto de URIs

  1. Identificar de forma única el recurso
  2. Las URI no deben contener acciones
  3. Independientes del formato
  4. Jerarquía lógica
  5. Los filtrados no se deben hacer en la URI

Nivel 2. HTTP

  1. Usar métodos HTTP; GET, POST, PUT, DELETE y PATCH
  2. Código de estado
  3. Aceptación de tipos de contenido

Nivel 3. Hypermedia

Se vera mas a detalle posteriormente.

Con lo que llevamos hasta este momento, podemos generar un proyecto de API REST en Web con las mejores practicas.
Vamos a retomar la tabla Persona y crear un Sistema Web con API REST para administrar personas; crear, leer, actualizar y eliminar.

Construir aplicación

Crear proyecto

Ir a

File -> New -> Other… -> Spring Boot -> Spring Starter Project

Seleccionamos nombre del proyecto, tipo, versión de java, paquete, entre otras opciones. Clic en Next>. Seleccionamos la versión de Spring Boot y las dependencias:

  1. JPA
  2. H2
  3. MySQL
  4. Web

Clic en Next> y posteriormente clic en Finish.

Crear paquetes

Creamos los paquetes

  • com.mio.administrar.controller
  • com.mio.administrar.repository
  • com.mio.administrar.entity

Copiar clases e interfaces

Tomando las clases e interfaces del proyecto anterior https://github.com/arielolivagh/gs-rest-service-complete/tree/v2.0  copiamos:

  • La clase PersonaController al paquete com.mio.administrar.controller
  • La interface PersonaRepository al paquete com.mio.administrar.repository
  • La clase Persona al paquete com.mio.administrar.entity

Conexión a la Base de Datos

Escribimos los parámetros de conexión a la Base de Datos en el archivo application.properties.

spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/Pruebas
spring.datasource.username=root
spring.datasource.password=root

Crear consulta para búsqueda de personas por id

En la clase repository vamos a crear un nuevo query para obtener una persona por su id.

@Query("select p from Persona p where p.idPersona = ?1")
Persona findPersona(int id);

Crear controller de calidad

Crear personas

  • Método POST
  • La respuesta es Json
  • Documentación JavaDoc
    /**
     * Crea una persona: POST http://{servidor}:{puerto}/persona
     * @param nombre Nombre de la persona
     * @param edad Edad de la persona
     * @param sexo Sexo de la persona
     * @return mensaje de 'Agregado correctamente'
     */
    @RequestMapping(method=RequestMethod.POST,produces={"application/json"})
    public String createPersona(@RequestParam String nombre,@RequestParam int edad,@RequestParam String sexo) {
            Persona p = new Persona();
    	p.setNombre(nombre);
    	p.setEdad(edad);
    	p.setSexo(sexo);
    	personaRepository.save(p);
    		
            return "Agregado correctamente";
    }

    Consumir:

    curl -i -X POST -d "nombre=Mariel&edad=51&sexo=F" http://localhost:8080/persona

Leer todas las personas

  • Método GET
  • La respuesta es Json
  • ocumentación JavaDoc
    /**
     * Obtiene todas las personas: GET http://{servidor}:{puerto}/persona
     * @return Lista de personas
     */
     @RequestMapping(method=RequestMethod.GET,produces={"application/json"})
        public Iterable<Persona> readPersonas() {
        return personaRepository.findAll();
     }

    Consumir:

    curl -i -X GET http://localhost:8080/persona

Leer una persona

  • Método GET
  • La respuesta es Json
  • Documentación JavaDoc
    /**
     * Obtiene una person por id: GET http://{servidor}:{puerto}/persona/{id}
     * @param id Id de la persona. En la Url
     * @return Una personas
     */
     @RequestMapping(value="/{id}",method=RequestMethod.GET,produces={"application/json"})
        public Persona readPersonaById(@PathVariable("id") int id) {
        return personaRepository.findPersona(id);
     }

    Consumir:

    curl -i -X GET http://localhost:8080/persona/7

Actualiza una persona

  • Método PUT
  • La respuesta es Json
  • Documentación JavaDoc
    /**
     * Actualiza una persona por Id: PUT http://{servidor}:{puerto}/persona/{id}
     * @param id Id de la persona. En la Url
     * @param nombre Nombre de la persona
     * @param edad Edad de la persona
     * @param sexo Sexo de la person
     * @return mensaje de 'Actualizado correctamente'
     */
     @RequestMapping(value="/{id}",method=RequestMethod.PUT,produces={"application/json"})
     public String updatePersona(@RequestParam String nombre,@RequestParam int edad,@RequestParam String sexo,@PathVariable("id") int id) {
        Persona p = new Persona();
        p.setIdPersona(id);
        p.setNombre(nombre);
        p.setEdad(edad);
        p.setSexo(sexo);
        personaRepository.save(p);
        return "Actualizado correctamente";
     }

    Consumir:

    curl -i -X PUT -d "nombre=Ariel&edad=100&sexo=M" http://localhost:8080/persona/7

Actualiza edad de una persona

  • Método PATCH
  • La respuesta es Json
  • Documentación JavaDoc
    /**
     * Actualiza la edad de una persona por Id: PATCH http://{servidor}:{puerto}/persona/{id}
     * @param id Id de la persona. En la Url
     * @param edad Edad de la persona
     * @return mensaje de 'Actualizando la edad correctamente'
     */
     @RequestMapping(value="/{id}",method=RequestMethod.PATCH,produces={"application/json"})
     public String updateParcialPersona(@PathVariable("id") int id,@RequestParam int edad) {
        Persona p = personaRepository.findPersona(id);
        p.setEdad(edad);
        personaRepository.save(p);
        return "Actualizando la edad correctamente";
     }

    Consumir:

    curl -i -X PATCH -d "edad=10" http://localhost:8080/persona/7

Elimina todas las personas

  • Método DELETE
  • La respuesta es Json
  • Documentación JavaDoc
    /**
     * Elimina todas las personas: DELETE http://{servidor}:{puerto}/persona
     * @return mensaje de 'Todo eliminado correctamente'
     */
     @RequestMapping(method=RequestMethod.DELETE,produces={"application/json"})
        public String deleteAllPersona() {
        personaRepository.deleteAll();
        return "Todo eliminado correctamente";
     }

    Consumir:

    curl -i -X DELETE http://localhost:8080/persona

Elimina una persona

  • Método DELETE
  • La respuesta es Json
  • Documentación JavaDoc
    /**
     * Elimina una persona por id: DELETE http://{servidor}:{puerto}/persona/{id}
     * @param id Id de la persona. En la Url
     * @return mensaje de 'Eliminado correctamente'
     */
     @RequestMapping(value="/{id}", method=RequestMethod.DELETE,produces={"application/json"})
     public String deletePersona(@PathVariable("id") int id) {
        Persona p = new Persona();
        p.setIdPersona(id);
        personaRepository.delete(p);
        return "Eliminado correctamente";
     }

    Consumir:

    curl -i -X DELETE http://localhost:8080/persona/7

Otras

Descargar proyecto

Se puede descargar el proyecto completo de https://github.com/arielolivagh/administrarPersona/tree/v1.0

2 comentarios en “API REST 4. Calidad al implementar aplicacion Web

  1. He visto muchas cosas que me han llamado la atención. Y quería comentar algunas para que la gente no copie los errores que veo aquí, sobretodo que no piensen que estamos haciendo un «controller de calidad» siguiendo estos pasos.

    En cuanto al controlador:
    Nunca puede haber una respuesta de un json con un simple String hardcodeado en el propio método, como en createPersona el String que devuelves….»Agregado correctamente»
    Por otro lado, es confuso tener un método en el controlador llamado readPersonaById que devuelva una lista con todas las personas

    Repositorio:
    La query así de simple se podría hacer utilizando filtros de CrudRepository y deducir la consulta a partir del nombre, en este caso:
    Persona findById(id)

    Hay unos cuantos gazapos, creo que no estaría mal darle un repaso para evitar confundir a la gente que llega aquí buscando información de ayuda.

Deja un comentario