VRaptor3 - Recuperar lista de todos os recursos

17 respostas
Lavieri

é possivel resgatar a lista de todos os recursos ?? das suas classes para ser mais especifico ?

17 Respostas

Lucas_Cavalcanti

Dá pra você usar uma certa trapaça pra fazer isso:

se você receber uma Lista de um determinado tipo, o container vai injetar todos os objetos compativeis com esse tipo…

por exemplo:

public MinhaClasse(List converters)

vai injetar todos os converters registrados…

se você quiser todos os objetos registrados no container é só receber uma List no construtor de alguma classe…

se você quiser criar uma lista de todos as classes anotadas com @Resource é um pouco mais complicado… mas dá pra fazer.
pergunte-me como :wink:

Lavieri

Bla(List<Object> objetos ) { Set<Class<?>> componentes = new HashSet<Class<?>>(); for(Object o : objetos) { if (o.getClass().isAnnotationPresent(Resource)) componentes.add(o.getClass()); } }

??

G

Alguns duas atrás postei sobre isso: http://www.guj.com.br/posts/list/140708.java

Não tive tempo ainda de ver sobre isso, mas estava pensando em criar uma classe estilo o que tinha no vraptor2.6.

Paulo_Silveira

oi garcia!

se fizer a classe e testes a gente agradece :), e comitamos no projeto!

abracos

Lavieri

Paulo Silveira:
oi garcia!

se fizer a classe e testes a gente agradece :), e comitamos no projeto!

abracos

segundo o lucas a possibilidade de fazer isso com os StereotypeHandler chguei a dar um olhada… parece que quando o server levanta ele usa esses handlers para tipo regitstrar…

vi que todos os recursos são enviados para os routers… mas que ele não faz um bag com a lista dos recursos…

depois vou ver c vejo como faz isso

G

lucascs:
se você quiser criar uma lista de todos as classes anotadas com @Resource é um pouco mais complicado… mas dá pra fazer.
pergunte-me como :wink:

Como? (parece aqueles comerciais de Herbalife, heheheheh.

Até então pensei em uma gambiarra: clazz.getName().contains(“Controller”). Injetando no construtor List traz mesmo todo mundo, basta fazer clazz.isAnnotationPresent(Resource.class)

evil, hahahahah

Lavieri

garcia-jj:
lucascs:
se você quiser criar uma lista de todos as classes anotadas com @Resource é um pouco mais complicado… mas dá pra fazer.
pergunte-me como :wink:

Como? (parece aqueles comerciais de Herbalife, heheheheh.

Até então pensei em uma gambiarra: clazz.getName().contains(“Controller”). Injetando no construtor List traz mesmo todo mundo, basta fazer clazz.isAnnotationPresent(Resource.class)

evil, hahahahah

é mas é feio de + … porem nem todo controle tem o Controller no nome, e nem tudo com Controller no nome é realmente um @Resource

melhor procurar pela anotação

Lucas_Cavalcanti

O que vocês têm que fazer é o seguinte:

@Component
@ApplicationScoped //importante
public class Resources implements StereotypeHandler {
      private List<Class<?>> resources = new ArrayList<>();
      
      public Class<? extends Annotation> stereotype() {
              return Resource.class
      }
 
      public void handle(Class<?> type) {
             resources.add(type);
      }

      public List<Class<?>> allResources() {
            return Collections.unmodifiableList(resources);
      }
}

e é só receber essa classe no construtor do componente que você quiser saber

não testei isso, mas deve funcionar, pelo menos no Spring

=)

Lavieri

não tem que ter essa anotação ? na classe ?

@org.springframework.stereotype.Component(“stereotypeHandler”)

só uma duvida, pq vi em uma la, vou fazer uns testes aqui

Lavieri

funcionou perfect... sem a anotação do sping

só mudei pra set =D

import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.StereotypeHandler;

@Component
@ApplicationScoped
public class ResourcesHandler implements StereotypeHandler {
      private Set&lt;Class&gt;&lt;?&gt;&gt; resources = new HashSet&lt;Class&gt;&lt;?&gt;&gt;();
      
      public Class&lt;? extends Annotation&gt; stereotype() {
              return Resource.class;
      }
 
      public void handle(Class&lt;?&gt; type) {
             resources.add(type);
      }

      public Set&lt;Class&gt;&lt;?&gt;&gt; allResources() {
            return Collections.unmodifiableSet(resources);
      }
}
Lucas_Cavalcanti

Perfeito! =)

quer fazer um cookbook sobre isso? :wink:

faz estilo o artigo que vc fez no seu blog

[]'s

G
lucascs:
Perfeito! =)

quer fazer um cookbook sobre isso? ;)

faz estilo o artigo que vc fez no seu blog

[]'s

Lucas, ainda hoje mandei uma MP para o Paulo Silveira perguntando se isso pode ficar como cookbook ou então fazer um componente bem genérico que disponibilize dados na view e deixe no core do vraptor. Assim se eu quiser fazer um controller com as stats bastaria:

public class MyXPTOStatsController {
    private final StatsResource stats;

    public MyXPTOStatsController(StatsResource stats) {
        this.stats = stats;
    }

