Select multiple populando errado no vraptor3 [resolvido]

Tenho o HTML abaixo:

[code]

opt1 opt1 opt1 opt2 opt2 opt2 [/code]

E as classes

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

public class Group { private Long id; }

Quando faço post da página a exception é lançada:

INFO: 21:02:01 DEBUG (OgnlParametersProvider.java:152) - Applying user.groups.id with [1, 2] SEVERE: StandardWrapperValve[default]: PWC1406: Servlet.service() for servlet default threw exception java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at br.com.caelum.vraptor.http.ognl.ListAccessor.setProperty(ListAccessor.java:75) at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:2225) at ognl.ASTProperty.setValueBody(ASTProperty.java:127) at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220) at ognl.SimpleNode.setValue(SimpleNode.java:279) at ognl.ASTChain.setValueBody(ASTChain.java:227) at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220) at ognl.SimpleNode.setValue(SimpleNode.java:279) at ognl.Ognl.setValue(Ognl.java:737) at ognl.Ognl.setValue(Ognl.java:783) at br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createViaOgnl(OgnlParametersProvider.java:154) at br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createRoot(OgnlParametersProvider.java:128) at br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.getParametersFor(OgnlParametersProvider.java:104) at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:81) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)

Fazendo de debug na classe ListAccessor, linha 75 do vraptor3-rc2 o valor de key é id, que é o nome do campo a popular (creio ser user.groups.id), porém o cast pra integer está lançando uma class-cast.

List<?> list = (List<?>) target; int index = (Integer) key; for (int i = list.size(); i <= index; i++) { list.add(null); }

o problema é o jeito que o select multiple manda os parâmetros para a requisição…

se o name é user.groups:

user.groups.id=1
user.groups.id=2

e o que vai pro vraptor:

user.groups=new String[]{"1","2"};

quanto ao class cast, é que quando o parâmetro é uma lista, o vraptor espera
user.groups[0].id

e quando você não coloca os colchetes, é equivalente a:
user.groups[“id”]

por isso o class cast…

por enquanto o vraptor não suporta isso, você pode receber na sua lógica um array direto ou uma lista, deve
funcionar por enquanto…

cadastrei lá no github o bug

Lucas, pelo que você disse posso então fazer no meu controller:

Ao invés de void store(User user) posso usar store(User user, String[] groups) e popular os dados manualmente?

sim… acho que é esse o workaround para o bug…
ou mudar os parâmetros via javascript… que eh bem mais chato…

Lucas, foi efetuada correção no v3 final?

o bug continua aberto… infelizmente não =(

vou colocar isso em maior prioridade pro próximo release…

desculpe

Lucas, por enquanto está funcionando com aquele workaround que você me passou.

Abraços, e obrigado.

Então… existe um problema grande para resolver esse bug:
se tivéssemos cliente.usuario.groups.id como nome da select, como sabemos qual é o objeto que é a collection?
temos que passar por todo o caminho e ver se algum deles é uma collection…

pior ainda, se tiver 2 coleções no caminho:

sala.clientes.usuario.groups.id

qual coleção vai ganhar vários elementos?

o que pode ser feito é suportar selects múltiplos do tipo:

usuario.groups[].id = [x, y]

aí dá pra converter pra

usuario.groups[0].id = x
usuario.groups[1].id = y

etc…

que vc acha?

Lucas, vou analisar isso com calma em casa e te respondo.

Abraços

Voltando ao tópico, agora estou de novo precisando usar select-multiple.

tentando usar o método como isso:

Funciona aparentemente bem. Porém quando eu seleciono apenas um o parametro chega como null. Se eu uso o método com List

Todos os parametros vem sempre como null, não importa quantos elementos eu selecione.

List não funciona por causa do jeito que o select multiple vai pra requisição… pra funcionar como list vc precisaria passar os parametros:

param1[0]
param1[1]
etc…

qto ao null qdo vc só passa um parâmetro, é um bug bem chato de resolver, pq envolve o ognl…

talvez vc consiga resolver o problema da lista criando um interceptor que roda antes de todo mundo (vc vai precisar de um CustomRequestExecution)

nomeie o select como param1[] e param2[], e no interceptor, procure todos os parâmetros do request que tenham [] e adicione um parametro com o mesmo nome, substituindo o [] por [0], [1], etc

tá dando qual class cast?

troque pra List… o String[] (na verdade qqer array) dá esse class cast qdo vc passa só um valor…

o List funciona da mesma forma, e funciona com o vraptor…

http://guj.com.br/posts/list/15/137522.java#1050717

Oi Lucas

Estou tentando usar o workaround sugerido acima, ou seja, no name utilizo caracteristicas.id e recebo um String[].

Está dando ClassCast… Foi feita alguma alteração nas versões posteriores?

Estou usando a versão vraptor-3.1.3-20100428.160403-2.jar

Abs

java.lang.ClassCastException: java.lang.String
	at br.com.caelum.vraptor.http.ognl.ArrayAccessor.setProperty(ArrayAccessor.java:53)
	at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:2225)
	at ognl.ASTProperty.setValueBody(ASTProperty.java:127)
	at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)
	at ognl.SimpleNode.setValue(SimpleNode.java:279)
	at ognl.ASTChain.setValueBody(ASTChain.java:227)
	at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)
	at ognl.SimpleNode.setValue(SimpleNode.java:279)
	at ognl.Ognl.setValue(Ognl.java:737)
	at ognl.Ognl.setValue(Ognl.java:783)
	at br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createViaOgnl(OgnlParametersProvider.java:132)
	at br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createRoot(OgnlParametersProvider.java:108)
	at br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.getParametersFor(OgnlParametersProvider.java:90)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.getParametersFor(ParametersInstantiatorInterceptor.java:83)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:68)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)

Obrigado

Resolvido :wink: