Como trabalhar com componentes e Jobs no Vraptor com TaskScheduler Spring

Caros, boa tarde.

Em minha aplicação necessito de alguns jobs com scopo de aplicação. E como se sabe não conseguimos injetar os componentes de request nesses jobs de application. Enfim, preciso de vários Daos e outros componentes nesses jobs.

O que devo fazer para utilizar estes componentes em meus jobs? Devo duplicar esses componentes para application scoped? Ou seja duplicar vários daos, sessionfactorys e etc, para poder trabalhar com eles dentro do job? Ou existe outra maneira de fazer isso de forma “correta”?

[]'s
Leonardo

o problema é que os jobs executam fora de requisições, então vc não pode usar nenhum componente de request ou session…

um dos jeitos de resolver o problema é criar controllers que executam as lógicas e os jobs chamarem urls desses controllers… daí vc faz de um jeito que esses controllers só possam ser chamados desses jobs.

[quote=Lucas Cavalcanti]o problema é que os jobs executam fora de requisições, então vc não pode usar nenhum componente de request ou session…

um dos jeitos de resolver o problema é criar controllers que executam as lógicas e os jobs chamarem urls desses controllers… daí vc faz de um jeito que esses controllers só possam ser chamados desses jobs.[/quote]

Entendi lucas, obrigado pela dica. Uma dúvida: É possível resgatar, apartir desse job, informações de dominio, contexto e etc? Para não ficar hardcode a chamada da URL, de forma a ficar mais dinâmico. Tentei injetar o HttpServletRequest e também não foi possível.

Mas a dica já resolveu o problema… valew!

injete o ServletContext, assim vc consegue qual é o context-path…

e como vc tá no servidor vc pode chamar por localhost:8080 :wink:

[quote=Lucas Cavalcanti]injete o ServletContext, assim vc consegue qual é o context-path…

e como vc tá no servidor vc pode chamar por localhost:8080 ;)[/quote]

Opa funcionou perfeitamente! Thanks!

leoloko esse projeto pode ajudar

https://github.com/wpivotto/vraptor-tasks

Criando algumas classes daria para fazer algo desse tipo:


@Scheduled(fixedRate = 5000)
public class MyTask implements Task {

     private final TaskRequest request;  //ou TaskResult, RequestExecutor...

     public MyTask(TaskRequest request){
          this.request = request;
     }

     public void execute(){
          request.access(Controller.class).method(); //ou request.invoke(Controller.class), request.at(Controller.class) ... 
          //TaskRequest recuperaria a URI do Router e faria a requisição. Assim a chamada ficaria refactor friendly
     }

}

[quote=wpivotto]leoloko esse projeto pode ajudar

https://github.com/wpivotto/vraptor-tasks

Criando algumas classes daria para fazer algo desse tipo:

[code]

@Scheduled(fixedRate = 5000)
public class MyTask implements Task {

 private final TaskRequest request;  //ou TaskResult, RequestExecutor...

 public MyTask(TaskRequest request){
      this.request = request;
 }

 public void execute(){
      request.access(Controller.class).method(); //ou request.invoke(Controller.class), request.at(Controller.class) ... 
      //TaskRequest recuperaria a URI do Router e faria a requisição. Assim a chamada ficaria refactor friendly
 }

}
[/code][/quote]

Parece legal este método, utilizando essa forma, como restringiria no controller a chamada somente apartir dessa task?

[quote=leoloko][quote=wpivotto]leoloko esse projeto pode ajudar

https://github.com/wpivotto/vraptor-tasks

Criando algumas classes daria para fazer algo desse tipo:

[code]

@Scheduled(fixedRate = 5000)
public class MyTask implements Task {

 private final TaskRequest request;  //ou TaskResult, RequestExecutor...

 public MyTask(TaskRequest request){
      this.request = request;
 }

 public void execute(){
      request.access(Controller.class).method(); //ou request.invoke(Controller.class), request.at(Controller.class) ... 
      //TaskRequest recuperaria a URI do Router e faria a requisição. Assim a chamada ficaria refactor friendly
 }

}
[/code][/quote]

Parece legal este método, utilizando essa forma, como restringiria no controller a chamada somente apartir dessa task?[/quote]

Então, uma maneira de fazer isso é assim: https://gist.github.com/1312993

Utilizando um interceptor que bloqueia qualquer requisição fora do servidor (127.0.0.1)

Show de bola, essa eu já implementei, mas o esquema do vraptor com o quartz ainda não, mas em breve farei.

