Vraptor 3 / upload select multiple

Estou com problemas para fazer upload, no VRaptor 3, quando tenho um ou mais <select multiple… no mesmo form. Acredito que seja relacionado ao parâmetro enctype=“multipart/form-data”.

@Path("/exemplo/upload/") @Post
public void upload(UploadedFile arquivo, String[] opcoes){
     .
     .
     .
}
<form action="<c:url value="/exemplo/upload/" />" method="post" >			
   <select multiple="multiple" name="opcoes" >
	<option value="1">opcao 1</option>
	<option value="2">opcao 2</option>
	<option value="3">opcao 3</option>	
    </select>
    <input type="file" name="arquivo" />
    <input type="submit" value="upload"/>  
</form>
exception

br.com.caelum.vraptor.InterceptionException: br.com.caelum.vraptor.http.InvalidParameterException: unable to parse expression 'opcoes'
.
.
.
root cause

ognl.OgnlException: opcoes [br.com.caelum.vraptor.VRaptorException: Unable to find converter for [Ljava.lang.String;]
.
.
.
root cause

br.com.caelum.vraptor.VRaptorException: Unable to find converter for [Ljava.lang.String;
.
.
.

obrigado.

isso é um bug do vraptor…

isso vai ser corrigido, mas por enquanto você pode criar a seguinte classe:

@Convert(String[].class)
@ApplicationScoped
public class StringArrayConverter implements Converter<String[]> {

	public String[] convert(String value, Class<? extends String[]> type,
			ResourceBundle bundle) {
		return value.split(",");
	}

}

e tudo vai funcionar direitinho…
[]'s

Lucas,

Fiz da forma que falou. O erro parou de ocorrer, mas o retorno esta
sendo sempre o último valor selecionado e não todos os valores
selecionados como deveria ser.

Att

oi bruno!

a requisicao é GET? pode mandar pra gente a URL que esta sendo gerada pelo form quando voce o submete?

abracos

Paulo,

Requisição: POST
URL…: http://localhost:8080/contexto_aplicacao/exemplo/upload/

Att

oi bruno!

vamos ver se soltamos o beta4 hoje ja com a correcao desse bug!

abracos

Paulo,

Obrigado. Fico no aguardo.

Boa tarde,

Agradeço a todos pela colaboração.
Com a versão liberada b[/b] mais o “converter” sugerido pelo lucascs o problema foi solucionado por completo.

Att.

Oi Bruno!

Creio que com o beta4 voce nem precise desse converter!

abracos

Fiz o teste com o beta4 sem o converter e não funcionou, daí testei com o converter e funcionou blz.

Obrigado.

Voltando a este tópico, vamos supor que eu tenha o metodo:

[code]public void addSubGrupo(List<SubGrupoProduto> subGrupoProduto) {
		if (subGrupoProduto == null) {
			//trato o null;
		} else {
			for (SubGrupoProduto subGrupo : subGrupoProduto) {
				//facaAlgo;
			}
		}
}[/code]

Na view tenho

<form action="$request.contextPath/produto/addsubgrupo/" method="post"> <button type="submit">$lang-add-subGrupoProduto</button> <div id="subGrupos"> <label id="lblSubgrupos" for="subGrupoProduto">$lang-subGrupoProduto</label><br/> <select multiple="multiple" name="subGrupoProduto" size="15" > #foreach( $subGrupoProduto in $subGruposDisponiveisList ) <option value="$!subGrupoProduto.id">$!subGrupoProduto.nome</option> #end </select> </div> </form>

O objeto está chegando null no método.
Já tentei da forma acima e assim também:

Em ambos os casos chega null. Quando trabalho com String[] recebo os ids populados.
Qual a forma correta?

com o vraptor padrão não dá pra fazer isso… a gente usa o ognl pra popular os parâmetros e ele não suporta isso…

vc tem duas opções: ou usar javascript pra colocar os índices antes de mandar a requisição, ou criar um interceptor que tenta ajustar esses parâmetros…

o do interceptor funcionaria assim (mais ou menos):

@Intercepts
public class FixParamsInterceptor implements Interceptor {
     public FixParamsInterceptor(MutableRequest request) {..guarda em um field }
     accepts(...) { return true;}

     intercepts(...) {
          Enumerator<String> params = request.getParameterNames();

          while(params.hasNext()) {
                String param = params.next();
                if (param.contains("[]") {
                   String[] values = request.getParameter(param);
                   for (int i = 0.....)
                       request.setParameter(param.replace("[]", "[" + i+ "]"), values[i]);
                }
          }
          stack.next(method, instance);
     }
}

e vc precisaria criar a classe:

@Component
@PrototypeScoped
public class CustomRequestExecution extends DefaultRequestExecution {
       public CustomRequestExecution(InterceptorStack stack, ...) {
          super(...);
          stack.add(FixParameterInterceptor.class);
       }
}

enfim, é algo assim

não foi implementado no vraptor ainda… mas vc pode usar o interceptor que eu mandei no último post

Lucas, sei que esse na verdade não é um problema do vraptor, já que é o select-multiple que envia os dados diferente dos outros objetos. Mas há um impacto que colocar esse fix no core do vraptor? Se o problema é apenas com o OGNL será que dá para fazer um fix nas classes que integram o OGNL ao vraptor?

Nas minhas aplicações que fazem o uso de select-multiple atualmente estou fazendo isso via request.getParameter.

implementei:

http://oss.sonatype.org/content/repositories/snapshots/br/com/caelum/vraptor/3.1.3-SNAPSHOT/vraptor-3.1.3-20100514.151912-6.jar

só colocar [] no nome do select, aonde fica a collection

Mais rápido que a foice do ceifador sinistro, hahahha.

Eu passei a noite toda com este problema, daí achei este snapshot aqui do vraptor e funcionou assim:

Eu dei o name do select name=“gruposId[]”

e na assinatura do método tive de fazer assim!

public void salvar(Long[] gruposId) {
...
}

eu quiser usar string, ele tava dando erro de conversão.

public void salvar(String[] gruposId) {
...
}

pra mim não é um problema, mas de repente pode ser para outras pessoas.

m0ska, você tentou com List?

testei com List funfou beleza :wink:

Eu não sei se é possível, mas pra mim o ideal seria que se o name do select fosse assim: name=“fornecedor.grupos.id” ou algo parecido, ele já preencheria os ids dos grupos do fornecedor. Acho que é a solução mais elegante neste caso.