[resolvido] Populando listas no vraptor3

10 respostas
G

Boa tarde.

Tenho uma classe User na qual possuo uma coleção de grupos que esse usuário possui, sendo assim:

public class User { private Long id; private List<Group> groups; }

public class Group { private Long id; private String name; }

No meu controller faço isso aqui para preencher o meu bean com os grupos selecionados pelo usuário.

public class UserController { public void update(User user) { userService.updateProfile(user); } }

E no JSPX tenho isso aqui:

<c:forEach items="${groups}" var="g"> <w:checkbox name="user.groups" checked="${fn:contains(user.groups, g)}" value="${g.id}" /> ${g.name} </c:forEach>

No vrator2 funcionava corretamente, porém no vraptor3 não funciona. Quando faço um user.getGroups() retorna null. Como devo fazer para popular listas no vraptor3?

10 Respostas

Adriano_Almeida

Basta colocar o indice no nome do checkbox e popular o id de cada grupo

&lt;c:forEach items="${groups}" var="g" varStatus="status"&gt;  
    &lt;w:checkbox name="user.groups[${status.count}].id" checked="${fn:contains(user.groups, g)}" value="${g.id}" /&gt;  
     ${g.name}  
&lt;/c:forEach&gt;
G

Adriano, esse exemplo que vocẽ me passou funciona no vraptor2, mas não no vraptor3. Aliás na documentação do vraptor não há ainda nada sobre popular listas.

Fiz usando essa forma que vocẽ falou, como passando sem o “.id”, mas em nenhum deles funcionou. Mas há um pequeno workaround que dá para fazer. No meu controler alterei para receber também uma lista de grupos além do usuário. Após alterei no JSPX para camar o campo de groups[0].id.

<c:forEach items="${groups}" var="g" varStatus="status"> <w:checkbox name="groups[${status.count}].id" checked="${fn:contains(user.groups, g)}" value="${g.id}" /> ${g.name} </c:forEach>

E no controller:

public class UserController { public void update(User user, List<Group> groups) { user.setGroups(groups); userService.updateProfile(user); } }

Lagaffe

Nos meus testes consegui popular normalmente listas, no VRaptor3, ± da forma que o Adriano indicou.

Só não tenho casos de checkbox.

Lucas_Cavalcanti

Verifique se você tem na sua classe:

user.getGroups()
e user.setGroups(List)

G

lucascs:
Verifique se você tem na sua classe:

user.getGroups()
e user.setGroups(List)

Sim, tem sim.

Lucas_Cavalcanti

acho que o problema é você estar usando a taglib do waffle… use html direto:

<input type="checkbox" name="user.groups[${status.count}].id" ${fn:contains(user.groups, g)? 'checked="checked"' : ''}" value="${g.id}" />

vê se isso funciona…

G

Lucas, obrigado pelo help.

O problema não me parece ser na taglib do waffle, pois o HTML gerado por ela me parece estar correto. Aliás essa aplicação estava rodando com vraptor2. Quando saiu o rc1 fui fazendo a migração dela para vraptor3. E essa tela parou de funcionar.

De qualquer forma fiz o teste conforme você falou. O HTML gerado foi:

<input type="checkbox" name="user.groups[0].id" value="1" /> Grupo 01 <br /> <input type="checkbox" name="user.groups[1].id" value="2" /> Peão <br /> <input type="checkbox" name="user.groups[2].id" value="4" /> Administrador <br />

Porém mesmo assim o vraptor não está injetando os dados. A solução por enquando foi colocar uma lista de grupos no método do controller:

E alterar o JSP para:

Quando eu chegar em casa vou fazer um debug nas classes envolvidas para tentar entender o que está acontecendo.

Abraços

Lucas_Cavalcanti

Com o teste:

@Resource
public class TesteController {
       @Path("/teste")
	public void teste(User user) {
		System.out.println(user);
	}

	public static class User {
		private List<Group> groups;

		public void setGroups(List<Group> groups) {
			this.groups = groups;
		}

		public List<Group> getGroups() {
			return groups;
		}
		@Override
		public String toString() {
			return groups.toString();
		}
	}
	public static class Group {
		private Long id;

		public Long getId() {
			return id;
		}
		public void setId(Long id) {
			this.id = id;
		}
		@Override
		public String toString() {
			return "[" + id + "]";
		}
	}
}

chamando a url: /teste?user.groups[0].id=1&user.groups[1].id=2
vai direitinho, ele imprime:
[[1], [2]] como deveria…

o seu getter e setter para groups do usuário estão iguais o desse meu teste?
tem algo diferente disso?

G

Lucas, muito obrigado pelo suporte.

Após colocar a classe que você fez, funcionou tudo certinho. Então pensei: poxa, é erro no código mesmo, não pode ser do vraptor. Então analisei meu código, mas estava tudo certo, desde o JSP até as classes Java. Inclusive a waffle estava imprimindo o HTML certinho.

Aumentei o nivel de log para debug, e notei que ele estava fazendo o bind dos valores, porém no bean ainda estava null.

21:04:38 DEBUG (OgnlParametersProvider.java:152) - Applying user.id with [1] 21:04:38 DEBUG (OgnlParametersProvider.java:152) - Applying user.groups[0].id with [3]

Então analizando a classe User tudo parecia certo. Porém ele nunca invocava o user.setGroups. Colocando um breakpoint no user.getGroups vi que ele invocava esse método, que é assim:

public List<Group> getGroups() { return groups == null ? new ArrayList<Group>() : groups; }

Ou seja, como ele nunca chama o set, aí estava o problema. Ele incluia os valores no array-list criado, que nunca era setado na classe. Engraçado que no vraptor2 funcionava talvez por ele fazer injeção no set. Já o ONGL aproveita o get para ir adicionando. Alterei meu código removendo esse new ArrayList e tudo funcionou.

Valeu pela ajuda. Estou te devendo, hehe.

Abraços

Lucas_Cavalcanti

quê isso, continue mandando dúvidas e sugestões! =)

abraços

Criado 27 de setembro de 2009
Ultima resposta 29 de set. de 2009
Respostas 10
Participantes 4