[resolvido] VRaptor - LinkTo ... no servidor?

Olá…

O LinkTo me abriu o olho…
e realmente não to afim de repetir as URI… Ficou facil fazer isto na view com o linkTo…

Porém eu preciso pegar a URI de um método no lado servidor.
Existe uma maneira facil e ‘clean’ de fazer isso ?

obrigado!

EDIT

Eu quero pegar a URI do método, pq eu to fazendo uma feature que vou mandar
um link no email do cliente. Quero montar esse link dinamicamente.

E eu não quero correr o risco de mudar a URI do método mais tarde
e depois enviar emails com links quebrados. Isso seria mto feio né ?
kkkkkkkkk

Ja peguei o Host e o Context Path do request. Só falta a URI.

Existe… Use o result.redirectTo(Controller.class).action()…

não quero usar redirect !

Quero saber o path anotado do método

@Get("/get/algo")
public void index(){
}

algo tipo

String uri = LinkToHandler.getURI(ExemploController.class).index();

**EDIT

o valor da var uri seria “/get/algo”

Eu não sei se o VRaptor tem algo para isso… Podemos pesquisar.

Eu faria com reflection pegando o @Get e/ou @Path daquela action…

Existe um componente do VRaptor que sabe gerar as rotas: o Router

String url = router.urlFor(ExemploController.class, ExemploController.class.getDeclaredMethod("index"));

Ou seja, vc passa pra ele a classe, o método e os parâmetros desse método, e ele te dá a url.

o problema que isso lança exceptions chatas, vc pode usar o mirror pra refletir o método pra se livrar delas:

Method method = new Mirror().on(ExemploController.class).reflect().method("index").withoutArgs();

se vc acha que vai usar isso bastante, me dá um toque que eu te ajudo a escrever um componente maroto que faz isso de um jeito mais fácil :wink:

[quote=Lucas Cavalcanti]Existe um componente do VRaptor que sabe gerar as rotas: o Router

String url = router.urlFor(ExemploController.class, ExemploController.class.getDeclaredMethod("index"));

Ou seja, vc passa pra ele a classe, o método e os parâmetros desse método, e ele te dá a url.

o problema que isso lança exceptions chatas, vc pode usar o mirror pra refletir o método pra se livrar delas:

Method method = new Mirror().on(ExemploController.class).reflect().method("index").withoutArgs();

se vc acha que vai usar isso bastante, me dá um toque que eu te ajudo a escrever um componente maroto que faz isso de um jeito mais fácil ;)[/quote]

cara… legal !

não sei se vou usar bastante… mas bora fazer o componente ?

blz, a graça desse componente é vc conseguir descobrir a classe e o método ‘magicamente’. Tipo isso:

Linker linker = //

linker.buildLinkTo(ExemploController.class).index();
String url = linker.getUrl();

não dá pra fazer em um passo só, pq o index retorna void

a idéia é esse Linker receber um proxifier no construtor e gerar um proxy no buildLinkTo que captura o método invocado e os parâmetros e no getUrl usa essas informações para passar para o Router.

Se precisar de mais ajuda dá um toque.

Legal…

Acho que entendi a ideia…
Mas vou precisar de uma aulinha sua !!
Você se impota?

Eu fiz um esboço… Mas fiz seguindo tuas palavras e sem entender
muito bem o que estou fazendo… O que é horrível :frowning:

Então… O que o Proxifier retorna? (Não me diga um Object ! kkk)
Como que funciona ? Quem que vai pegar o retorno dele?

Se eu quiser fazer uns testes de unidade no Linker, como injeto componentes do VRaptor no meu test?

Ta aqui o que eu fiz até agora:

@Component
public class Linker {

	private Logger logger = Logger.getLogger(Linker.class);
	
	private Proxifier proxifier;
	private Router router;
	
	private Class<?> clazz;
	private Method invokedMethod;
	private Object[] arguments;
	
	public Linker(Proxifier proxifier, Router router) {
		this.proxifier = proxifier;
		this.router = router;
		
		proxifier.proxify(Linker.class, new MethodInvocation<Linker>() {

			@Override
			public Object intercept(Linker proxy, Method method, Object[] args, SuperMethod superMethod) {
				invokedMethod = method;
				arguments = args;
				
				return null;
			}
		});
		
	}

	public String getURI(){
		return router.urlFor(clazz, invokedMethod, arguments);
	}
	
	public <T> T buildLinkTo(Class<T> clazz){
		this.clazz = clazz;
		try {
			return clazz.newInstance();
		} catch (InstantiationException e) {
			logger.error("Can´t instanciate class: "+clazz.getSimpleName(), e);
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			logger.error("Error on "+clazz.getSimpleName(), e);
			e.printStackTrace();
		}
		
		return null;
	}
	
}

Obrigado

O proxifier retorna um proxy da classe que vc passou…

e daí vc passa um interceptor que executa o código que vc quiser. Nesse caso o que vc quer fazer é capturar o método.

a sua classe está quase pronta, só que ao invés do proxifier.proxify estar no construtor ele tem que estar no buildLinkTo:

public <T> T buildLinkTo(Class<T> clazz){ 
     this.clazz = clazz;
     return this.proxifier.proxify(clazz, new Method.....) {..};
}

para testar, vc tem que passar um proxifier de verdade (é meio difícil de testar), pode ser o new JavassistProxifier(), e passar um mock do Router. Daí vc verifica que ele chamou o urlFor passando a classe e o método esperados.

[quote=Lucas Cavalcanti]O proxifier retorna um proxy da classe que vc passou…

e daí vc passa um interceptor que executa o código que vc quiser. Nesse caso o que vc quer fazer é capturar o método.

a sua classe está quase pronta, só que ao invés do proxifier.proxify estar no construtor ele tem que estar no buildLinkTo:
[/quote]

ta… mas o que o meu método intercept tem que retornar? Pq eu to retornando null…
Aqui com as modificações que vc falou

...

	@SuppressWarnings("unchecked")
	public <T> T buildLinkTo(Class<T> clazz){
		this.clazz = clazz;
			return (T) proxifier.proxify(Linker.class, new MethodInvocation<Linker>() {

					@Override
					public Object intercept(Linker proxy, Method method, Object[] args, SuperMethod superMethod) {
						invokedMethod = method;
						arguments = args;
						
						return null;
					}
				});
	}

pode retornar null sem problemas… a gente não usa o retorno do método pra nada.

cara,
como que a proxy vai ficar na classe que o cara passou se eu não posso:

return (T) proxifier.proxify(clazz, new MethodInvocation<clazz>() {

?

bom , eu pensei…
vou olhar no vraptor como que o Result funciona né…

ai olhei esta classe:

e MANO do céu, de onde saiu esse método use() ?

a gente tem ele na interface:

mas onde que ele é implementado ?

falei brincando com um amigo meu que o pessoal da Caelum tava mexendo com bruxaria…
Agora eu tô com medo de que seja verdade!
asdjiashudahusdhuasd

abraços

é implementado no DefaultResult…

vc pode fazer:

return (T) proxifier.proxify(clazz, new MethodInvocation<T>() {  

afinal, o clazz é um Class

Nossa que mancada!
x]

vlww mano…
muito obrigado !!!