VRaptor 3 Converters - estou usando errado ou esbarrei em alguma limitação?  XML
Índice dos Fóruns » Frameworks e Bibliotecas brasileiros
Autor Mensagem
victorwss
JWizard
[Avatar]

Membro desde: 18/12/2007 14:46:00
Mensagens: 2409
Localização: São Paulo - SP
Offline

Olá, tenho uma dúvida avançada sobre o VRaptor. Não sei ao certo se estamos esbarrando em uma limitação dele ou se apenas o estamos usando de forma errada.
Aqui vai a controller inicial:Isso funciona perfeitamente. No entanto não estamos satisfeitos e gostaríamos que os parâmetros fossem do tipo Usuario. Lá vai a primeira tentativa:Isto falha miseravelmente. O VRaptor não pesquisa a entidade no banco de dados, o que ele faz é instanciar o Usuario e chamar os setters.
Esta outra tentativa é mais feliz:
E para que o VRaptor saiba como instanciar o usuário, usamos isso:E então, até aqui, a controller funciona como esperado.

No entanto, quando eu uso o metodo outroMetodo, que tem um redirectTo, o VRaptor gera umas URLs assim:
/meuprojeto/br.com.teste.Usuario@45f7e2/perfil

Apesar de a conversão de ida String->Usuario ter usado o Converter, a conversão de volta Usuario->String sempre usa o método toString().
Utilizar o método toString() sempre é muito restritivo, pois ele já é utilizado para outras finalidades.

Para contornar este problema, existem algumas soluções possíveis. Mas todas elas são meio gambiarrosas.

A primeira delas é criar um Router herdando de DefaultRouter e sobreescrever o método urlFor por um quase idêntico, mas com uma diferença:É substituído por:Este código é uma gambiarra grotesca, que consiste em consertar a URL errada que foi gerada.

Para tentar fazer um código menos gambiarroso, analisamos que a variável matches é do tipo Iterator<Route> e a implementação concreta de Route é FixedMethodStrategy.
O Iterator<Route> é criado pela classe PathAnnotationRoutesParser, que por sua vez utiliza a RouteBuilder. RouteBuilder instancia a FixedMethodStrategy, injetando nela uma instância de DefaultParametersControl.
O método fillUri(Object) de DefaultParametersControl utiliza o método toString() e é aí que é a origem do problema.
A classe PathAnnotationRoutesParser está fortemente acoplada a RouteBuilder, que por sua vez está fortemente acoplada a FixedMethodStrategy e a DefaultParametersControl, o que significa que substituir a implementação de alguma destas classes por outra coisa é algo difícil.

Uma outra possibilidade mais atraente para resolver isso sem precisar desta gambiarra seria criar uma espécie de decorator de Route e fazer o matcher conter instâncias apenas do decorator. Mas isso continua sendo algo trabalhoso.

Então vem a minha pergunta: Estamos usando o VRaptor de uma forma inadequada ou não prevista? Caso seja inadequada, eu devo me contentar em receber apenas Strings e números como parâmetros extraídos da URL e devo deixar coisas mais complexas apenas para dados de formulários? Caso contrário, gostaria de sugerir uma nova interface para um "Converter reverso", e então o meu converter ficaria assim:Essa interface hipotética ReverseConverter resolveria este tipo de problema.

This message was edited 1 time. Last update was at 01/09/2010 01:07:59


Victor Williams Stafusa da Silva

Bacharel em Ciência da Computação - UFMT // Especialista em Desenvolvimento Java - CEFET/MT // Doutorando em Ciência da Computação - IME-USP
SCJP 6.0 - 19/12/2007 - PASS - 88% // SCWCD 5 - 17/05/2008 - PASS - 79% // SCJA - 09/09/2008 - PASS - 96% // SCSNI - 30/06/2009 - PASS - 68% // SCBCD 5 - 31/05/2010 - PASS - 95%
Próximos: SCJD (encalhado com o projeto), SCEA parte I (estudando). Algum dia desses: SCMAD, OCA, SCEA e SCDJWS.

Computação: uma ciência holística e esotérica!
E então veio Deus a terra e disse aos homens: Não dividireis por zero.
XML is a giant step in no direction at all. (Erik Naggum)
Arquitetura de sistemas: Eu prefiro ser essa metamorfose ambulante do que ter aquela velha opinião formada sobre tudo.
Diga não as drogas: Não use java.util.Vector.
Cuidado: Este usuário pode ter temperamento agressivo.

Always code as if the person who will maintain your code is a maniac serial killer that knows where you live.
I am the maniac serial killer that knows where you live who will maintain your code.


