Search This Blog

Wednesday, December 8, 2010

Grails : Scheduling jobs with Quartz

Had taken the time and integrated quartz with grails.
Thought I will share it.
In this post I will discuss how to Install and configure quartz with jobs persistent in a database( mysql)
Get quartz distribution.
Unzip to a directory.
Run the table-creation SQL scripts in the "docs/dbTables" directory of the Quartz distribution
2.Install quartz plugin
grails install-plugin quartz

Create a file, QuartzConfig.groovy in grails-app\conf
Specify quartz startup and storage options here like this:
quartz {
    autoStartup = true
    jdbcStore = true
    waitForJobsToCompleteOnShutdown = true
environments {
    test {
        quartz {
            autoStartup = true

Create a file, in grails-app\conf 
Configure your db name in URL as well as user name and password
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass =
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = prodDataSource
org.quartz.jobStore.isClustered = false
org.quartz.dataSource.prodDataSource.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.prodDataSource.URL = "jdbc:mysql://localhost:3306/xxx?autoreconnect=true">org.quartz.dataSource.prodDataSource.user=grails
org.quartz.dataSource.prodDataSource.password ="server"
In resources.groovy in grails-app\conf\spring
add the imports:
import org.springframework.scheduling.quartz.SchedulerFactoryBean 
import org.codehaus.groovy.grails.plugins.quartz.listeners.*
add this to spring beans dsl:
quartzScheduler(SchedulerFactoryBean) {
autoStartup = false
dataSource = ref('dataSource')
transactionManager = ref('transactionManager')
configLocation = ''
jobFactory = ref('quartzJobFactory')
jobListeners = [ref("${SessionBinderJobListener.NAME}")]
globalJobListeners = [ref("${ExceptionPrinterJobListener.NAME}")]
Create a service class(or where you would prefer to do this) with grails create-service
Enable the service class to be injeced with a scheduler by declaring like this
    def quartzScheduler
define a method which will do the scheduling for you.
In this eg I put in a domain object for later retrieval during job execution.
   def schedule(my.Motd m) {
       // execute task
    def jobDetail = new JobDetail(m?.message, group, MotdJob.class);
    jobDetail.getJobDataMap().put("job", m)
    SimpleDateFormat formatter  = new SimpleDateFormat ("yyyy.MM.dd hh:mm:ss");
    Date myDate = formatter.parse("2010.07.02 15:13:56");
    def myTrigger = new SimpleTrigger("myTrigger" + new Random().nextInt().toString(), "mygroup" + new Random().nextInt().toString(),  myDate,null,0,0)
    quartzScheduler.scheduleJob(jobDetail, myTrigger);

Create a quartz job using 
grails create-job fully-qualified-job-name
In this class define a execute method and implement your business logic
    void execute(JobExecutionContext context) {
         String instName = context.getJobDetail().getName();
         println "I have been triggered to run instGroup"
         String instGroup = context.getJobDetail().getGroup();
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        def mo =dataMap.get("job")
        if(mo) {
            Motd m = (Motd)mo
        println "null job"

If you job uses a domain class (like in example above) you need to create a jar with all the domain class used by quartz and add this to your lib directory
NOTE: This is at best a hack solution. Better option is doing this through classloader. But I wont go into it.
Thats it.
Enjoy and email me at trbala attherateof if you need an exmaple source or if you can offer me a good paying job in siliconvalley!!!

No comments:

Post a Comment