Si creeis que con lo explicado hasta el momento, habíamos dejado claro todas las posibilidades que encierra la validación en Spring… estais equivocados. Si, como temíais, hay muchas mas, y, aunque no vamos nunca a poder explicarlas todas, si que podemos dejar claro algunas cosas mas, y, espero que en este articulo queden claras …. o casi……
(En github, encontrareis una serie de modificaciones en cuanto a nombres de paquetes, sugeridas por Ramiro May, al que le agradezco su colaboracion.)
Validación de datos recibidos en PathVariable
Hasta ahora hemos visto como podemos filtrar los datos recibidor por el «body» de un controlador, a traves de la anotacion @Valid, pero eso dejaba sin verificar los casos en que nosotros recibiamos los datos como PathVariable… bien, veamos como puedo filtrar lo que me llega por ese camino. He utilizado el CRUD de cine para hacer el ejercicio; alli me encuentro con que en el @GetMapping(«/{id}»), necesito que el id que me indican exista en la BBDD, y, en la version original, me molesto en estar atento a dos Exception y genero una si no existe.
Veamos, realmente lo que podemos hacer utilizando la anotación @CheckCineValidation que creamos en Añadiendo un filtro de comprobación de existencia en tabla por anotaciones, en Spring
Deberemos anotar la clase como @Validated
@CrossOrigin
@RestController
@RequestMapping("/api/cine")
@Validated
public class CineController {
private final CineService cDao;
CineController(CineService cDao) {
this.cDao = cDao;
}
y, a continuación, podemos añadir la anotacion de filtro, cuando pedimos el id. Incorporo el método entero, para ver la simplificación que representa
@GetMapping("/{id}")
public ResponseEntity<Map<String, Object>> leerUno(@PathVariable("id") @CheckCineValidation Long id) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
Optional<Cine> cineDB = cDao.leerUno(id);
map.put("status", 1);
map.put("data", cineDB.get());
return new ResponseEntity<>(map, HttpStatus.OK);
}
Cuando intenten acceder a un cine que no existe, se dispara una excepción ConstraintViolationException y en Postman, se vería asi:
Vale, no es demasiado bonito, pero, podemos modificar nuestro @ControllerAdvice añadiendo un nuevo método para que controle la excepción generada
@ResponseStatus(code = HttpStatus.UNPROCESSABLE_ENTITY)
@ExceptionHandler(value = { jakarta.validation.ConstraintViolationException.class,
org.hibernate.exception.ConstraintViolationException.class })
public Map<String, Object> gestionConstraint(ConstraintViolationException ex) {
Map<String, Object> errores = new HashMap<String, Object>();
errores.put("status", 900);
Map<String, String> listaErrores = new HashMap<String, String>();
ex.getConstraintViolations().forEach(error -> {
String nombreCampo = error.getPropertyPath().toString();
String mensaje = error.getMessage();
listaErrores.put(nombreCampo, mensaje);
});
errores.put("lista", listaErrores);
return errores;
}
y ya tenemos mejorado el mensaje de error
Solo nos queda añadir esa comprobacion, alli donde la necesitemos, por ejemplo en el DELETE
@DeleteMapping("/{id}")
public ResponseEntity<Map<String, Object>> eliminar(@CheckCineValidation() @NotNull @PathVariable("id") Long id) throws ControllerException {
Map<String, Object> map = new LinkedHashMap<String, Object>();
try {
cDao.deleteById(id);
map.put("status", 1);
map.put("message", "Registro borrado");
return new ResponseEntity<Map<String, Object>>(map, HttpStatus.OK);
} catch (Exception ex) {
throw new ControllerException("Error al borrar");
}
throw new ControllerException("No existe registro al borrar");
}
Y ya conseguimos que controle la entrada
Conclusión
Todo este desarrollo lo teneis explicado con mas detalle en youTube (a partir de10/02/24) , 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
Relacionado
Descubre más desde Recursos para formacion
Suscríbete y recibe las últimas entradas en tu correo electrónico.