Como trabalhar com componentes e Jobs no Vraptor com TaskScheduler Spring
13 respostas
L
leoloko
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”?
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
leoloko
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
L
leoloko
Lucas Cavalcanti:
injete o ServletContext, assim vc consegue qual é o context-path…
e como vc tá no servidor vc pode chamar por localhost:8080 ;)
Criando algumas classes daria para fazer algo desse tipo:
@Scheduled(fixedRate=5000)publicclassMyTaskimplementsTask{privatefinalTaskRequestrequest;//ou TaskResult, RequestExecutor...publicMyTask(TaskRequestrequest){this.request=request;}publicvoidexecute(){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}}
Criando algumas classes daria para fazer algo desse tipo:
@Scheduled(fixedRate=5000)publicclassMyTaskimplementsTask{privatefinalTaskRequestrequest;//ou TaskResult, RequestExecutor...publicMyTask(TaskRequestrequest){this.request=request;}publicvoidexecute(){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?
Criando algumas classes daria para fazer algo desse tipo:
@Scheduled(fixedRate=5000)publicclassMyTaskimplementsTask{privatefinalTaskRequestrequest;//ou TaskResult, RequestExecutor...publicMyTask(TaskRequestrequest){this.request=request;}publicvoidexecute(){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?
Utilizando um interceptor que bloqueia qualquer requisição fora do servidor (127.0.0.1)
L
leoloko
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
Criando algumas classes daria para fazer algo desse tipo:
@Scheduled(fixedRate=5000)publicclassMyTaskimplementsTask{privatefinalTaskRequestrequest;//ou TaskResult, RequestExecutor...publicMyTask(TaskRequestrequest){this.request=request;}publicvoidexecute(){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?
Criando algumas classes daria para fazer algo desse tipo:
@Scheduled(fixedRate=5000)publicclassMyTaskimplementsTask{privatefinalTaskRequestrequest;//ou TaskResult, RequestExecutor...publicMyTask(TaskRequestrequest){this.request=request;}publicvoidexecute(){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
Goncalo_PT
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 horaspublicclassEntitySyncTaskimplementsTask{//Os dao terão de ser prototypeScopepublicEntitySyncTask(ProtoEntidadesDAOentidadesDao,TaskSchedulerscheduler){this.entidadesDao=entidadesDao;this.scheduler=scheduler;}publicvoidexecute(){for(MosSincronizacaosincronizacao:entidadesDao.getAllSinc()){scheduler.schedule(GenericSyncTask.class,customTrigger("teste",sincronizacao.getPeriodicidadeMs()),"GenericSyncTask");}privateSimpleTriggercustomTrigger(StringtriggerName,longrepeatRate){//simpleSchedule() nao funciona...returnnewTrigger().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.