É impossível falar de CMMI (Capability Maturity Model Integration) sem saber o que é CIMM (Capability Im-Maturity Model).


Se você escreve "concerteza", "concerteza" você andou matando aulas de português.
[MSN]
dev.rafael
Virtual Machine Man
[Avatar]

Membro desde: 17/09/2007 01:35:27
Mensagens: 631
Offline

Cara, eu não tenho muita experiência com VRaptor mas, até onde eu me lembro, ele não requer conversão de objetos para
Strings (como JSF) posto que você mesmo renderiza a página usando JSP.

O código ai de cima não funciona?

Esquece isso. O que eu falei não tem nada a ver!!

This message was edited 1 time. Last update was at 01/09/2010 09:48:05


"A mente humana é limitada, mas a estupidez é ilimitada." Wilhelm Steinitz
[Email]
pbnf
JavaGuru

Membro desde: 18/06/2003 12:06:55
Mensagens: 228
Localização: De volta a Cuiabá-MT, 40º na sombra !!!
Offline

Olá Armadilha,

Como vc explicou muito bem o seu problema eu vou ser mais curto, leia http://vraptor.caelum.com.br/documentacao/resources-rest/

OBS:

- Não ha necessidade de colocar no @Path o contexto da aplicação.


Isto falha miseravelmente. O VRaptor não pesquisa a entidade no banco de dados, o que ele faz é instanciar o Usuario e chamar os setters.


- O vraptor não sabe que existe banco de dados, e o comportamento por padrão dele é instaciar o objeto e popular e te entregar pronto no controller.

This message was edited 2 times. Last update was at 01/09/2010 15:41:11

Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6395
Offline

@victorwss
isso de usuario.login só usar os setters é o comportamento esperado do VRaptor mesmo. Ele não tem como saber qual é o seu banco de dados ou como vc quer buscar o Usuario no banco

De qqer forma achei muito interessante a sua abordagem de converters! Não tinha pensado nessa possibilidade, e acho que vale a pena fazer isso funcionar e escrever na documentação do VRaptor uma receita (http://vraptor.caelum.com.br/cookbook)

detalhes:
- o seu converter deveria ser request scoped se o seu dao for request scoped (escopo padrão).

- concordo que o acoplamento das classes PathAnnotationRoutesParser, RoutesBuilder e ParametersControl está bastante alta... criei uma issue para refatoração: http://github.com/caelum/vraptor/issues/issue/239

- vcs não estão usando errado, é só uma forma não prevista mesmo...

de qqer forma, vou tentar criar essa interface ReverseConverter e fazer ela funcionar, e já te mando um snapshot pra vc testar =)

Muito obrigado pelo Hack

--
Caelum
www.caelum.com.br

garcia-jj
JWizard

Membro desde: 13/04/2009 22:11:50
Mensagens: 2715
Localização: Porto Alegre
Offline

Isto falha miseravelmente. O VRaptor não pesquisa a entidade no banco de dados, o que ele faz é instanciar o Usuario e chamar os setters.


Mas hein?!

Lucas Cavalcanti wrote:De qqer forma achei muito interessante a sua abordagem de converters! Não tinha pensado nessa possibilidade, e acho que vale a pena fazer isso funcionar e escrever na documentação do VRaptor uma receita (http://vraptor.caelum.com.br/cookbook)


Eu também gostei, e nunca tinha pensado nessa prossibilidade. Porém acho que ao invés de ReverseConverter poderiamos alterar o atual converter para ser bidirecional, estilo o XmlAdapter do JAXB.

This message was edited 1 time. Last update was at 01/09/2010 16:44:46


http://github.com/garcia-jj
Não respondo dúvidas via MP. Use o fórum.
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6395
Offline

garcia-jj wrote:
Eu também gostei, e nunca tinha pensado nessa prossibilidade. Porém acho que ao invés de ReverseConverter poderiamos alterar o atual converter para ser bidirecional, estilo o XmlAdapter do JAXB.

to criando um TwoWayConverter extends Converter

--
Caelum
www.caelum.com.br

Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6395
Offline

criado o snapshot =)

https://oss.sonatype.org/content/repositories/snapshots/br/com/caelum/vraptor/3.2.0-SNAPSHOT/vraptor-3.2.0-20100901.225614-2.jar

o nome da interface é a TwoWayConverter (que estende Converter), pode testar pra mim por favor @victorwss ?

--
Caelum
www.caelum.com.br

victorwss
JWizard
[Avatar]

Membro desde: 18/12/2007 14:46:00
Mensagens: 2409
Localização: São Paulo - SP
Offline

