Spring Boot Aplicacion Web Parte 5.

Crear Usuario y Validacion de campos

Necesitaremos un método en el controlador que reciba el formulario, lo valide, guarde el usuario y retorne una respuesta a la vista.

Este metodo recibira mas que Model como parametro, necesitara un objeto User que tendra mapeado todos los campos del formulario y un objecto con el resultado de la validacion del formulario.


Contenido

  1. Agregar Validacion a la entidad Usuario.
  2. Agregar mensajes de error al HTML.
  3. Crear metodo en el controlador.
  4. Crear Servicio para guardar usuario.
  5. Arreglar Formulario HTML.
  6. Git Commit.
  7. Video Paso a Paso.

1.Agregar Validacion

Para usar el BindingResult cuando tratamos de crear un usuario, necesitaremos anotar los campos que queramos validar. Hay una gran lista de anotacions que se pueden usar, puedes encontrar mas informacion en este link (click aqui).

Utilizaremos solo dos (@NotBlank, @Email) en nuestro ejemplo pero puedes probar los que quieras.

*@NotBlank: El valor no puede ser null y debe contener al menos un caracter que no sea espacio.
*@Email: Valida que el valor ingresado tenga el formato valido de email.

	@Column 
	@NotBlank
	private String firstName;
	
	@Column 
	@NotBlank
	private String lastName;
	
	@Column(unique = true) 
	@Email 
	@NotBlank
	private String email;
	
	@Column(unique = true) 
	@NotBlank
	private String username;
	
	@Column 
	@NotBlank
	private String password;

2.Agregar mensajes de error

Inmediatamente debajo de cada campo de texto deberas colocar la siguiente linea de codigo, que solo aparecera si hay un error para ese campo.

<div class="alert-danger" th:if="${#fields.hasErrors('Nombre_del_atributo')}" th:errors="*{Nombre_del_atributo}">Name Error</div>

Como resultado todos tus campos se deberian de ver de la siguiente manera

<div class="form-group row">
	<label class="col-lg-3 col-form-label 	form-control-label">First name</label>
	<div class="col-lg-9">
		<input class="form-control" type="text" th:field="${userForm.firstName}" th:disabled="${disableFields}">
		<div class="alert-danger" th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}">Name Error</div>
	</div>
</div>

3.Crear metodo en el Controlador.

Para este metodo necesitaremos agregar mas que el modelo a la firma como lo hicimos en el metodo anterior, esta vez recibiremos 2 parametros mas, uno que es el usuario mapeado desde el formulario y el otro sera el resultado de ese mapeo.

<span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">"/userForm"</span><span class="token punctuation">)<br></span><span class="token keyword">public</span> String <span class="token function">postUserForm</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Valid</span> <span class="token annotation punctuation">@ModelAttribute</span><span class="token punctuation">(</span><span class="token string">"userForm"</span><span class="token punctuation">)</span>User user<span class="token punctuation">,</span> BindingResult result<span class="token punctuation">,</span> ModelMap model<span class="token punctuation">)</span> 
Java
  • @PostMapping: Indica que para acceder a este metodo debe ser utilizando un llamado POST y no GET, ademas que la ruta debe de ser /userForm
  • @Valid: Indica Spring que verifique los atributos del entity, en este caso @NotBlank y @Email.
  • @ModelAttribute: El constructor de esta anotacion recibe el nombre del formulario html y lo convierte a un objeto Java.
  • BindingResult: Contendra la informacion del resultado entre el mapeo del formulario html y el objeto Java User.

Lo primero que debemos hacer es verificar que no hayan errores dentro de nuestro BindingResult de la siguiente manera: result.hasErrors().

Si hay errores necesitaremos regresar a la pantalla para poder mostrar estos errores, esto lo hicimos en el punto #2 poniendo una seccion de errores debajo de cada input, y ademas debes indicar que la pestaña del formulario debe de estar activa y sino hay errores hay que proceder a crear el usuario.

El codigo final del metodo descrito seria el siguiente dentro de la clase UserController:

