0
votes

I added QuartzFramework in a strut2 web-app by using a Servlet that implements ServletContextListener. In the servlet using quartz properties i created a instance of Quartz with name say "AsyncJobsQuartz" and started it using scheduler.start().

Scheduled JObs using JobStore, therefore daily at the scheduled time, jobs are executed. But the problem is when a job is under execution, i cannot use the scheduler instance else where. i.e, in other action i am trying to get the instance by using

scheduler = schedulerFactory.getScheduler("ASYNC_JOBS_SCHEDULER");

But iam getting scheduler as null and later scheduler.getJobGroupNames() is Null pointer Exception. But as soon as the job ends, the scheduler is back, with all details.

I am in confusion, that whether i missed some settings or is there a bug with Quartz. Please provide me a solution for this.

The class (servlet) that instantiates and start the scheduler. I am not using quartz.properties file because as per instructions i am not supposed to specify the db credentials in more than once i.e, in hibernate.cfg.xml and then in quartz.properties.

package com.generalsentiment.test.quartz;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.lang.reflect.Field;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.common.collect.Maps;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.ConfigurationException;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.hibernate.SessionFactory;
import org.hibernate.impl.SessionFactoryImpl;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerMetaData;
import org.quartz.impl.matchers.GroupMatcher;

import com.generalsentiment.util.HibernateUtil;
import com.generalsentiment.util.quartz.SchedulerConstants;
import com.generalsentiment.util.quartz.QuartzSchedulerUtil;
import org.apache.commons.configuration.*;

public class QuartzServlet implements ServletContextListener {

    private Map<String, String> existingJobsList;
    private String hibernateConnectionUrl;
    private SessionFactory sessionFactory;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            Properties properties = new Properties();
            Field f = SessionFactoryImpl.class.getDeclaredField("properties");
            f.setAccessible(true);
            sessionFactory = HibernateUtil.getSessionFactory();

            Properties p = (Properties) f.get(sessionFactory);
            properties.setProperty("org.quartz.scheduler.instanceName", SchedulerConstants.SCHEDULER_INSTANCE_NAME);
            properties.setProperty("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
            properties.setProperty("org.quartz.threadPool.threadCount", "4");
            properties.setProperty("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");

            properties.setProperty("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreCMT");
            properties.setProperty("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
            properties.setProperty("org.quartz.jobStore.useProperties", "false");
            properties.setProperty("org.quartz.jobStore.dataSource", "tasksDataStoreContainer");
            properties.setProperty("org.quartz.jobStore.nonManagedTXDataSource", "tasksDataStoreQuartz");
            properties.setProperty("org.quartz.jobStore.tablePrefix", "QRTZ_");
            properties.setProperty("org.quartz.jobStore.misfireThreshold", "60000");
            properties.setProperty("org.quartz.jobStore.isClustered", "false");

            properties.setProperty("org.quartz.dataSource.tasksDataStoreContainer.driver", p.getProperty("hibernate.connection.driver_class"));
            properties.setProperty("org.quartz.dataSource.tasksDataStoreContainer.URL", p.getProperty("hibernate.connection.url"));
            properties.setProperty("org.quartz.dataSource.tasksDataStoreContainer.user", p.getProperty("hibernate.connection.username"));
            properties.setProperty("org.quartz.dataSource.tasksDataStoreContainer.password", p.getProperty("hibernate.connection.password"));
            properties.setProperty("org.quartz.dataSource.tasksDataStoreContainer.maxConnections", "20");

            properties.setProperty("org.quartz.dataSource.tasksDataStoreQuartz.driver", p.getProperty("hibernate.connection.driver_class"));
            properties.setProperty("org.quartz.dataSource.tasksDataStoreQuartz.URL", p.getProperty("hibernate.connection.url"));
            properties.setProperty("org.quartz.dataSource.tasksDataStoreQuartz.user", p.getProperty("hibernate.connection.username"));
            properties.setProperty("org.quartz.dataSource.tasksDataStoreQuartz.password", p.getProperty("hibernate.connection.password"));
            properties.setProperty("org.quartz.dataSource.tasksDataStoreQuartz.maxConnections", "20");
            hibernateConnectionUrl = p.getProperty("hibernate.connection.url");


            System.out.println("THE APPLICATION STARTED");

            // First we must get a reference to a scheduler
            existingJobsList = Maps.newHashMap();
            Scheduler scheduler = QuartzSchedulerUtil.initiateSchedulerFactory(properties);
            System.out.println("------- Initialization Complete --------");
            System.out.println("------- Scheduling Jobs ----------------");

            System.out.println("------- Starting Scheduler ----------------");
            List<String> jobGroupNames = scheduler.getJobGroupNames();
            for (String current : jobGroupNames) {
                for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.<JobKey>groupEquals(current))) {
                    existingJobsList.put(jobKey.getName(), jobKey.getGroup());
                }
            }