    public void stats() {
        stats.listResources();
        stats.listInterceptos();
        stats.listFoo();
        stats.listBar();
        [...]
    }
}

:oops:

Lavieri

posso montar o cook =D … mas a clase quem fez foi vc =P … eu ate tinha visto como era, mas não sabia que era so implementar a interface que já seria usado como handler…

vou montar um cook la no blog

Lucas_Cavalcanti

Converters => receber List
Interceptors => receber List
Resources => modificar um pouco o ResourceHandler pra guardar a lista de resources
Components => modificar um pouco o ComponentHandler pra guardar a lista de componentes

não sei se precisa de um componente pra guardar isso tudo…

Lavieri

meu componente para recursos...

package br.com.tomazlavieri.vraptor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.StereotypeHandler;

/**
 * Guarda um map de recursos e logicas deste aplicativo web.
 * @author Tomaz Lavieri
 * @since 1.0
 */
@Component
@ApplicationScoped
public class ResourcesCollection implements StereotypeHandler {
	/**
	 * Ordena as classes por ordem alfabetica do {@link Class#getSimpleName()} ou pelo
	 * nome do pacote, caso tenham o mesmo simple name.
	 */
	private static final Comparator&lt;Class&gt;&lt;?&gt;&gt; ORDENADOR_CLASS = new Comparator&lt;Class&gt;&lt;?&gt;&gt;() {
		@Override
		public int compare(Class&lt;?&gt; o1, Class&lt;?&gt; o2) {
			int result = o1.getSimpleName().compareTo(o2.getSimpleName());
			return result != 0 ? result : o1.getName().compareTo(o2.getName());
		}
	};
	/**
	 * ordena os métodos por ordem alfabetica, ou pela quantidade de argumentos ou, caso a ordem
	 * persista, comparando seus argumentos um a um.
	 */
	private static final Comparator&lt;Method&gt; ORDENADOR_METHOD = new Comparator&lt;Method&gt;() {
		@Override
		public int compare(Method o1, Method o2) {
			if (o1.equals(o2))
				return 0;
			int result = o1.getName().compareTo(o2.getName());
			if (result != 0)
				return result;
			
			Class&lt;?&gt;[] param1 = o1.getParameterTypes();
			Class&lt;?&gt;[] param2 = o2.getParameterTypes();
			
			result = param1.length - param2.length;
			if (result != 0)
				return result;
			
			for(int i = 0; i &lt; param1.length; i++) {
				result = ORDENADOR_CLASS.compare(param1[i], param2[i]);
				if (result != 0)
					return result;
			}
			return result;
		}
	};
	
	private Map&lt;Class&gt;&lt;?&gt;,Set&lt;Method&gt;&gt; resourcesMap = new TreeMap&lt;Class&gt;&lt;?&gt;,Set&lt;Method&gt;&gt;(ORDENADOR_CLASS);

	@Override
	public Class&lt;? extends Annotation&gt; stereotype() {
		return Resource.class;
	}
	@Override
	public void handle(Class&lt;?&gt; resource) {
		Set&lt;Method&gt; logicas = new TreeSet&lt;Method&gt;(ORDENADOR_METHOD);
		for (Method method : resource.getMethods())
			if (method.getDeclaringClass().equals(resource)) {
				logicas.add(method);
			}
		resourcesMap.put(resource, logicas);
	}
	
	/**
	 * Recupera um {@link Set} somente leitura em ordem alfabetica dos recursos do aplicativo.
	 */
	public Set&lt;Class&gt;&lt;?&gt;&gt; getResources() {
		return Collections.unmodifiableSet(resourcesMap.keySet());
	}
	
	/**
	 * Recupera um {@link Set} somente leitura em ordem alfabetica das lógicas do recurso passado.
	 * <br>
	 * Caso não encontre o recuso uma lista vazia será retornada.
	 * @param resource 
	 * @return
	 */
	public Set&lt;Method&gt; getLogics(Class&lt;?&gt; resource) {
		if (resourcesMap.containsKey(resource))
			return Collections.unmodifiableSet(resourcesMap.get(resource));
		else
			return Collections.emptySet();
	}
	
	/**
	 * Recupera um {@link Map} ordenado com os recursos de chave e a lista de logicas como valores.
	 */
	public Map&lt;Class&gt;&lt;?&gt;,Set&lt;Method&gt;&gt; getResourcesMap() {
		return Collections.unmodifiableMap(resourcesMap);
	}
	
	/**
	 * Verifica se a classe enviada é de um recurso do aplicativo.
	 */
	public boolean contains(Class&lt;?&gt; resource) {
		return resourcesMap.containsKey(resource);
	}
	
	/**
	 * Verifica se o metodo enviado é de uma lógica do aplicativo.
	 */
	public boolean contains(Method logic) {
		return resourcesMap.containsValue(logic);
	}
}
Lucas_Cavalcanti

troque o resource.getMethods() por resource.getDeclaredMethods()… ele retorna os métodos declarados (não os herdados)
da classe

Lavieri

porem não retorna apenas os publicos, implicando em outro if, para publicos.

Criado 18 de outubro de 2009
Ultima resposta 19 de out. de 2009
Respostas 17
Participantes 4