pbnf wrote:
- O vraptor não sabe que existe banco de dados, e o comportamento por padrão dele é instaciar o objeto e popular e te entregar pronto no controller.
Lucas Cavalcanti wrote:
isso de usuario.login só usar os setters é o comportamento esperado do VRaptor mesmo. Ele não tem como saber qual é o seu banco de dados ou como vc quer buscar o Usuario no banco
garcia-jj wrote:Mas hein?!

Eu sei que o VRaptor não conhece o banco e que aquilo não daria certo nunca. Acho que não me expressei direito, o que eu queria dizer é que a primeira ideia ingênua para resolver é aquela, mas ela falha pelo motivo óbvio que todos aqui sabem: O VRaptor não conhece o banco de dados e mesmo se conhecesse ele não teria informação suficiente para fazer aquilo, a semântica que ele usa é sempre instanciar o bean e chamar os setters e nunca fazer uma busca em algum lugar por um bean já existente. E é este um dos motivos pelo qual usamos os converters.

Lucas Cavacanti wrote:
- o seu converter deveria ser request scoped se o seu dao for request scoped (escopo padrão).

Obrigado. Você descobriu um bug obscuro na nossa aplicação que dificilmente iríamos perceber.

Lucas Cavalcanti wrote:
criado o snapshot =)

Obrigado. Vou brincar com ele um pouco e depois eu digo o que aconteceu.

Bem, uma observação que tenho que fazer, para que vocês fiquem cientes e coloquem no cookbook, é que se o bean for acessado na URL por duas ou mais formas diferentes de acordo com casos específicos (ex: em um lugar eu uso o id do usuário, em outro lugar o login, e em outro o CPF), é responsabilidade do converter lidar com isso, o que tende a ser bem complicado, e por este motivo deve ser fortemente recomendado que o acesso a um determinado bean na URL seja uniforme. Com algum tipo de converter mais complexo seria mais fácil suportar este caso, mas acho que não vale a pena. De qualquer forma gostaria que pensassem um pouco neste aspecto.

Pbnf, sei que te conheço pessoalmente, mas pelo seu nick não dá para saber quem você é. Poderia me dizer o teu nome real?

Obrigado a todos

Victor Williams Stafusa da Silva

Bacharel em Ciência da Computação - UFMT // Especialista em Desenvolvimento Java - CEFET/MT // Doutorando em Ciência da Computação - IME-USP
SCJP 6.0 - 19/12/2007 - PASS - 88% // SCWCD 5 - 17/05/2008 - PASS - 79% // SCJA - 09/09/2008 - PASS - 96% // SCSNI - 30/06/2009 - PASS - 68% // SCBCD 5 - 31/05/2010 - PASS - 95%
Próximos: SCJD (encalhado com o projeto), SCEA parte I (estudando). Algum dia desses: SCMAD, OCA, SCEA e SCDJWS.

Computação: uma ciência holística e esotérica!
E então veio Deus a terra e disse aos homens: Não dividireis por zero.
XML is a giant step in no direction at all. (Erik Naggum)
Arquitetura de sistemas: Eu prefiro ser essa metamorfose ambulante do que ter aquela velha opinião formada sobre tudo.
Diga não as drogas: Não use java.util.Vector.
Cuidado: Este usuário pode ter temperamento agressivo.

Always code as if the person who will maintain your code is a maniac serial killer that knows where you live.
I am the maniac serial killer that knows where you live who will maintain your code.


É impossível falar de CMMI (Capability Maturity Model Integration) sem saber o que é CIMM (Capability Im-Maturity Model).


Se você escreve "concerteza", "concerteza" você andou matando aulas de português.
[MSN]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6395
Offline

victor, só um adendo:
qdo vc coloca @Path("/users/{user.id}") o VRaptor sabe que o id é número, por exemplo, e só deixa colocar números nessa parte da url. Se vc coloca @Path("/users/{user}") o VRaptor vai aceitar qqer coisa.

Então vc teria que falar que só pode aceitar números: @Path("/users/{user:\\d+}")...

Você quer escrever o cookbook, já que a idéia é sua? A gente coloca com o seu nome no site do VRaptor.

[]'s

--
Caelum
www.caelum.com.br

Paulo Silveira
Administrador
[Avatar]

Membro desde: 07/08/2002 18:38:50
Mensagens: 4204
Localização: São Paulo
Offline

Oi Victor! Foi uma excelente ideia. Valeu Lucas pelas implementacao para permitir isso. Parabens aos dois.

http://blog.caelum.com.br twitter: @paulo_caelum


