[VRaptor] Interceptando chamada de Métodos  XML
Índice dos Fóruns » Frameworks e Bibliotecas brasileiros
Autor Mensagem
rodrigousp
JavaEvangelist
[Avatar]

Membro desde: 09/10/2003 14:23:31
Mensagens: 379
Offline

Pessoal tudo bem !?

Gostaria de saber se é possível interceptar a invocação dos mutators no VRaptor sem apelar para AOP. Eu poderia fazer isso utilizando CGlib mas para isso eu preciso alterar o funcionamento do VRaptor para que ele utilize um construtor específico dos objetos do Modelo.

Abaixo o código que com AspectJ que faz o que eu quero (mas infelizmente depende do aspectj )



[]'s
Rodrigo

Rodrigo di Lorenzo Lopes - blogger
[MSN] [ICQ]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6396
Online

isso é feito nas entidades que vem do banco de dados?

você usa hibernate?

--
Caelum
www.caelum.com.br

rodrigousp
JavaEvangelist
[Avatar]

Membro desde: 09/10/2003 14:23:31
Mensagens: 379
Offline

Oi Lucas (herói do VRaptor )

Deixa eu esclarecer um pouco...

Eu utilizo um banco de dados não relacional chamado Mongo. Criei um framework para o mapeamento objeto - documentos chamado Monjo (https://github.com/rdllopes/monjo). Uma das features do Monjo é a habilidade dele fazer atualizações diferencias (leve em consideração que num banco não relacional um documento pode conter toda uma árvore de documentos). Isso é feito desprezando todas propriedades do objeto que não foram preenchidas. O problema é quando um usuário preenche uma propriedade com null (ou no caso do VRaptor, com uma String Vazia... ex: campo "Data de Despublicação" alterado de '01/07/2012' para '' e no Modelo a propriedade data de despublicação é do tipo Date...).

A solução mais simples (e porca) que vi seria adicionar uma propriedade com a lista de campos alterados em cada objeto e atualizar essa lista em cada um dos setters. Uma alternativa que achei razoável é utilizar AOP, mas isso forçaria todos usuários do Monjo a também utilizar aop.

Gostaria de saber se ao menos no VRaptor não seria possível resolver o problema de uma forma diferente.

[]'s
Rodrigo

Rodrigo di Lorenzo Lopes - blogger
[MSN] [ICQ]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6396
Online

o que vc quer usar é AOP por definição...

o que vc pode fazer é não usar o aspectJ (que seria a única dependência que vc adicionaria aos seus usuários, o que eu não vejo muito problema)

como vc receberia essas entidades? por parâmetros dos métodos dos controllers?

se sim, dá pra vc criar um interceptor que decora esses parâmetros com proxies. Algo assim:



o único chato é que não dá pra vc fazer o mixin, então vc teria que usar alguma mágica para gerar os dirty fields e para buscá-los depois.

um jeito talvez feio mas efetivo é criar um componente que tem um Map de Entidade para dirty fields e usar esse mapa no Monjo...

outro jeito é usar cglib puro (o proxifier é do vraptor e wrappeia o cglib), daí dá pra fazer o mixin sem problemas

--
Caelum
www.caelum.com.br

rodrigousp
JavaEvangelist
[Avatar]

Membro desde: 09/10/2003 14:23:31
Mensagens: 379
Offline

Pois é Lucas,

Depois de muita luta descobri que não seria assim tão fácil...

Pelo que eu entendi do código do VRaptor, o ParametersInstantiatorInterceptor faz duas coisas ( e por isso compromete uma solução mais simples).

1) Ele instancia uma floresta de objetos que será usada como parâmetros do método alvo no controller, no meu caso através do Ognl
2) Ele atribui às propriedade desses objetos os valores recebidos via parâmetros, no meu caso chamando os setters apropriado e fazendo as conversões necessárias

O problema é que a floresta de Objetos no passo 2 precisa ser uma floresta de proxies, porque depois que os setters já aconteceram o proxy já não funcionaria mais. A idéia do proxy é justamente interceptar essas chamadas de set*.

Talvez seja preciso configurar o Ognl para ele instanciar os proxies. Eu vi por cima a documentação do Ognl e parece que ele possui uma interface ClassResolver... o que me leva a um novo problema. Encontrar o código que recebe a class do ClassResolver, e que invoca o class.newInstace. Daí sim eu poderia alterar o código para usar um MonjoProxifier(class.newInstance) ...

Algumas dúvidas...
É mais ou menos isso que eu falei mesmo, ou estou viajando? Você acha que essa solução seria viável? Se sim, como/onde eu poderia alterar/configurar o Ognl para ele utilizar o MonjoProxifier?

[]'s




Rodrigo di Lorenzo Lopes - blogger
[MSN] [ICQ]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6396
Online

olá rodrigousp,

a gente fez uma modificação no OgnlParametersProvider para ele usar o objeto instanciado como root antes de aplicar os setters...

