Una vez escritos Pelicula, PeliculaRepository, PeliculaService y @CheckPeliculaValidation, y probados con Junit5 y @DataJpaTest el servicio, podemos empezar a construir el Controller, y probarlo con Postman
En esta visión, mejoraremos un poco las cosas, aunque dejo para mas adelante una refactorización de todo el proyecto, el hacerlo así, os ayudará a comprender el siguiente paso.
Planteamiento del controlador
Estamos trabajando en una API, esto quiere decir que a salida, estamos enviando JSON con los datos, por lo que definimos nuestro controlador como @RestController, indicamos @CrossOrigin porque vamos a aceptar llamadas desde cualquier sitio, y añadimos @Validated, porque queremos que en el momento de recibir la informacion, se efectúe un filtrado según lo que indiquemos en la entity; con eso, nuestro inicio, tendrá esta forma
@CrossOrigin
@RestController
@RequestMapping("/api/pelicula")
@Validated
public class PeliculaController {
private final PeliculaService cDao;
private Map<String, Object> map = new LinkedHashMap<String, Object>();
public PeliculaController(PeliculaService peliculaService) {
this.cDao = peliculaService;
}
Como veis, hemos añadido que este controlador atenderá al path genérico «/api/pelicula»
Tambien hemos añadido la definición de dos campos que necesitaremos, el servicio y la respuesta que nosotros definimos así.
Respecto al servicio, fijaros que no he utilizado @Autowire, porque las últimas versiones empiezan a desaconsejarlo, y recibimos la inyección en el constructor.
Leer un registro
Cuando se quiera leer un único registro, podemos escribir
@GetMapping("/{id}")
public ResponseEntity<Map<String, Object>> leerUno(@CheckPeliculaValidation @PathVariable("id") Long id){
Optional<Pelicula> peli = cDao.leerUno(id);
map.put(Constantes.STATUS, 1);
map.put(Constantes.DATOS, peli.get());
return new ResponseEntity<>(map, HttpStatus.OK);
}
Naturalmente, el id que se ha de facilitar, debe existir en la tabla, por lo que podemos utilizar el @CheckPeliculaValidation para que lo verifique, entonces, cuando hacemos el «leerUno«, sabemos que existe seguro, ya que si no, hubiera salido por excepción,.
Podríamos extraer el Optional allí mismo, aunque lo hacemos cuando cargamos los datos; luego preparamos la respuesta OK, porque la Error salta como excepción, y ya tenemos leido el registro.
Leer todos los registros
De momento, vamos a preparar el metodo sin paginación…. más adelante haremos otras cosas
@GetMapping({ "", "/" })
public ResponseEntity<Map<String, Object>> leerTodos() throws ControllerException {
List<Pelicula> pelis = cDao.listarTodos();
if (!pelis.isEmpty()) {
map.put(Constantes.STATUS, 1);
map.put(Constantes.DATOS, pelis);
return new ResponseEntity<>(map, HttpStatus.OK);
} else {
throw new ControllerException("No existen datos");
}
}
Según vimos en el servicio, vamos a devolver una lista, que puede estar vacía si no hay registros,entonces podemos hacer algo como esto
- Leemos el registro
- Si hay datos, los enviamos a salida
- Si no hay datos, comunicamos un error
Nuestro controlador de errores (ControllerAdvice o RestControllerAdvice), se encargará de traducir el mensaje como nos interese.
Realizar un insert
Segun las normas, en una API full-Rest, deberemos utilizar un POST, a la dirección principal, añadiendo los datos del alta, pues nuestro código será:
@PostMapping
public ResponseEntity<Map<String, Object>> alta(@Valid @RequestBody Pelicula p)
throws DomainException, ControllerException, DAOException {
p.setId_pelicula(0);
try {
Pelicula pdb = cDao.insert(p);
map.put(Constantes.STATUS, 1);
map.put(Constantes.DATOS, pdb);
return new ResponseEntity<>(map, HttpStatus.CREATED);
} catch (Exception ex) {
throw new ControllerException("Error al hacer la insercion " + ex.getMessage());
}
}
Como detalle, recogemos lo que devuelve el Insert, ya que será el mismo objeto que hemos enviado MAS la id, que como es autogenerada, puede ser cualquiera.
Tambien, señalar que seteamos el id a 0, precisamente para que se autogenere la clave, ya que si fuera algun valor, se intentaría dar de alta el objeto con ese valor….
Tambien hemos pedido que se verifique el objeto recibido, según las especificaciones del Entity, lo hemos hecho, por medio de la anotación de @Valid.
Estamos atentos a cualquier excepción, y la transformamos en una ControllerException, para organizar nuestra salida de errores.
La modificación
Nuestro servicio, responde al PUT que es la modificación de todo el objeto, y al PATCH que es la modificación de parte del objeto, por lo que debemos decidir cómo queremos trabajar, ya que hay un monton de variables implicadas, como por ejemplo, filtros.
En este caso, y dado los pocos atributos, utilizamos el PUT
@PutMapping("")
public ResponseEntity<Map<String, Object>> update(@Valid @RequestBody Pelicula p)
throws ConstraintViolationException, ControllerException {
try {
cDao.update(p);
map.put(Constantes.STATUS, 1);
map.put(Constantes.DATOS, p);
return new ResponseEntity<>(map, HttpStatus.OK);
} catch (Exception ex) {
throw new ControllerException("Error al hacer la actualizacion " + ex.getMessage());
}
}
Solo garantizamos que el objeto esté bien formado, por medio de la anotación de @Valid, y las anotaciones del entity, y podemos mandarlo a grabar, estando atentos a cualquier excepción que nos de…
Borrado de registro
Para el borrado, nos deben facilitar el Id, y ese id ha de existir, por lo que lo podemos someter a una validación con @CheckPeliculaValidation, y si pasa, no deberia dar mas problemas; en cualquier caso, podrían aparecer excepciones debido a dependencias, por lo que estamos atentos a ellas.
@DeleteMapping("/{id}")
public ResponseEntity<Map<String, Object>> borrar(@CheckPeliculaValidation @PathVariable("id") Long id)
throws ControllerException {
try {
cDao.borrarPorId(id);
map.put(Constantes.STATUS, 1);
map.put(Constantes.MENSAJE, "Registro eliminado");
return new ResponseEntity<>(map, HttpStatus.OK);
} catch (Exception ex) {
throw new ControllerException("Error al hacer la eliminacion " + ex.getMessage());
}
}
Probando con Postman
Ya podemos poner todo en marcha, para realizar una pequeña prueba en Postman, en mi caso, arranco Postman y un docker con una base de datos Oracle23 Express, y mi programa:
En Postman, ya hemos preparado algunos casos… realmente, los hicimos mientras escribíamos código, para irnos asegurando que todo iba bien, pero vamos a realizar una revisión ahora
Empezamos con un listar todo para ver lo que tenemos en nuestra base de datos
Nos devuelve dos registros, pues podemos añadir uno más
Vemos que nos creara uno con id 1102, si quereis, podemos utilizar el ver todos, para asegurarnos que está grabado
Ahora podemos modificarlo
Podemos utilizar el VerUno, para comprobar la modificación
y, por último, comprobamos el borrado
Y con este caso, nos damos cuenta que hay un error, ya que en un mensaje, segun nuestro diseño, nunca deberia aparecer data y mensaje en el mismo JSON….
El error es facil, pero os lo dejo a vosotros. Yo lo modificar en Github, pero…….
Tambien debemos recordar probar los casos de error, por ejemplo, si intentamos volver a borra el 1102
O intentamos leer uno que no existe
O añadir uno incompleto…
Y, aunque luego prepararemos nuestra prueba Junit, ya nos empezamos a hacer una idea de como funcionara nuestro trabajo.
Conclusión
Todo este desarrollo lo tendréis explicado con más detalle en youTube, en este artículo lo vereis, y, aunque es conveniente que intentéis escribirlo TODO vosotros, si queréis renunciar a ello, lo teneis tambien en GitHub
Este desarrollo esta hecho para disponer de un fuente para explicar otros temas, tal y como se indica en Visión de conjunto con Spring
En YouTube
Relacionado
Descubre más desde Recursos para formacion
Suscríbete y recibe las últimas entradas en tu correo electrónico.