            if (!existingJobsList.containsKey("ExportOrgUsersToFileJob")) {

                JobDetail job = newJob(ExportOrgUsersToFileJob.class).withIdentity("ExportOrgUsersToFileJob",
                        SchedulerConstants.JOBS_GROUP).build();

                CronTrigger trigger = newTrigger().withIdentity("trigger@morning",
                        SchedulerConstants.TRIGGER_MORNING_GROUP).withSchedule(cronSchedule("00 10 15 * * ?")).build();
                job.getJobDataMap().put("jobDescription", "Exports a particular Organization users to file");
                job.getJobDataMap().put("jobStatus", SchedulerConstants.JOB_STATUS.PENDING);
                Date ft = scheduler.scheduleJob(job, trigger);
            }

            if (!existingJobsList.containsKey("DownloadScoresJob")) {
                JobDetail job1 = newJob(DownloadScoresJob.class).withIdentity("DownloadScoresJob",
                        SchedulerConstants.JOBS_GROUP).build();

                CronTrigger trigger1 = newTrigger().withIdentity("trigger@evening",
                        SchedulerConstants.TRIGGER_EVENING_GROUP).withSchedule(cronSchedule("00 15 15 * * ?")).build();

                job1.getJobDataMap().put("jobDescription", "Downloads involvement index scores for given synsets");
                job1.getJobDataMap().put("jobStatus", SchedulerConstants.JOB_STATUS.PENDING);
                Date ft1 = scheduler.scheduleJob(job1, trigger1);
            }
            //            JobListener jobListener = new QuartzJobListener();
            //            scheduler.getListenerManager().addJobListener(jobListener, allJobs());

            scheduler.start();

            System.out.println("------- Started Scheduler -----------------");

            SchedulerMetaData metaData = scheduler.getMetaData();
            System.out.println("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
        } catch (IllegalAccessException ex) {
            Logger.getLogger(QuartzServlet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchFieldException ex) {
            Logger.getLogger(QuartzServlet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(QuartzServlet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SchedulerException se) {
            System.out.println(se);
        } catch (ConfigurationException ex) {
            Logger.getLogger(QuartzServlet.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        try {
            Scheduler scheduler = QuartzSchedulerUtil.getCurrentScheduler();
            if (scheduler != null) {
                //to avoid NPE
                scheduler.shutdown(true);
            }
            Thread.sleep(1000);
            Driver mySqlDriver = DriverManager.getDriver(hibernateConnectionUrl);
            DriverManager.deregisterDriver(mySqlDriver);
            sessionFactory.close();
        } catch (SchedulerException ex) {
            Logger.getLogger(QuartzServlet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InterruptedException ex) {
            Logger.getLogger(QuartzServlet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException ex) {
            Logger.getLogger(QuartzServlet.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("THE QUARTZ APPLICATION STOPPED");
    }

    public String getHibernateConnectionUrl() {
        return hibernateConnectionUrl;
    }

    public void setHibernateConnectionUrl(String hibernateConnectionUrl) {
        this.hibernateConnectionUrl = hibernateConnectionUrl;
    }
}
1
can you show your quartz.properties file? scheduler needs thread in order to execute multiple jobs and you need to tell Quartz how many threads you wants in pool to be ready to serve. - Umesh Awasthi
added code in the question post. - Sangram Anand

1 Answers

1
votes

I'm using Quartz v1.8.4 and Struts2 (not that I believe that matters particularly here). To access the Scheduler in one of my actions I had to use the following.

    public Scheduler getScheduler() throws SchedulerException {
    ServletContext context = this.getServletRequest().getSession().getServletContext();
    SchedulerFactory factory = (StdSchedulerFactory) context.getAttribute("org.quartz.impl.StdSchedulerFactory.KEY");
    return factory.getScheduler();
}

The Quartz jars I have in my project are quartz-1.8.4.jar and quartz-oracle-1.8.4.jar.

I initialize Quartz using the servlet they provide, which I simply define in web.xml:

<servlet> 
  <servlet-name>QuartzInitializer</servlet-name> 
  <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class> 
  <init-param>
    <param-name>shutdown-on-unload</param-name>
    <param-value>true</param-value>
  </init-param>
  <load-on-startup>2</load-on-startup>
</servlet>