Como trabalhar com componentes e Jobs no Vraptor com TaskScheduler Spring

13 respostas
L

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

13 Respostas

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.

L

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.

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!

Lucas_Cavalcanti

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

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

L

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

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

Opa funcionou perfeitamente! Thanks!

wpivotto

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
     }

}
L
wpivotto:
leoloko esse projeto pode ajudar

[url]https://github.com/wpivotto/vraptor-tasks[/url]

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
     }

}

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

wpivotto
leoloko:
wpivotto:
leoloko esse projeto pode ajudar

[url]https://github.com/wpivotto/vraptor-tasks[/url]

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
     }

}

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

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

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

L

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

miltonjr27
wpivotto:
leoloko esse projeto pode ajudar

[url]https://github.com/wpivotto/vraptor-tasks[/url]

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
     }

}

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?

Lucas_Cavalcanti

isso é um plugin do VRaptor:

G
wpivotto:
leoloko esse projeto pode ajudar

[url]https://github.com/wpivotto/vraptor-tasks[/url]

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
     }

}

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? :)
Obrigado!

edit: a annotation que refiro é a @Scheduled

Lucas_Cavalcanti

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

G

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

Criado 19 de outubro de 2011
Ultima resposta 24 de jan. de 2014
Respostas 13
Participantes 5