[RESOLVIDO] VRaptor - Módulos ERP - URL

Olá Galera!

Meu sistema ERP, tem vários módulos (Financeiro, Operacional, Compras, RH, etc), estou usando VRaptor.

Gostaria de implementar o seguinte

Suponhamos que eu tenha um FuncionarioController, que pertence ao módulo RH.
Então, na WEB-INF/jsp eu tenho a pasta funcionario/ com todos .jsp’s necessário dele. E a URL padrão seria /sistema/funcionario

O que eu quero, é mudar essa URL, fazer por exemplo /sistema/rh/funcionario, ou então numa outra situação /sistema/operacional/frete

Só que não quero anotar todos os métodos com o @Path.

Há uma forma de fazer isso?
Gostaria de dicas. Como vocês implementariam algo assim?

Obrigado!

você pode sobrescrever o componente RoutesParser do VRaptor, colocando a convenção que você quiser.

um dos jeitos é criar uma classe que estende PathAnnotationRoutesParser, e sobrescreve um dos métodos protected dela.

[quote=Lucas Cavalcanti]você pode sobrescrever o componente RoutesParser do VRaptor, colocando a convenção que você quiser.

um dos jeitos é criar uma classe que estende PathAnnotationRoutesParser, e sobrescreve um dos métodos protected dela.[/quote]

Lucas, pode me dar um exemplo?

Muito Obrigado cara!

@Component
@ApplicationScoped
public class MeuRoutesParser extends PathAnnotationRoutesParser {
    
    //delegate constructor

    @Override
    protected String[] urisFor(Method method, Class<?> type) {
         // sua convenção aqui, talvez usando o super.urisFor
    }
}

Lucas, pode me dar um outro exemplo? Alguma implementação.
Não sei como usar essa classe.

Obrigado cara!

os métodos protected tem nomes razoavelmente claros… dá uma olhada na implementação padrão:

Tem razão Lucas, vi a implementação padrão.
Vou implementar aqui e depois posto como fiz.

Valeu! Abração!

Cara, consegui implementar, mas notei que preciso fazer uma outra coisa também.
Por exemplo, A url padrão agora é /sistema/operacional/frete, certo, mas o vraptor procura em WEB-INF/jsp/frete

Como faço para o vraptor procurar em WEB-INF/jsp/operacional/frete?

Obrigado!

precisa sobrescrever outro componente, o PathResolver…

a implementação padrão é a DefaultPathResolver.

Lucas, eu implementei o meu PathResolver

@Component
public class ModuloPathResolver extends DefaultPathResolver{

	private FormatResolver resolver;

	public ModuloPathResolver(FormatResolver resolver) {
		super(resolver);
		this.resolver = resolver;
	}
	
	@Override
	public String pathFor(ResourceMethod method) {
		String format = this.resolver.getAcceptFormat();

		String suffix = "";
		if (format != null && !format.equals("html")) {
			suffix = "." + format;
		}
        String name = method.getResource().getType().getSimpleName();
        String folderName = extractControllerFromName(name);
        
		return this.getPrefixo(folderName) + folderName + "/" + method.getMethod().getName() + suffix
				+ "."+getExtension();
	}
	
	private String getPrefixo(String controller) {
		return "/WEB-INF/jsp/" + this.getModulo(controller);
	}

	private String getModulo(String controller) {
		String modulo = "";
		if( controller.contains("frete") ){
			modulo = "operacional/";
		}	
		return modulo;
	}
}

Mas, quando tento acessar /sistema/operacional/frete ele não procura no lugar correto, ou não acha o controller, não sei.

No log normalmente aparece assim, quando acesso uma outra url qualquer do sistema

16:28:20,721 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor ForwardToDefaultViewInterceptor
16:28:20,721 DEBUG [ForwardToDefaultViewInterceptor] forwarding to the dafault page for this logic
16:28:20,739 DEBUG [DefaultPageResult   ] forwarding to /WEB-INF/jsp/funcionario/list.jsp
16:28:20,741 DEBUG [DefaultStaticContentHandler] Deferring request to container: /sistema/WEB-INF/jsp/funcionario/list.jsp 
16:28:20,814 DEBUG [VRaptor             ] VRaptor ended the request

Mas quando acesso a url que estou tentando “filtrar”, aparece assim

16:29:00,026 DEBUG [VRaptor             ] VRaptor received a new request
16:29:00,056 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor ResourceLookupInterceptor
16:29:00,056 DEBUG [DefaultResourceTranslator] trying to access /operacional/frete
16:29:00,057 DEBUG [VRaptor             ] VRaptor ended the request

