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…
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