7
respostas

Cadastro usuário

Boa a tarde, durante o curso foi feito o cadastro de um usuário direto no banco de dados e tambem a definição da role desse usuario, então fiquei curioso e resolvi desenvolver um cadastro de usuario onde fosse possivel atravez de um radio button definir quais roles teria os usuarios. quando tento acessar meu formulario de cadastro (/usuarios/form/cadastro) recebo:

org.springframework.beans.NotReadablePropertyExceptionInvalid property 'roles.previlegio' of bean class [br.com.clienteoculto.models.Usuario]: Bean property 'roles.previlegio' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

eu já refiz meus getter e setter mas da clase Role mais ainda assim recebo a exception

segue minha classe Usuario

package br.com.clienteoculto.models;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
public class Usuario implements UserDetails {

    private static final long serialVersionUID = 1L;

    @Id
    private String email;
    private String senha;
    private String nome;
    @ManyToMany(fetch=FetchType.EAGER)
    private List <Role> roles = new ArrayList<Role>() ;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles;
    }

    @Override
    public String getPassword() {
        return senha;
    }

    @Override
    public String getUsername() {
        return email;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }    
}

segue a classe UsuarioDAO

package br.com.clienteoculto.daos;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Repository;

import br.com.clienteoculto.models.Usuario;

@Repository
public class UsuarioDAO implements UserDetailsService{

    @PersistenceContext
    private EntityManager manager;

    @Override
    public UserDetails loadUserByUsername (String email) throws UsernameNotFoundException {
        String jpql = "select u from Usuario u where u.email = :email";    
        List<Usuario> usuarios    = manager.createQuery(jpql, Usuario.class)
                .setParameter("email", email).getResultList();

     if(usuarios.isEmpty()){
         throw new UsernameNotFoundException("o " + email + " não foi encontrado!");
     }

     return usuarios.get(0);
    }

    public void adicionaUsuario(Usuario usuario){
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String hasSenha = passwordEncoder.encode(usuario.getSenha());
        usuario.setSenha(hasSenha);        
        manager.persist(usuario);
        }

    public List<Usuario> lista() {
        return manager.createQuery("select u from Usuario u", Usuario.class).getResultList();
    }


}

segue classe UsuariosController

package br.com.clienteoculto.controllers;

import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import br.com.clienteoculto.daos.UsuarioDAO;
import br.com.clienteoculto.models.Usuario;

@Controller
@RequestMapping("/usuarios")
public class UsuariosController {

    @Autowired
    private UsuarioDAO usuarioDAO;

    @RequestMapping(method=RequestMethod.POST)
    public ModelAndView grava(@Valid Usuario usuario, BindingResult result,
                                RedirectAttributes redirectAttributes ){
        if(result.hasErrors()){
            return form(usuario);
        }
        usuarioDAO.adicionaUsuario(usuario);
        redirectAttributes.addFlashAttribute("sucesso", "Usuario "+usuario+" cadastrado com sucesso!");

        return new ModelAndView("redirect:usuarios");
    }

    @RequestMapping("/form/cadastro")
    public ModelAndView form(Usuario usuario) {
        ModelAndView modelAndView = new ModelAndView("usuarios/form-cad-usuario");
        return modelAndView;
    }

    @RequestMapping(method=RequestMethod.GET)
    public ModelAndView lista(){
        List<Usuario> usuarios = usuarioDAO.lista();
        ModelAndView modelAndView = new ModelAndView("usuarios/lista-usuario");
        modelAndView.addObject("usuarios", usuarios);

        return modelAndView;
    }

}

Por fim a jsp

package br.com.clienteoculto.controllers;

import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import br.com.clienteoculto.daos.UsuarioDAO;
import br.com.clienteoculto.models.Usuario;

@Controller
@RequestMapping("/usuarios")
public class UsuariosController {

    @Autowired
    private UsuarioDAO usuarioDAO;

    @RequestMapping(method=RequestMethod.POST)
    public ModelAndView grava(@Valid Usuario usuario, BindingResult result,
                                RedirectAttributes redirectAttributes ){
        if(result.hasErrors()){
            return form(usuario);
        }
        usuarioDAO.adicionaUsuario(usuario);
        redirectAttributes.addFlashAttribute("sucesso", "Usuario "+usuario+" cadastrado com sucesso!");

        return new ModelAndView("redirect:usuarios");
    }

    @RequestMapping("/form/cadastro")
    public ModelAndView form(Usuario usuario) {
        ModelAndView modelAndView = new ModelAndView("usuarios/form-cad-usuario");
        return modelAndView;
    }

    @RequestMapping(method=RequestMethod.GET)
    public ModelAndView lista(){
        List<Usuario> usuarios = usuarioDAO.lista();
        ModelAndView modelAndView = new ModelAndView("usuarios/lista-usuario");
        modelAndView.addObject("usuarios", usuarios);

        return modelAndView;
    }

}

desde já obrigado!

7 respostas

Wilker,

Ficou faltando apenas a jsp

desculpe... segue abaixo

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<!DOCTYPE html>
<html>
    <head>
    <meta charset="UTF-8">
    <title>Cliente Oculto</title>
    </head>
    <body>
        <h1>Cadastro Usuários</h1>

        <form:form action="${spring:mvcUrl('UC#grava').build()}" method="post" commandName="usuario">
            <div>
                <label for="nome">Nome</label> 
                <form:input path="nome"/>
                <form:errors path="nome" />
            </div>

            <div>
                <label for="email">E-mail</label>
                <input type="email" name="email"/>
                <form:errors path="email" />
            </div>

            <div>
                <label for="senha">Senha</label>
                <input type="password" name="senha"/>
                <form:errors path="senha" />
            </div>
            <div>
                <form:radiobutton path="roles" value="ADMIN" label="Administrador" />
                <form:radiobutton path="roles" value="OPERADOR" label="Operador" />
                <form:errors path="roles" />
            </div>
            <div>
                <button type="submit">Cadastrar</button>
            </div>
        </form:form>
    </body>
</html>

Beleza Wilker,

Cara, me questiono sobre alguns pontos da sua lógica, como o da sua classe Usuário ta com uma lista de roles, sendo que na tela é disponibilizado radios (ou seja, apenas um valor)...

Se você mudar para apenas uma role na classe usuário o seu problema tá resolvido.

Agora caso realmente ele (o usuário) possa ter mais de uma role, você vai ter que disponibilizar as opções na tela (como um selectbox multiple options), e atrelando o path a lista roles

<form:select path="roles">
    <form:options items="${rolesList}" />
</form:select>

Sacou?

Qualquer dúvida manda ai! ... espero ter ajudado

Igo mais uma vez obrigado pela ajuda, coloquei da forma como descreveu porem quando tento acessar o meu form recebo a seguinte exception

org.springframework.beans.NotReadablePropertyException: Invalid property 'roles' of bean class [br.com.clienteoculto.models.Usuario]: Bean property 'roles' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

ai me veio uma duvida no codigo que voce mandou, nessa linha temos:

<form:select path="roles">

onde o spring faz o binding com o atributo role da minha classe Usuario. Mas e esse trecho de codigo:

<form:options items="${rolesList}"

não entendi de onde tiraria essa variavel ${rolesList}?

Então, nessa sugestão você informaria as opções possíveis setando na controller da mesma forma que você informa o usuário quando você lista...

Caso as suas Roles sejam informadas em um Enum, você poderia fazer assim:

 modelAndView.addObject("rolesList", Roles.values());

Te atende?

Igo mais uma vez obrigado pela força e desculpe a demora, acho fazer ter as roles em uma enum como mostrou é uma boa saída, porem no método

    @Override
    public String getAuthority() {
        return this.nome;
    }

exige que eu retorne um string com eu retornaria no caso da minha role ser uma enum?

Eu que demorei dessa vez ... rs'

Bom, utilizando enum você pode colocar um atributo com a descrição da Role, e chamar o método que retorna essa descrição:

public enum Roles {

    ADMIN("Administrador"),
    OPERADOR("Operador");

    private String descricao;

    private Roles(String descricao){
        this.descricao = descricao;
    }

    public String getDescricao() {
        return descricao;
    }

}

E para retornar a String

Roles.ADMIN.getDescricao();