<span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">"/userForm"</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> String <span class="token function">postUserForm</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Valid</span> <span class="token annotation punctuation">@ModelAttribute</span><span class="token punctuation">(</span><span class="token string">"userForm"</span><span class="token punctuation">)</span>User user<span class="token punctuation">,</span> BindingResult result<span class="token punctuation">,</span> ModelMap model<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">if</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span><span class="token function">hasErrors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			model<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"userForm"</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
			model<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"formTab"</span><span class="token punctuation">,</span><span class="token string">"active"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token punctuation">{</span>
			<span class="token keyword">try</span> <span class="token punctuation">{</span><span class="token comment">//Aca tendras error porque este metodo no existe, pero lo crearemos en la siguiente seccion.</span>
				userService<span class="token punctuation">.</span><span class="token function">createUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
				model<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"userForm"</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				model<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"listTab"</span><span class="token punctuation">,</span><span class="token string">"active"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
				model<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"formError"</span><span class="token punctuation">,</span>e<span class="token punctuation">.</span><span class="token function">getMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
				model<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"userForm"</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
				model<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"formTab"</span><span class="token punctuation">,</span><span class="token string">"active"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>

		model<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"userList"</span><span class="token punctuation">,</span> userService.getAllUsers()<span class="token punctuation">)</span><span class="token punctuation">;</span>
		model<span class="token punctuation">.</span><span class="token function">addAttribute</span><span class="token punctuation">(</span><span class="token string">"roles"</span><span class="token punctuation">,</span>roleRepository<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> <span class="token string">"user-form/user-view"</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
Java

4. Crear Servicio

Tendras que agregar el metodo a la interfaz del servicio y luego crear el metodo en la implementacion. Pero antes de crear el usuario tenemos que hacer dos validaciones, que el username no este ocupado por otra persona y que el password y el confirmPassword sean iguales.

UserService
public User createUser(User formUser) throws Exception;

UserServiceImpl
private boolean checkUsernameAvailable(User user) throws Exception {
		Optional<User> userFound = repository.findByUsername(user.getUsername());
		if (userFound.isPresent()) {
			throw new Exception("Username no disponible");
		}
		return true;
	}

	private boolean checkPasswordValid(User user) throws Exception {
		if ( !user.getPassword().equals(user.getConfirmPassword())) {
			throw new Exception("Password y Confirm Password no son iguales");
		}
		return true;
	}


	@Override
	public User createUser(User user) throws Exception {
		if (checkUsernameAvailable(user) && checkPasswordValid(user)) {
			user = repository.save(user);
		}
		return user;
	}

Nota:Cuando agregemos Spring Boot Security necesitaremos encriptar el password antes de guardar el usuario.

5.Arreglar Formulario HTML

Para poder que el formulario haga el request apropiadamente asegurate que este usando el metodo post, el action sea userForm y el boton de guardar los cambios sea tipo submit.

<form id="userForm" th:object="${userForm}" method="post" class="form" role="form" th:action="@{/userForm}">

Ademas asegurate de haber programado el cambio de pestañas adecuadamente en el archivo form-view.html. Tanto los enlaces de cada tab como el cuerpo deben de tener el atributo th:classappend.

6.Git Commit

Se me olvido tomar la captura de pantalla antes de hacer el commit por lo tanto esta imagen es diferente a las anteriores. Esta imagen muestra la informacion del commit, como el commit Id, el mensaje y los archivos modificados en ese commit.

Git Commit of CreateUser Service
Git Commit of CreateUser Service

Github Commit:
https://github.com/cruizg93/Spring-Boot-Aplicacion/commit/356e82bf7b7eeb73cf9ee2535055b4b7f866beef#diff-412c40d2ba899c9197b94f35d9305426

7.Video Paso a Paso

Menu

  1. Setup
  2. Entidades y POJOS
  3. Basic HTML
  4. Lista de Usuarios
  5. Crear Usuario y Validar Campos
  6. Editar Usuario
  7. Eliminar Usuario
  8. Cambiar Contraseña
  9. Spring Security
  10. Paginas de Error
  11. Bonus, Arreglando Cositas
  12. Formulario de registro
  13. Despliegue en Heroku

Gracias por llegar al final de este post.
No se te olvide dejar tus comentario o preguntas aca abajo o en mi twitter @Cruizg93

6 Replies to “Spring Boot Aplicacion Web Parte 5.”

  1. En el minuto 2:35 agregamos los mensajes de errores, pero tengo una duda si tengo una relacion de oneToOne, como lo haces en tu tutorial Spring Boot -06- JPA Relaciones de uno a uno y de muchos a muchos (LINK: https://www.youtube.com/watch?v=0Iaafne6BRs&t=1287s) en este caso como pondria el div que contiene el error en mi caso tengo una relacion de 1 a 1 de cliente con usario y accedo al campo de esta forma th:field=”${clienteForm.users.nombres}” pero en el div especificaria igual como lo haces aqui th:if=”${#fields.hasErrors(‘Nombre_del_atributo’)}” th:errors=”*{Nombre_del_atributo} o tendria que poner th:if=”${#fields.hasErrors(‘users.Nombre_del_atributo’)}” gracias por responder de antemano.

  2. Hola Cristian,

    Debo molestarte… estoy realizando lo que me comentas para validar tanto contraseñas como campos… entiendo que lo hice de acuerdo a como tu nos estas enseñando, pero lo cierto es que no me aparece ningun tipo de validación salvo las de campo vacío, ¿alguna sugerencia?

    1. Lo primero q se viene a mi mente es que tienes q revisar los import, todas las validaciones pertenecen al paquete javax.validation.constraints. Por lo tanto si pones un * deberias de poder usar todas.

      Si compartes el codigo completo de tu entidad/pojo yo podria revisar que tienes mal.

      1. Tenías tooodaaa la razón… solo estaba el import javax.validation.Valid;…. lo cambié a import javax.validation.*; y ahora todo anda de maravillas

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *