Select multiple populando errado no vraptor3 [resolvido]

16 respostas
G

Tenho o HTML abaixo:

<select multiple="multiple" name="user.groups">
  <option value="1">opt1 opt1 opt1</option>
  <option value="2">opt2 opt2 opt2</option>
</select>

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);
}

16 Respostas

Lucas_Cavalcanti

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

G

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?

Lucas_Cavalcanti

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

G

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

Lucas_Cavalcanti

o bug continua aberto… infelizmente não =(

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

desculpe

G

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

Abraços, e obrigado.

Lucas_Cavalcanti

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?

G

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

Abraços

G

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.

Lucas_Cavalcanti

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

Lucas_Cavalcanti

tá dando qual class cast?

Lucas_Cavalcanti

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…

G

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

seufagner

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

seufagner
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

seufagner

Resolvido :wink:

Criado 30 de setembro de 2009
Ultima resposta 9 de mai. de 2010
Respostas 16
Participantes 3