Agora uma outra questão, implementei dois jobs aqui, ambos rodam de 1 em 1 minuto, porém um dos jobs demora 5 minutos pra executar, enquanto o mais demorado está executando o outro não roda ele fica esperando o de 5 terminar. Alguém saberia me dizer porque isso está ocorrendo? Pois pra mim esses jobs eram multi-thread, não deveriam possuir nenhum tipo de dependência, ou seja, se um dos jobs demorar 30 minutos pra rodar, o outro deveria continuar rodando de 1 em 1 minuto em paralelo, pelo menos esse é o meu conceito… hehehe

[]'s
Leonardo

[quote=wpivotto]leoloko esse projeto pode ajudar

https://github.com/wpivotto/vraptor-tasks

Criando algumas classes daria para fazer algo desse tipo:

[code]

@Scheduled(fixedRate = 5000)
public class MyTask implements Task {

 private final TaskRequest request;  //ou TaskResult, RequestExecutor...

 public MyTask(TaskRequest request){
      this.request = request;
 }

 public void execute(){
      request.access(Controller.class).method(); //ou request.invoke(Controller.class), request.at(Controller.class) ... 
      //TaskRequest recuperaria a URI do Router e faria a requisição. Assim a chamada ficaria refactor friendly
 }

}
[/code][/quote]

Estou precisando criar uma classe para rodar em background num sistema que estou implementando. Quais classes devo criar para poder utilizar esse Task e por que o VRaptor não reconhece a interface Task aqui? É preciso configurar o Spring para utilizar essa anotação @Scheduled?

isso é um plugin do VRaptor:

[quote=wpivotto]leoloko esse projeto pode ajudar

https://github.com/wpivotto/vraptor-tasks

Criando algumas classes daria para fazer algo desse tipo:

[code]

@Scheduled(fixedRate = 5000)
public class MyTask implements Task {

 private final TaskRequest request;  //ou TaskResult, RequestExecutor...

 public MyTask(TaskRequest request){
      this.request = request;
 }

 public void execute(){
      request.access(Controller.class).method(); //ou request.invoke(Controller.class), request.at(Controller.class) ... 
      //TaskRequest recuperaria a URI do Router e faria a requisição. Assim a chamada ficaria refactor friendly
 }

}
[/code][/quote]

Boa tarde,

tendo em conta que estou a usar o plugin acima, há alguma forma de definir o intervalo de tempo de execução de forma manual?

O Objectivo é ir buscar esta informação a um DAO, permitindo assim ter o intervalo de execução da task parametrizavel.

Já estive a dar uma vista de olhos nas classes TaskHandler ( que verifica se a annotation existe ) e na TriggerBuilder que é usada pelo Handler. Contudo nao queria reescrever todo o código já feito pelo plugin, até pq o mais provavel é perder funcionalidades.

Alguma sugestão? :slight_smile:
Obrigado!

edit: a annotation que refiro é a @Scheduled

o plugin existe pra facilitar o uso, mas vc sempre pode apelar para a API do Quartz, que deixa vc fazer o que precisar.

Boas,
deixo a forma como resolvi o problema usando o vraptor-tasks, caso alguem procure aquilo q eu procurava…

@ApplicationScoped
@Scheduled(fixedRate = 1000 * 60 * 60 * 24, concurrent = false) //ms s m horas
public class EntitySyncTask implements Task{
//Os dao terão de ser prototypeScope
public EntitySyncTask(ProtoEntidadesDAO entidadesDao, TaskScheduler scheduler) {
        this.entidadesDao = entidadesDao;
        this.scheduler = scheduler;    
    }
    public void execute() {
          for (MosSincronizacao sincronizacao : entidadesDao.getAllSinc()) {
                scheduler.schedule(GenericSyncTask.class, customTrigger("teste", sincronizacao.getPeriodicidadeMs() ),                "GenericSyncTask");
    }
    private SimpleTrigger customTrigger(String triggerName, long repeatRate) {
        //simpleSchedule() nao funciona...
        return newTrigger().withIdentity(UUID.randomUUID().toString())
        .startNow()
        .withSchedule(repeatSecondlyForever().withIntervalInMilliseconds(repeatRate))            
        .build();
    }

Depois basta criarem a outra Task. Reparei tambem que ,nesta versão que estou a usar 1.0.3 do vraptor-taks, a anotação Scheduled terá de estar presenta em Tasks que não tenham um construtor por omissão. O workaround que usei foi colocar o tal @Scheduled e dar 1 id diferente. Contudo pode nao ser um issue geral visto que eu recompilei o plugin com java 1.5 visto ser requisito do meu proj.

Cumps