30 de abril de 2020

Exponer metodo con @RepositoryRestController

En la entrada anterior hemos añadido un método personalizado a nuestro repositorio para una consulta más compleja que las que nos resuelve JPA en automático. Incluso luego la hemos optimizado utilizando datos cacheados en memoria.

Pero para que los usuarios de la API puedan utilizarlo hace falta exponerla. Esto no es automático, si revisamos los links generados por HATEOAS no aparecerá. La funcionalidad está en la capa de persistencia pero no es parte de la interfaz de la API.

Lo tradicional es tener un @Controller donde se indica el @RequestMapping que corresponda para conducir la llamada HTTP hasta el método concreto y derivar a un @Service. Más adelante veremos con más detalle y compararemos esta forma con la que vamos a usar aquí. Ahora quiero centrarme en la forma de hacerlo con Data Rest.

En esta entrada se va a utilizar la anotación @RepositoryRestController para continuar dentro del módulo Data Rest. El javadoc lo deja muy claro:

Anotación para marcar los controladores Spring MVC proporcionados por Spring Data REST. Permite detectarlos fácilmente y excluirlos del manejo estándar de Spring MVC.
Esta anotación sólo debe ser utilizada por los controladores de aplicaciones que se asignan a los URI administrados por Spring Data REST, ya que los maneja una implementación especial que aplica funcionalidad adicional.

Esto la convierte en el camino correcto y así lo indica la documentación. Lamentablemente la documentación no está actualizada y sigue utilizando el HATEOAS antiguo (Resource/s) así que aquí se va a ver cómo hacerlo migrado ya a la versión actual.

Me creo una clase PartidoController en mi paquete de rest con el siguiente código:
@RepositoryRestController
public class PartidoController {

    private PartidoDAO partidoDAO;

    PartidoController(PartidoDAO partidoDAO) {
        this.partidoDAO = partidoDAO;
    }

    @GetMapping("/partidos/search/con-nombre-participante")
    @ResponseBody
    public CollectionModel<PersistentEntityResource> getPartidosConParticipanteComo(@RequestParam String txt,
            PersistentEntityResourceAssembler assembler) {
        List<PartidoConId> partidos = partidoDAO.getEventosConParticipanteConTexto(txt);

        return assembler.toCollectionModel(partidos);
    }

}
Al marcar la clase se excluyen de la gestión de Spring MVC (la que usa @RestController por ejemplo) y pasan a ser gestionados por Data Rest. Con ello se consigue:
  1. El controlador utilizará la configuración basePath de Data Rest (en nuestro caso /api)
  2. Se podrá inyectar en sus métodos el objeto PersistentEntityResourceAssembler. Este objeto va a permitir la creación de EntityModel o CollectionModel (lo que sustituye a Resource/s) en función de si hay que representar un elemento o una colección de elementos. Así la representación será la misma que la que se genera para el resto de métodos, dando consistencia a la API.
Hay otras dos anotaciones necesarias según se ve en la documentación:
  • @GetMapping: usamos esta anotación que equivale a @RequestMapping(method=GET,...). Ambas sirven para indicar el endpoint que dirigirá hasta el método. La ruta la ponemos sin el basePath. Si se pone a nivel de clase el fragmento afecta a todos los mapeos internos.
  • @ResponseBody: significa que el método devuelve una respuesta web. Si no se pone no se expondrá el endpoint. También se puede poner a nivel de clase para que todos los métodos de dentro tomen ese valor por defecto.

Ahora al arrancar la API podemos probar ese endpoint y ver que existe y funciona correctamente. Sin embargo si acudimos a /partidos/search no se va a mostrar y no se puede autodescubrir. En la próxima entrada vamos a ver cómo añadir este nuevo endpoint a los link de /partidos/search.

Puedes encontrar el código hasta aquí en su repositorio.

No hay comentarios:

Publicar un comentario

Compárteme

Entradas populares