VRaptor3: validator.onErrorUse(voltar());

Amigos, estou com um pequeno problema na vaidação.

Criei um aspecto pra validar todos os metodos registrar(entity).

vejam e opinem:

	@Pointcut("execution(public void *.registrar(..)) && args(entity,..)")
	public void validar(Object entity){};
	
	@Before("validar(entity)")
	public void validarBefore(JoinPoint joinPoint, Object entity){
		logger.debug("Validando beans");

		//Infelizmente ainda tenho que fazer isso para não levar nullpointer
		JSR303Validator.getFactory();

		validator.validate(entity);
		validator.onErrorUse(Results.referer()).forward();
	}

O problema é o seguinte:

Eu quero ter um efeito semelhande ao código acima, só que não quero depender do cliente enviar o header referer para saber para quem responder, e sim usar uma convenção onde se o método a ser validado for Batatas.registrar(Batata batata) o formulário está em Batatas.formularioBatataRegistrar(), e é para la que eu vou apontar o erro também;

se fosse pra colocar no próprio controler ficaria:

	@Get
	@Path("/registro")
	public void formularioRegistrar(){}
	
	@Post
	@Path("/registro")
	public void registrar(Batata batata){
		validator.onErrorUse(page()).of(getClass()).formularioRegistrar();
		//neǵocios
	}

mas criei o aspecto justamente para não fazer isso.

Lá no aspect não estou conseguindo pegar as informações do método que foi interceptado, para tentar formar o nome do método que quero chamar…

Alguém tem alguma idéia?

baixe o último snapshot:
http://oss.sonatype.org/content/repositories/snapshots/br/com/caelum/vraptor/3.1.3-SNAPSHOT/vraptor-3.1.3-20100519.161626-7.jar

que não tem mais o problema do nullpointer…

e faça algo do tipo:

@Before("validar(entity)")  
public void validarBefore(JoinPoint joinPoint, Object  entity){
    Class<?> controller = joinPoint.getSignature().getDeclaringClass();

    String methodName = joinPoint.getSignature().getSimpleName();

    validator.validate(entity);
    Object proxy = validator.onErrorUse(page()).of(controller);
    new Mirror().on(proxy).invoke().method("formulario" + methodName).withoutArgs();
} 

a última linha é pra invocar o método tendo o nome dele em string…

valeu lucas…

tive apenas alguns problemas mas era isso mesmo que eu queria saber.

Olha. no joinPoint.getSignature() não tinha o método getDeclaringClass, mas sim o getDeclaringType… que fez a mesma coisa…

também não tinha o getSimpleName(), e não consegui outro método para pegar o nome do método interceptado.

mas, para testar a última linha eu fiz:

new Mirror().on(proxy).invoke().method("tomate").withoutArgs();

mas eu levo

06/06/2010 14:40:26 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
br.com.caelum.vraptor.InterceptionException: an exception was raised while executing resource method
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:86)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:77)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:47)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:81)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:70)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:56)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:619)
Caused by: net.vidageek.mirror.exception.ReflectionProviderException: Could not invoke method tomate
	at net.vidageek.mirror.provider.java.PureJavaMethodReflectionProvider.invoke(PureJavaMethodReflectionProvider.java:45)
	at net.vidageek.mirror.invoke.MethodHandlerByMethod.withArgs(MethodHandlerByMethod.java:54)
	at net.vidageek.mirror.invoke.MethodHandlerByName.withArgs(MethodHandlerByName.java:46)
	at net.vidageek.mirror.invoke.MethodHandlerByName.withoutArgs(MethodHandlerByName.java:42)
	at br.teste.aspect.Validacao.validarBefore(Validacao.java:40)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:627)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:609)
	at org.springframework.aop.aspectj.AspectJMethodBeforeAdvice.before(AspectJMethodBeforeAdvice.java:39)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:49)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:160)
	at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:50)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:160)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:77)
	at br.teste.aspect.Transacao.realizarAround(Transacao.java:32)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:627)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:616)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:64)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:160)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
	at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
	at br.teste.controller.DefaultController$$EnhancerByCGLIB$$6444265b.registrar(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:57)
	... 37 more
Caused by: br.com.caelum.vraptor.validator.ValidationException
14:40:26,705 DEBUG [VRaptor             ] VRaptor received a new request
14:40:26,708 DEBUG [DefaultRequestExecution] executing stack  DefaultRequestExecution
14:40:26,722 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor ResourceLookupInterceptor
14:40:26,742 DEBUG [DefaultResourceTranslator] trying to access /scripts/lib/jquery-1.4.2.min.js
14:40:26,743 DEBUG [VRaptor             ] VRaptor ended the request
14:40:26,768 DEBUG [DefaultStaticContentHandler] Deferring request to container: /styles/default.css 

reparem que no final ele manda a request para o vraptor montar a view… ele monta a view do método tomate… mas não o executa…

	public void tomate(){
		System.out.println("TOMATE NO ARGS");
	}

usando

joinPoint.getSignature().getName()

consegui o nome do método… mas mesmo assim recebo a exception

Could not invoke method tomate

tá dando esse erro…

tenta ver qual classe tá sendo retornada no getDeclaringType() e vê se é a classe do controller mesmo

System.out.println(joinPoint.getSignature().getDeclaringType());

class br.teste.controller.DefaultController

Ai eu mudei para um método que realmente NÃO existe:

new Mirror().on(proxy).invoke().method("alface").withoutArgs();

ai o exception mudou para

Caused by: net.vidageek.mirror.exception.MirrorException: Could not find method alface on class br.teste.controller.DefaultController$$EnhancerByCGLIB$$1ad8b750

Com método que não existe:
Could not find method alface

Com método que existe:
Could not invoke method tomate

então acho que ele está achando o método… mas por algum motivo não consegue invocar…

dá uma olhada na última linha:

Caused by: br.com.caelum.vraptor.validator.ValidationException

o problema é que o validation.onErrorUse solta uma ValidationException ao fim da invocação do método, pro vraptor conseguir parar a execução e executar o erro de validação… e o Mirror tá relançando a exception…

faça o seguinte então:

try {
   new Mirror().on(proxy).invoke().method("tomate").withoutArgs();
} catch (ReflectionProviderException e) {
     throw e.getCause();
}

isso deve funcionar…

desse jeito não da o exception mas não executa o método tomate no controller :frowning:

aí que tá, não é pra executar!

não se vc estiver usando o page()).of(

se vc quiser que execute o método tomate (qdo der erro de validação) use:

validator.onErrorUse(logic()).forwardTo(controller);

o resto da lógica é igual…

(lembre-se page() só mostra a página, logic() executa a lógica)

Deu certo Lucas. Valeu!