Preciso fazer mais alguma configuração?

Obrigado!

Desculpe, falha minha. Era um erro no controller.
Está tudo certo agora!

Obrigado Lucas!

[quote=bglbruno]Tem razão Lucas, vi a implementação padrão.
Vou implementar aqui e depois posto como fiz.

Valeu! Abração![/quote]

Bruno, voce teria condições de postar a solução de seu problema? estou com o mesmo desafio!

Grato,

Jorel

Eu consegui resolver o problema da seguinte forma.

Meu sistema esta distribuído em pacotes.
Ex:
br.com.exemplo.modulo
br.com.exemplo.modulo2
e assim por diante, queria identificar automaticamente o modulo de acordo o pacote então consegui através da seguinte.

[code]package br.com.exemplo.modulo.http;

import br.com.caelum.vraptor.http.FormatResolver;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.view.DefaultPathResolver;

@Component
public class ModuloPathResolver extends DefaultPathResolver {

private FormatResolver resolver;

public ModuloPathResolver(FormatResolver resolver) {
	super(resolver);
	this.resolver = resolver;
}

@Override
public String pathFor(ResourceMethod method) {
	String format = resolver.getAcceptFormat();

	String suffix = "";
	if (format != null && !format.equals("html")) {
		suffix = "." + format;
	}
	String name = method.getResource().getType().getSimpleName();
	String folderName = extractControllerFromName(name);
	
    // Mágica acontece aqui, onde é identificado o pacote da classe onde será processada a requisição
	String pacote = method.getResource().getType().getPackage().getName();
	String modulo = getModulo( pacote );
	
	return getPrefix() + modulo + "/" + folderName + "/" + method.getMethod().getName()
			+ suffix + "." + getExtension();
}

/**
 * Identifica o modulo de acordo com o 
 * pacote que esta inserida o Controller que processará a requisição.
 * 
 * @param String pacote
 * @return String
 */
private String getModulo(String pacote) {
	String[] pacotes = pacote.split("\\.");
	return pacotes[3];
}

}[/code]

Espero que minha solução tenha ajudado.

mr Lucas, sera que da forma que eu fiz ta muito primata?

[code]@Component
public class JspPathResolver
implements PathResolver {

@Override  
public String pathFor(ResourceMethod method) {  
	final Class<?> clazz = method.getResource().getType();  
    final String clazzName = clazz.getSimpleName();  
    final Package pkg = clazz.getPackage();
    String modulo[] = pkg.getName().split("\\.");
    
    final StringBuilder s = new StringBuilder();  
    s.append("/WEB-INF/jsp/");  
    
    s.append(modulo[4]);
    s.append("/");  
    s.append(StringUtils.substringBefore(clazzName, "Controller").toLowerCase());
    s.append("/");
    s.append(method.getMethod().getName().toLowerCase());
    s.append(".jsp");  

    return s.toString(); 
}  

}[/code]

eu só usaria ao invés do stringBuilder:

return String.format("/WEB-INF/jsp/%s/%s/%s.jsp", modulo[4], controller, method);

mmmm como voce pega o controller?
tentei assim mas acho que nao é isso:

@Component  
public class JspPathResolver  
    implements PathResolver {  
	
	@Override  
    public String pathFor(ResourceMethod method) {  
    	final Class<?> clazz = method.getResource().getType();  
        final String clazzName = clazz.getSimpleName();  
        final Package pkg = clazz.getPackage();
        String modulo[] = pkg.getName().split("\\.");
        String controller = StringUtils.substringBefore(clazzName, "Controller").toLowerCase();
        
        return String.format("/WEB-INF/jsp/%s/%s/%s.jsp", modulo[4], controller, method);  
    }  
}  

é quase isso… só olhar a implementação padrão :wink:

hehe… assim funcionou mestre Lucas:

@Component  
public class JspPathResolver  
    implements PathResolver {  
	
	@Override  
    public String pathFor(ResourceMethod method) {  
    	final Class<?> clazz = method.getResource().getType();  
        final String clazzName = clazz.getSimpleName();  
        final Package pkg = clazz.getPackage();
        
        String modulo[] = pkg.getName().split("\\.");
        String controller = StringUtils.substringBefore(clazzName, "Controller").toLowerCase();
        String metodo = method.getMethod().getName().toLowerCase();
        String recurso = String.format("/WEB-INF/jsp/%s/%s/%s.jsp", modulo[4], controller, metodo);
        
        return recurso;
    }  
}

era isso mesmo?
obrigado e um abraço!