Spring Boot Aplicacion Web Parte 6.

Actualizar Usuario

Explicare el flujo que necesitamos seguir para poder conseguir actualizar nuestro usuario.

Primero necesitamos cargar la información existente de nuestro usuario en el formulario, eso lo vamos hacer al pulsar el icono de editar en la lista de usuarios en el HTML. Pero obviamente no queremos actualizar el password de un usuario cada vez que algún dato se modifico por lo cual esconderemos el campo de password y confirmar password.

Luego recibiremos la nueva informacion en nuestro controlador y tendremos que volver a buscar el usuario en la base de datos para poder tener una transaccion abierta, luego mapeamos los datos del usuario que viene del formulario dentro del usuario encontrado y listo, Hibernate se encargara de hacer el update.

En caso de que se quiera editar el username de una usuario se necesitara validar la disponibilidad de ese nuevo username.


Contenido

  • 1.Crear metodo get.
  • 2.Activar modoEdit en HTML.
  • 3.Crear metodo Post.
  • 4.Crear servicio para actualizar usuario.
  • 5.Cancelar edicion.
  • 6.Git Commit.
  • 7.Video Paso a Paso.

1.Crear metodo get.

Necesitamos recibir como parametro el id del usuario que queremos editar en la url, de esta manera /editUser/{id}.

Tambien crearemos un servicio para consultar el usuario correspondiente y para finalizar retornamos los mismo valores en el modelo como lo hicimos en el metodo getUserForm, pero en vez de asignar new User(), asignamos el usuario consultado.

UserService.java

User getUserById(Long id) throws Exception 
Java

UserServiceImpl.java

@Override
	public User getUserById(Long id) throws Exception {
		User user = userRepository.findById(id).orElseThrow(() -> new Exception("User does not exist"));
		return user;
	}
Java

UserController.java

@GetMapping("/editUser/{id}")
	public String getEditUserForm(Model model, @PathVariable(name="id") Long id) throws Exception {
		User user = userService.getUserById(id);
		
		model.addAttribute("userList", userService.getAllUsers());
		model.addAttribute("roles",roleRepository.findAll());
		model.addAttribute("userForm", user);
		model.addAttribute("formTab","active");//Activa el tab del formulario.
		
		model.addAttribute("editMode",true);//Mira siguiente seccion para mas informacion
		
		return "user-form/user-view";
	}
Java

user-view.html

Busca los enlaces de las pestañas y los divs con id list y form, asegurate de agregar el atributo de thymeleaf th:classapend, como lo hacemos mas abajo.

Recuerda que con cada llamado al controlador se recarga la pagina por lo mismo la pestana del div list sera siempre mostrada por defecto y con esto podemos dinamicamente seleccionar la pestaña que necesitemos.

<a class="nav-link" th:classappend=" ${listTab}" id="list-tab" data-toggle="tab" href="#list" role="tab" aria-controls="list" aria-selected="false">List</a>
<div class="tab-pane fade" th:classappend="${listTab}" id="list" role="tabpanel" aria-labelledby="list-tab">


<a class="nav-link" th:classappend=" ${formTab}" id="form-tab" data-toggle="tab" href="#form" role="tab" aria-controls="form" aria-selected="true">Form</a> <div class="tab-pane fade" th:classappend="${formTab}" id="form" role="tabpanel" aria-labelledby="form-tab">

2.Activar modoEdit en HTML

Algo que hay que tener claro es que podemos reutilizar el formulario de crear usuarios para editar usuarios.

En nuestro caso yo no quiero alctualizar el password cada vez que cambie algun dato del usuario, por lo cual tenemos que esconder ese campo, ademas renombraremos el texto del boton y cambiaremos el th:action del formulario.

Para lograr lo anterior descrito activaremos el modo de edicion en nuestro pantalla, enviando desde el controlador el atributo “editMode” verdadero (model.addAttribute("editMode",true);). Y verificando esa variable en el html.

user-form.html

<form class="form" role="form" autocomplete="off"  th:object="${userForm}" th:action="${editMode} ?@{/editUser} :@{/userForm}" method="post">

	<!--Es necesario para poder pasar la validacion del Model-->
	<input class="form-control" type=hidden th:field="${userForm.id}"  th:if="${editMode}">

	<input class="form-control" type=hidden name="password" value="xxxx" th:if="${editMode}">
	<!--quita el comentario si quieres mantener la validacion @NotBlank del campo confirmPassword
		 <input class="form-control" type=hidden name="confirmPassword" value="xxxx" th:if="${editMode}">
	 -->

        <input type="submit" class="btn btn-primary"
				value="Save Changes" th:value="${editMode}?'Save User':'Create User'">

3.Crear metodo Post.

UserController.java

@PostMapping("/editUser")
	public String postEditUserForm(@Valid @ModelAttribute("userForm")User user, BindingResult result, ModelMap model) {
		if(result.hasErrors()) {
			model.addAttribute("userForm", user);
			model.addAttribute("formTab","active");
			model.addAttribute("editMode","true");
		}else {
			try {
				userService.updateUser(user);
				model.addAttribute("userForm", new User());
				model.addAttribute("listTab","active");
			} catch (Exception e) {
				model.addAttribute("formErrorMessage",e.getMessage());
				model.addAttribute("userForm", user);
				model.addAttribute("formTab","active");
				model.addAttribute("userList", userService.getAllUsers());
				model.addAttribute("roles",roleRepository.findAll());
				model.addAttribute("editMode","true");
			}
		}
		
		model.addAttribute("userList", userService.getAllUsers());
		model.addAttribute("roles",roleRepository.findAll());
		return "user-form/user-view";
		
	}

4.Crear servicio para actualizar usuario.

UserService.java

public User updateUser(User user) throws Exception;

UserServiceImpl.java

@Override
	public User updateUser(User fromUser) throws Exception {
		User toUser = getUserById(fromUser.getId());
		mapUser(fromUser, toUser);
		return repository.save(toUser);
	}
	
	/**
	 * Map everythin but the password.
	 * @param from
	 * @param to
	 */
	protected void mapUser(User from,User to) {
		to.setUsername(from.getUsername());
		to.setFirstName(from.getFirstName());
		to.setLastName(from.getLastName());
		to.setEmail(from.getEmail());
		to.setRoles(from.getRoles());
	}

5.Cancel Action

UserController.java

@GetMapping("/editUser/cancel")
	public String cancelEditUser(ModelMap model) {
		return "redirect:/userForm";
	}

6.Git Commit

Como el post anterior, les muestro la imagen del commit, recuerda que Github necesita que el final del commit sea “Close #7”, para poder mover tu tarea automaticamente a estado “Done”.

UPDATEGithub Repositorio, a diferencia de otros capitulos este tiene dos commits porque al final del curso me di cuenta que podia hacer algo de una mejor manera. Entonces mira abmos commits en orden Commit #1
https://github.com/cruizg93/Spring-Boot-Aplicacion/commit/67b9219303f48ca79999aca2d4f33d2435808900
Commit #2
https://github.com/cruizg93/Spring-Boot-Aplicacion/commit/a9611394cc46a0699d2ec019b1caa39147d53fb6

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

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

  1. Tengo el siguinete error : Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction

      1. Hola Daniel, tendria que ver tu codigo. por favor comparterlo en un repositorio o copia y pega aqui tu formulario html, tu controlador y entidad con la que tengas problema y con mucho gusto te ayudo

Deja un comentario

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