se vc usar o último snapshot (que eu anexei aqui) é só criar um interceptor que roda antes do ParametersInstantiatorInterceptor
e setar um atributo de request com o mesmo nome do parâmetro, que o ognl vai usar como root. Assim vc pode colocar o proxy
lá.

seria mais ou menos assim:



Que acha?
 Nome do arquivo vraptor-3.3.2-SNAPSHOT.jar [Disk] Download
 Descrição snapshot com o ognl modificado
 Tamanho 497 Kbytes
 Baixado:  10 vez(es)


--
Caelum
www.caelum.com.br

rodrigousp
JavaEvangelist
[Avatar]

Membro desde: 09/10/2003 14:23:31
Mensagens: 379
Offline

Bom valeu a ajuda Lucas mas acho que infelizmente essa solução não serve

Ocorre o seguinte, a entidade que chega em tese é uma árvore de entidades com qualquer loucura de objetos (uma propriedade pode ser uma lista de entidades com lista de entidades). Então, eu não posso simplesmente criar só o proxy da entidade raíz. É preciso que todas entidades da árvore também sejam proxies. Verdade, eu poderia fazer isso na mão... Mas instanciar todos objetos de uma árvore na mão me parece muito esforço.

O ideal seria saber onde ocorre o class.newInstance e mudar esse ponto. Eu não sei se isso ocorre dentro do ognl, e se for não sei se é possível configurá-lo para que ele passe a usar meu proxifier.

[]'s
Rodrigo

Rodrigo di Lorenzo Lopes - blogger
[MSN] [ICQ]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6396
Online

é um cara chamado ReflectionBasedNullHandler.

vc precisa decorá-lo com o cara que cria os seus proxies.



isso só resolve o dos objetos internos, pra resolver o problema da raiz não tem uma extensão boa ainda, teria que ter o interceptor, ou criar um método protected no OgnlParametersProvider (daí eu faço aqui).

o que acha?

PS: essa é a parte mais zuada do VRaptor, ainda é um pouco difícil modificar as coisas =(

--
Caelum
www.caelum.com.br

rodrigousp
JavaEvangelist
[Avatar]

Membro desde: 09/10/2003 14:23:31
Mensagens: 379
Offline

É lucas, isso tá dando trabalho.

Acabo de ler as classes...
Acho que não dá para simplesmente decorar os handlers. Na verdade, eu precisaria copiar o ReflectionBasedNullHandler e o GenericNullHandler (e.g.: MonjoReflectionBasedNullHandler e MonjoGenericNullHandler).

O ReflectionBasedNullHandler instancia o GenericNullHandler dentro do nullPropertyValue. Dentro do GenericNullHandler está a linha de código que preciso alterar...


No método nullPropertyValue ocorre a atribuição dessa instância recém criada.



Num tem como decorar isso
Alguma ideia!?



Rodrigo di Lorenzo Lopes - blogger
[MSN] [ICQ]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6396
Online

To mandando um outro snapshot agora...

sobrescreva o OgnlParametersProvider e sobrescreva o método nullHandler(), com o seu nullHandler decorado.
Vai funcionar tanto pra criar o root quanto pra setar as propriedades.

 Nome do arquivo vraptor-3.3.2-SNAPSHOT.jar [Disk] Download
 Descrição vraptor com o null handler modificado
 Tamanho 479 Kbytes
 Baixado:  11 vez(es)


--
Caelum
www.caelum.com.br

rodrigousp
JavaEvangelist
[Avatar]

Membro desde: 09/10/2003 14:23:31
Mensagens: 379
Offline

Ficou show a solução.

E o DirtWatcherNullHandler assim...




Mas estou com algum problema com o guice devido a mudança na versão do VRaptor, eu acho.



Rodrigo di Lorenzo Lopes - blogger
[MSN] [ICQ]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6396
Online

dica: pra vc não precisar guardar o removal, faça o seguinte:



o erro do VRaptor2 é pq eu apaguei esse pacote pra poder caber aqui no guj =S

use esse jar:
https://oss.sonatype.org/content/repositories/snapshots/br/com/caelum/vraptor/3.3.3-SNAPSHOT/vraptor-3.3.3-20110329.205406-1.jar

--
Caelum
www.caelum.com.br

Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6396
Online

na verdade use esse:
https://oss.sonatype.org/content/repositories/snapshots/br/com/caelum/vraptor/3.3.2-SNAPSHOT/vraptor-3.3.2-20110329.205836-1.jar

(problemas de versão)

--
Caelum
www.caelum.com.br

rodrigousp
JavaEvangelist
[Avatar]

Membro desde: 09/10/2003 14:23:31
Mensagens: 379
Offline

Acho que estou fazendo alguma coisa de errado.

Coloquei o tomcat em debug mode mas o meu DirtWatcherOgnlParametersProvider não é chamado.

Como eu registro o DirtWatcherOgnlParametersProvider? Precisa colocar alguma notação?

Vlw.
[]'s
Rodrigo


Rodrigo di Lorenzo Lopes - blogger
[MSN] [ICQ]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6396
Online

precisa anotar com @Component

--
Caelum
www.caelum.com.br

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