4
respostas

NotReadablePropertyException ao tentar acessar ArrayList com jsp

Fala galera tudo bem ? Mais uma vez vou recorre a vocês aqui hehe

Bom vamos lá, vou tentar ser o mais claro possível:

Tenho um bean que representam as roles de um usuário

@Entity
public class Role implements GrantedAuthority{

    private static final long serialVersionUID = 1L;

    @Id
    private String nome;

    public Role(){
    }

    public Role(String nome) {
      this.nome = nome;
    }

    public String getNome() {
        return nome;
    }

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

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

    @Override
    public String toString() {
        return nome;
    }
}

Preciso exibir um form com checkboxes que representam essas roles, então fiz um método do meu controller:

    @RequestMapping(method = RequestMethod.GET, path="/roles")
    public ModelAndView formRoles(@RequestParam("email") String email) {
        Usuario usuario = usuarioDao.loadUserByUsername(email);
        List<Role> roles = roleDao.listar();
        ModelAndView modelAndView = new ModelAndView("/roles/form");
        modelAndView.addObject("usuario", usuario);
        modelAndView.addObject("roles", roles);
        return modelAndView;
    }

Por fim fiz o seguinte no meu jsp:

    <form:form action="${s:mvcUrl('UC#atualizarRoles').build() }" method="post" commandName="roles" enctype="multipart/form-data">
        <div>
            <label for="roles">Permissões</label>
            <c:forEach items="${roles}" var="roles">
                <p>${roles }</p>
                <form:checkboxes items="${roles }" path="${roles }"/>
            </c:forEach>
        </div>
    </form:form>

A ideia era que o foreach deveria receber a lista de roles e exibir um checkbox para cada role... Mas ao invés disso estou obtendo o seguinte erro:

org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: org.springframework.beans.NotReadablePropertyException: Invalid property 'ROLE_ADMIN' of bean class [java.util.ArrayList]: Bean property 'ROLE_ADMIN' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

Ok, eu entendi que ele está tentando extrair a propriedade ROLE_ADMIN da classe ArrayList... Mas não entendi por que, uma vez que meu ArrayList é um ArrayList de role...

Alguém poderia me ajudar por favor, não só a corrigir mas a entender o por que desse erro..

Grato desde já !!!

4 respostas

Antes de mais nada, mil desculpas pelo atraso :(.

Acho que você não precisa da tag foreach ali... Usa o checkboxes direto e passa a variável roles. Do jeito que você fez você tava passando a variável roles definida para o escopo do foreach.

Fala Alberto blz ? Obrigado pela ajuda

Cara fiz assim:

UsuarioController.java

@RequestMapping(method = RequestMethod.GET, path="/roles")
    public ModelAndView formRoles(@RequestParam("email") String email) {
        Usuario usuario = usuarioDao.loadUserByUsername(email);
        List<Role> roles = roleDao.listar();
        ModelAndView modelAndView = new ModelAndView("/roles/form");
        modelAndView.addObject("usuario", usuario);
        modelAndView.addObject("roles", roles);
        return modelAndView;
    }

form.jsp

    <form:form action="${s:mvcUrl('UC#atualizarRoles').build() }" method="post" commandName="roles" enctype="multipart/form-data">
        <div>
            <label for="roles">Permissões</label>
                <form:checkboxes items="${roles }" path="${roles }"/>
        </div>
    </form:form>

E continuo recendo essa exceção

Message javax.servlet.ServletException: javax.servlet.jsp.JspException: org.springframework.beans.NotReadablePropertyException: Invalid property '[ROLE_ADMIN, ROLE_COMERCIAL, ROLE_USER]' of bean class [java.util.ArrayList]: Bean property '[ROLE_ADMIN, ROLE_COMERCIAL, ROLE_USER]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

Curioso é que tenho o getter e setter definido na classe Role.java

package br.com.casadocodigo.loja.models;

import javax.persistence.Entity;
import javax.persistence.Id;

import org.springframework.security.core.GrantedAuthority;

@Entity
public class Role implements GrantedAuthority{

    private static final long serialVersionUID = 1L;

    @Id
    private String nome;

    public Role(){
    }

    public Role(String nome) {
      this.nome = nome;
    }

    public String getNome() {
        return nome;
    }

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

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

    @Override
    public String toString() {
        return nome;
    }
}

Tem uma propriedade que chama itemValue e outra que chama itemLabel. Você precisa o nome da propriedade que o spring deve fazer a leitura para montar cada checkbox. Ex:

itemValue="id" itemLabel="name"

Opa fala Alberto tudo bem ?

Cara valeu pela ajuda... graças a sua ajuda eu consegui exibir as roles com o seguinte código:

UsuarioController.java

    @RequestMapping(method = RequestMethod.GET, path="/roles")
    public ModelAndView formRoles(@RequestParam("email") String email) {
        Usuario usuario = usuarioDao.loadUserByUsername(email);

        List<Role> roles = roleDao.listar();

        ModelAndView modelAndView = new ModelAndView("/roles/form");
        modelAndView.addObject("usuario", usuario);
        modelAndView.addObject("roles", roles);
        return modelAndView;
    }

/roles/form.jsp

    <form:form action="${s:mvcUrl('UC#atualizarRoles').build() }"
        method="post" commandName="roles" enctype="multipart/form-data">
        <div>
            <label for="roles">Permissões</label>            
                <form:checkboxes items="${roles }" path="${role }" />
        </div>
    </form:form>

Porém me surgiu uma dúvida, quando mostro esses checkbox, eu tenho que verificar quais as roles que o usuário já tem e marcar os checkboxes correspondentes, tentei de várias formas e a última foi a seguinte:

<form:checkboxes items="${roles }" path="${role }"> 
                    <c:if test="${fn:contains(usuario.roles, role) }">checked="checked"</c:if>                    
                </form:checkboxes>

Veja que no UsuarioController.java eu passo o usuário via ModelAndView isso já está funcionando pois consigo recuperar o nome do usuário na outra tela... Quanto aos checkboxes tentei fazer assim:

Mas daí tomei essa exception:

org.apache.jasper.JasperException: /WEB-INF/views/roles/form.jsp (line: [68], column: [4]) According to TLD, tag [form:checkboxes] must be empty, but is not

Que pela mensagem me diz que a tag <form:checkboxes /> deve estar vazia mas não está pois ali tem um <c:if>...

Eu dei uma olhada na documentação em https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/spring-form-tld.html#spring-form.tld.checkboxes

Tentei assim também:

<form:checkboxes items="${roles }" path="${role }" itemValue="${role.id}" itemLabel="${role }"  />

Dessa forma recebi o seguinte erro:

org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: java.lang.IllegalArgumentException: 'itemValue' must not be empty

Nesse caso dizendo que itemValue está vazia e isso não pode ocorrer... O que estou fazendo de errado ?

Grato....