Injeção de Double nos parametros no vraptor [resolvido]

Tenho o seguinte controller:

@Path("/l10n/fetch-map/{coordX}/") public void coords(String coordX) { System.out.println(coordX); result.use(Results.nothing()); }

Quando acesso o URI /l10n/fetch-map/10/ funciona perfeitamente. Porém quando altero o parametro coordX para Double encontro o seguinte erro:

@Path("/l10n/fetch-map/{coordX}/") public void coords(Double coordX) { System.out.println(coordX); result.use(Results.nothing()); }

INFO: 22:51:45 DEBUG (VRaptorRequest.java:95) - Setting coordX with [10] SEVERE: StandardWrapperValve[default]: PWC1406: Servlet.service() for servlet default threw exception java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 at java.util.ArrayList.RangeCheck(ArrayList.java:547) at java.util.ArrayList.get(ArrayList.java:322) at br.com.caelum.vraptor.http.route.DefaultParametersControl.fillIntoRequest(DefaultParametersControl.java:101) at br.com.caelum.vraptor.http.route.FixedMethodStrategy.matches(FixedMethodStrategy.java:71) at br.com.caelum.vraptor.http.route.DefaultRouter.parse(DefaultRouter.java:113) at br.com.caelum.vraptor.http.DefaultResourceTranslator.translate(DefaultResourceTranslator.java:65) at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:64) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)

Fazendo um debug no código noto que no código br.com.caelum.vraptor.http.route.DefaultParametersControl o request.parameters vem vazio.

public void fillIntoRequest(String uri, MutableRequest request) { Matcher m = pattern.matcher(uri); m.matches(); for (int i = 1; i <= m.groupCount(); i++) { String name = parameters.get(i - 1); request.setParameter(name, m.group(i)); } }

O mais interessante é quando eu coloco um double no formato 10,00 o controller não é encontrado:

INFO: 23:00:47 DEBUG (DefaultResourceTranslator.java:63) - trying to access /l10n/map/10,00/ INFO: 23:00:47 DEBUG (DefaultResourceTranslator.java:67) - found resource null

Onde posso cadastrar supostos bugs do vraptor sem ser no github?

olá garcia…

provavelmente o problema é essa virgula…

se vc usar a url …/10.00/ deve funcionar…

o VRaptor usa o Double.valueOf no parâmetro pra fazer a conversão…
e isso só funciona se tiver ponto, não funciona com vírgula…

se ficar difícil trocar isso no jsp, você pode criar um converter tipo:

@Convert(Double.class)
@ApplicationScoped
public class DoubleConverter implements Converter<Double> {

    public Double convert(String value, Class<? extends Double> type, ResourceBundle bundle) {
        if (value == null || value.equals("")) {
            return null;
        }
        try {
            return Double.valueOf(value.replace(',', '.');
        } catch (NumberFormatException e) {
			throw new ConversionError(MessageFormat.format(bundle.getString("is_not_a_valid_number"), value));
        }
    }

}

Oi Lucas

Talvez seja interessante a gente lancar uma exception mais adequada em vez de deixar levantar uma IndexOutOfBoundsException, algo que de a entender que a URI nao se encaixou com os esperados

Lucas, você me entendeu errado.

Quando eu coloco double = 10.0 dá IndexOutOfBoundsException. Aliás sempre que uso double como parametro de entrada no método dá isso. Se eu usar meu método como coords(String coordX) funciona, quando uso coords(Double coordX) não funciona. É lançada essa exception. Fiz um debug no código e notei que o vraptor-rc1 a classe DefaultParametersControl retorna como se o método não tivesse parametros. Se eu fizer coords(String coordX, Double blah) ele retorna como se o método tivesse apenas um parametro.

Já em outro teste, quando eu usei na URL 10,0 (e na entrada do método double) deu como “page not found”. Nesse caso não houve a IndexOutOfBoundsException.

Vou ver se faço mais uns debugs quando chegar em casa, que possa auxiliar na detecção do problema.

Abraços

ok… é um bug então… tinha entendido que era só erro de conversão… vou verificar e corrigir o bug…

[]s

já identifiquei o problema… vai estar funcionando na próxima versão…

o fato de não funcionar com vírgula, é que o VRaptor limita o formato dos doubles pra
numero.numero ou numero

talvez seja bom mudar esse padrão…

Obrigado!

[quote=lucascs]já identifiquei o problema… vai estar funcionando na próxima versão…

o fato de não funcionar com vírgula, é que o VRaptor limita o formato dos doubles pra
numero.numero ou numero

talvez seja bom mudar esse padrão…

Obrigado![/quote]

Lucas, o normal mesmo dos decimais são usar com ponto mesmo. Mas como aqui no BR é com virgulas, quem save uma boa opção era basear-se no locale ou algo assim.

o VRaptor faz o matching de URIs usando expressões regulares… é BEM complicado fazer isso baseado no locale :stuck_out_tongue:

De qualquer forma, dá pra criar um componente do VRaptor que faça isso futuramente de um jeito mais extensível

olá garcia,

eu gerei um rc-2 com correção de vários bugs, alguns dos quais você apontou…

http://code.google.com/p/vraptor3/

se puder atualizar o seu vraptor, e me dizer se tudo funcionou, ficarei muito grato =)

