VRaptor3 - Recuperar lista de todos os recursos

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

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:

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

??

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.

oi garcia!

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

abracos

[quote=Paulo Silveira]oi garcia!

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

abracos[/quote]

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

[quote=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:[/quote]

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

[quote=garcia-jj][quote=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:[/quote]

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[/quote]

é 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

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

=)

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

funcionou perfect… sem a anotação do sping

só mudei pra set =D

[code]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<Class><?>> resources = new HashSet<Class><?>>();

  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);
  }

}[/code]

Perfeito! =)

quer fazer um cookbook sobre isso? :wink:

faz estilo o artigo que vc fez no seu blog

[]'s

[quote=lucascs]Perfeito! =)

quer fazer um cookbook sobre isso? :wink:

faz estilo o artigo que vc fez no seu blog

[]'s[/quote]

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:

[code]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();
    [...]
}

}[/code]

:oops:

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

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…

meu componente para recursos…

[code]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<Class><?>> ORDENADOR_CLASS = new Comparator<Class><?>>() {
      @Override
      public int compare(Class<?> o1, Class<?> 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<Method> ORDENADOR_METHOD = new Comparator<Method>() {
      @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<Class><?>,Set<Method>> resourcesMap = new TreeMap<Class><?>,Set<Method>>(ORDENADOR_CLASS);

    @Override
    public Class<? extends Annotation> stereotype() {
    return Resource.class;
    }
    @Override
    public void handle(Class<?> resource) {
    Set<Method> logicas = new TreeSet<Method>(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<Class><?>> getResources() {
      return Collections.unmodifiableSet(resourcesMap.keySet());
      }

    /**

    • Recupera um {@link Set} somente leitura em ordem alfabetica das lógicas do recurso passado.

    • Caso não encontre o recuso uma lista vazia será retornada.
    • @param resource
    • @return
      */
      public Set<Method> getLogics(Class<?> 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<Class><?>,Set<Method>> getResourcesMap() {
      return Collections.unmodifiableMap(resourcesMap);
      }

    /**

    • Verifica se a classe enviada é de um recurso do aplicativo.
      */
      public boolean contains(Class<?> 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);
      }
      }[/code]

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

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