[Email] [WWW]
Spidey
Thread.start()

Membro desde: 27/08/2010 17:08:27
Mensagens: 30
Offline

Se não me engano, por um acaso trabalho com o victorwss, e foi com o código que ele também fez que eu to aprendendo VRaptor (além da documentação do site né, mas aprender por exemplo auxilia bastante).
De início eu achava que o VRaptor chamava o construtor correto. Será que não dá pra fazer isso sem utilizar um converter?

Pensei no próprio VRaptor identificando um campo numérico, por exemplo, e chamando um construtor.

Por exemplo, eu chamo



Outra coisa que podia rolar é usar um ${parametro#tipo}, de forma que o valor dessa variável seria usado na chamada do construtor em "new MinhaClasse(tipo);".


Não sei se fui claro, qualquer coisa eu tento explicar de outra forma.
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6395
Offline

tem como fazer isso habilitando o IOGI no VRaptor...

assim se vc tiver:



e fizer


ele vai instanciar usando o construtor, com o tipo certo (só vai aceitar numeros).

para habilitar o IOGI, coloque no web.xml:


e coloque o jar do iogi no WEB-INF/lib. Pode tirar o ognl do lib se quiser depois de fazer isso.

mais info: http://vraptor.caelum.com.br/documentacao/componentes-utilitarios-opcionais/


o problema do victor não era instanciar pelo construtor, e sim já carregar do banco.

This message was edited 1 time. Last update was at 02/09/2010 18:50:31


--
Caelum
www.caelum.com.br

Spidey
Thread.start()

Membro desde: 27/08/2010 17:08:27
Mensagens: 30
Offline

Como minha aplicação é simples, eu implementaria essa busca do banco direto no construtor do objeto, passa o id dele, chamo o dao e copio os campos objeto que o dao retorno pra instância.
victorwss
JWizard
[Avatar]

Membro desde: 18/12/2007 14:46:00
Mensagens: 2409
Localização: São Paulo - SP
Offline

Lucas e Paulo, testei o TwoWayConverter e funcionou perfeitamente.

Posso sim escrever o cookbook. Mas não entendi essa de colocar regex na URL. Poderia explicar melhor? Eu pessoalmente preferiria colocar este tipo de validação no Converter.

This message was edited 1 time. Last update was at 02/09/2010 21:28:03


Victor Williams Stafusa da Silva

Bacharel em Ciência da Computação - UFMT // Especialista em Desenvolvimento Java - CEFET/MT // Doutorando em Ciência da Computação - IME-USP
SCJP 6.0 - 19/12/2007 - PASS - 88% // SCWCD 5 - 17/05/2008 - PASS - 79% // SCJA - 09/09/2008 - PASS - 96% // SCSNI - 30/06/2009 - PASS - 68% // SCBCD 5 - 31/05/2010 - PASS - 95%
Próximos: SCJD (encalhado com o projeto), SCEA parte I (estudando). Algum dia desses: SCMAD, OCA, SCEA e SCDJWS.

Computação: uma ciência holística e esotérica!
E então veio Deus a terra e disse aos homens: Não dividireis por zero.
XML is a giant step in no direction at all. (Erik Naggum)
Arquitetura de sistemas: Eu prefiro ser essa metamorfose ambulante do que ter aquela velha opinião formada sobre tudo.
Diga não as drogas: Não use java.util.Vector.
Cuidado: Este usuário pode ter temperamento agressivo.

Always code as if the person who will maintain your code is a maniac serial killer that knows where you live.
I am the maniac serial killer that knows where you live who will maintain your code.


É impossível falar de CMMI (Capability Maturity Model Integration) sem saber o que é CIMM (Capability Im-Maturity Model).


Se você escreve "concerteza", "concerteza" você andou matando aulas de português.
[MSN]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6395
Offline

eh que é assim, suponha que user.id é um número

se o path eh @Path("/users/{user.id}"), a URI /users/banana dá 404 direto, nem passa por nada...

se vc colocar @Path("/users/{user}") tudo vai passar pelo converter

se vc colocar @Path("/users/{user:\\d+}") só vai bater URIs que sejam números /users/234, /users/1, etc... se for /users/asdf é 404 direto tb...

o que vc deveria fazer tb é: se o usuario com o id passado não existir no banco, dar 404 direto. Então a gente precisa ver um jeito fácil de fazer isso. Alguma sugestão?

--
Caelum
www.caelum.com.br

 
Índice dos Fóruns » Frameworks e Bibliotecas brasileiros
Ir para:   
Powered by JForum 2.1.8 © JForum Team