Lucas, fiz os testes aqui e funcionou tudo bem. Digo, pelo menos os bugs que eu havia apontado.

Só tem um porém. Esse controller uso para informações de geoprocessamento, e quando coloco na URL um double negativo ele não consegue encontrar o recurso.

/l10n/map/10/51/ - funciona OK
/l10n/map/10.01/51.93/ - funciona OK
/l10n/map/-10.01/51.93/ - not-found

INFO: 22:15:55 DEBUG (DefaultResourceTranslator.java:63) - trying to access /l10n/map/-10.8540808/-11.7919526/
INFO: 22:15:55 DEBUG (DefaultResourceTranslator.java:67) - found resource null

Vou com calma tentar me interar com o código para já tentar te passar algo mais resolvido, hehe.

Abraços

já sei onde é o problema…

não previ que poderiam passar numeros negativos :stuck_out_tongue:

já foi corrigido no fonte

Aproveitando o tópico:

Usando o Converter Localizado: br.com.caelum.vraptor.converter.l10n do VRaptor eu consigo enviar como parametro num form um valor decimal com vírgula em
vez de ponto. O problema é que se um outro input der erro, o VRaptor repopula o meu input com o numero decimal com ponto. E se eu envio a requisicao com ponto,
o valor não é inserido como decimal mas sim como milhar.

Insiro 1,24.

deu erro

VRaptor popula com 1.24

Envio de novo

1.24 se torna 1240,00

Tem solução?

use a tag <fmt:formatNumber

Sim, isso funciona. Mas eu queria saber como eu faço pra mexer na conversao do valor pra exibir na view.

usando o fmt:formatNumber

<h1>Minha view legal</h1>
<fmt:formatNumber value="${oNumero}" />

se estiver com o locale setado corretamente ele vai imprimir o número com ,

Não foi isso que eu quis dizer, eu quero saber como eu posso ter o controle no back-end sobre a conversão que o VRaptor faz dos meus dados
inseridos no form na volta, isto é, a conversão que o VRaptor faz por exemplo de um string 1,99(vindo do form) para um double 1.99

o double não é formatado… é um número… com o <fmt:formatNumber vc coloca o que vc quiser…

vamos supor que vc fez um input pra esse número, só vc colocar o format com o mesmo nome no value:

<input type="text" name="meuObjeto.numero" value="<fmt:formatNumber value="${meuObjeto.numero}"/>" />

isso funciona… se vc quiser mudar o padrão, mude o locale ou use o pattern:

<fmt:formatNumber value="$..." pattern="#.###,##" />

ou algo do tipo

Então Lucas, eu entendi como usa a tag <format:… mas a questão que eu quero saber é que eu envio 1,99 e, se de erro, o VRaptor popula o meu form com 1.99.

O que eu quero saber é como eu posso popular “na mão” esse meu input, isto é, eu quero que, quando der um erro, o meu form seja populado com as strings que
foram inseridas. Eu sei que se eu usar a tag format eu corrijo isso, mas eu quero saber como o VRaptor faz pra repopular esse form e, se possível, mexer aí.

você testou o que eu falei pra vc usar? isso faz o que vc quer.

qdo dá erro de validação ou conversão, e vc usa o validator.onErrorXXXXX, o vraptor repassa os dados que vc mandou, em variaveis com o mesmo nome.