edu.usu.sdl.openstorefront.service.manager.JobManager.java Source code

Java tutorial

Introduction

Here is the source code for edu.usu.sdl.openstorefront.service.manager.JobManager.java

Source

/*
 * Copyright 2014 Space Dynamics Laboratory - Utah State University Research Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.usu.sdl.openstorefront.service.manager;

import edu.usu.sdl.openstorefront.common.exception.OpenStorefrontRuntimeException;
import edu.usu.sdl.openstorefront.common.manager.FileSystemManager;
import edu.usu.sdl.openstorefront.common.manager.Initializable;
import edu.usu.sdl.openstorefront.core.entity.ComponentIntegration;
import edu.usu.sdl.openstorefront.service.ServiceProxy;
import edu.usu.sdl.openstorefront.service.io.ArticleImporter;
import edu.usu.sdl.openstorefront.service.io.AttributeImporter;
import edu.usu.sdl.openstorefront.service.io.ComponentImporter;
import edu.usu.sdl.openstorefront.service.io.HighlightImporter;
import edu.usu.sdl.openstorefront.service.io.LookupImporter;
import edu.usu.sdl.openstorefront.service.job.BaseJob;
import edu.usu.sdl.openstorefront.service.job.ComponentUpdateJob;
import edu.usu.sdl.openstorefront.service.job.IntegrationJob;
import edu.usu.sdl.openstorefront.service.job.NotificationJob;
import edu.usu.sdl.openstorefront.service.job.RecentChangeNotifyJob;
import edu.usu.sdl.openstorefront.service.job.ScheduledReportJob;
import edu.usu.sdl.openstorefront.service.job.SystemCleanupJob;
import edu.usu.sdl.openstorefront.service.job.TrackingCleanupJob;
import edu.usu.sdl.openstorefront.service.job.UserProfileSyncJob;
import edu.usu.sdl.openstorefront.service.manager.model.AddJobModel;
import edu.usu.sdl.openstorefront.service.manager.model.JobModel;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang3.StringUtils;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import org.quartz.Trigger;
import static org.quartz.TriggerBuilder.newTrigger;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.jobs.DirectoryScanJob;
import org.quartz.jobs.DirectoryScanListener;

/**
 * Handles Automation jobs
 *
 * @author dshurtleff
 */
public class JobManager implements Initializable {

    private static final Logger log = Logger.getLogger(JobManager.class.getName());

    private static final String JOB_GROUP_SYSTEM = AddJobModel.JOB_GROUP_SYSTEM;
    private static Scheduler scheduler;

    public static void init() {
        try {
            StdSchedulerFactory factory = new StdSchedulerFactory(
                    FileSystemManager.getConfig("quartz.properties").getPath());
            scheduler = factory.getScheduler();
            initSystemJobs();
            scheduler.start();
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Failed to init quartz.", ex);
        }
    }

    private static void initSystemJobs() throws SchedulerException {
        log.log(Level.FINEST, "Setting up Import Jobs...");
        addImportJob(new LookupImporter(), FileSystemManager.IMPORT_LOOKUP_DIR);
        addImportJob(new AttributeImporter(), FileSystemManager.IMPORT_ATTRIBUTE_DIR);
        addImportJob(new ArticleImporter(), FileSystemManager.IMPORT_ARTICLE_DIR);
        addImportJob(new HighlightImporter(), FileSystemManager.IMPORT_HIGHLIGHT_DIR);
        addImportJob(new ComponentImporter(), FileSystemManager.IMPORT_COMPONENT_DIR);

        addCleanUpErrorsJob();
        addTrackingCleanUpJob();
        addNotificationJob();
        addRecentChangeNotifyJob();
        addScheduledReportJob();
        addComponentUpdate();
        addComponentIntegrationJobs();
        addUserProfileSyncjob();
    }

    private static void addComponentIntegrationJobs() throws SchedulerException {
        log.log(Level.INFO, "Adding Integration Jobs");

        ServiceProxy serviceProxy = new ServiceProxy();
        List<ComponentIntegration> integrations = serviceProxy.getComponentService()
                .getComponentIntegrationModels(ComponentIntegration.ACTIVE_STATUS);
        for (ComponentIntegration integration : integrations) {
            addComponentIntegrationJob(integration);
        }
    }

    private static void addComponentIntegrationJob(ComponentIntegration componentIntegration)
            throws SchedulerException {
        ServiceProxy serviceProxy = new ServiceProxy();
        String jobName = "ComponentJob-" + componentIntegration.getComponentId();

        JobKey jobKey = JobKey.jobKey(jobName, JOB_GROUP_SYSTEM);
        if (scheduler.checkExists(jobKey)) {
            log.log(Level.WARNING, MessageFormat.format("Job already Exist: {0} check data", jobName));
        } else {
            JobDetail job = JobBuilder.newJob(IntegrationJob.class)
                    .withIdentity("ComponentJob-" + componentIntegration.getComponentId(), JOB_GROUP_SYSTEM)
                    .withDescription("Component Integration Job for " + serviceProxy.getComponentService()
                            .getComponentName(componentIntegration.getComponentId()))
                    .build();

            job.getJobDataMap().put(IntegrationJob.COMPONENT_ID, componentIntegration.getComponentId());
            String cron = componentIntegration.getRefreshRate();
            if (cron == null) {
                cron = serviceProxy.getSystemService().getGlobalIntegrationConfig().getJiraRefreshRate();
            }
            Trigger trigger = newTrigger()
                    .withIdentity("ComponentTrigger-" + componentIntegration.getComponentId(), JOB_GROUP_SYSTEM)
                    .startNow().withSchedule(cronSchedule(cron)).build();

            scheduler.scheduleJob(job, trigger);
        }
    }

    /**
     * Add or Update job
     *
     * @param componentIntegration
     */
    public static void updateComponentIntegrationJob(ComponentIntegration componentIntegration) {
        try {
            removeComponentIntegrationJob(componentIntegration.getComponentId());
            addComponentIntegrationJob(componentIntegration);
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Unable update Job: " + componentIntegration.getComponentId(),
                    ex);
        }
    }

    public static void removeComponentIntegrationJob(String componentId) {
        JobKey jobKey = JobKey.jobKey("ComponentJob-" + componentId, JOB_GROUP_SYSTEM);
        try {
            if (scheduler.checkExists(jobKey)) {
                scheduler.deleteJob(jobKey);
            }
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Unable remove Job.", ex);
        }
    }

    public static void runComponentIntegrationNow(String componentId, String integrationConfigId) {
        JobKey jobKey = JobKey.jobKey("ComponentJob-" + componentId, JOB_GROUP_SYSTEM);
        try {
            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put(IntegrationJob.COMPONENT_ID, componentId);
            if (StringUtils.isNotBlank(integrationConfigId)) {
                jobDataMap.put(IntegrationJob.CONFIG_ID, integrationConfigId);
            }
            scheduler.triggerJob(jobKey, jobDataMap);
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Unable run Job.", ex);
        }
    }

    public static void unscheduleSystemJob(String triggerName) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, JOB_GROUP_SYSTEM);
            if (scheduler.checkExists(triggerKey)) {
                scheduler.unscheduleJob(triggerKey);
            }
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Unable unschedule Job.", ex);
        }
    }

    private static void addComponentUpdate() throws SchedulerException {
        log.log(Level.INFO, "Adding Component Update Job");

        JobDetail job = JobBuilder.newJob(ComponentUpdateJob.class)
                .withIdentity("ComponentUpdateJob", JOB_GROUP_SYSTEM)
                .withDescription("Applies component updates index and watches.").build();

        Trigger trigger = newTrigger().withIdentity("ComponentUpdateJobTrigger", JOB_GROUP_SYSTEM).startNow()
                .withSchedule(simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();

        scheduler.scheduleJob(job, trigger);
    }

    private static void addScheduledReportJob() throws SchedulerException {
        log.log(Level.INFO, "Adding Scheduled Job");

        JobDetail job = JobBuilder.newJob(ScheduledReportJob.class)
                .withIdentity("ScheduledReportJob", JOB_GROUP_SYSTEM).withDescription("Run scheduled reports")
                .build();

        Trigger trigger = newTrigger().withIdentity("ScheduledReportJobTrigger", JOB_GROUP_SYSTEM).startNow()
                .withSchedule(simpleSchedule().withIntervalInMinutes(1).repeatForever()).build();

        scheduler.scheduleJob(job, trigger);
    }

    private static void addUserProfileSyncjob() throws SchedulerException {
        log.log(Level.INFO, "Adding User Profile Sync Job");

        JobDetail job = JobBuilder.newJob(UserProfileSyncJob.class)
                .withIdentity("UserProfileSyncJob", JOB_GROUP_SYSTEM).withDescription("Run User Profile Sync")
                .build();

        Trigger trigger = newTrigger().withIdentity("SUserProfileSyncJobrigger", JOB_GROUP_SYSTEM).startNow()
                .withSchedule(simpleSchedule().withIntervalInHours(24).repeatForever()).build();

        scheduler.scheduleJob(job, trigger);
    }

    private static void addCleanUpErrorsJob() throws SchedulerException {
        log.log(Level.INFO, "Adding System Clean up Job");

        JobDetail job = JobBuilder.newJob(SystemCleanupJob.class).withIdentity("SystemCleanupJob", JOB_GROUP_SYSTEM)
                .withDescription("Removes old error tickets and db log cleanup").build();

        Trigger trigger = newTrigger().withIdentity("SystemCleanupJob", JOB_GROUP_SYSTEM).startNow()
                .withSchedule(simpleSchedule().withIntervalInMinutes(5).repeatForever()).build();

        scheduler.scheduleJob(job, trigger);
    }

    private static void addTrackingCleanUpJob() throws SchedulerException {
        log.log(Level.INFO, "Adding Tracking Cleanup Job");

        JobDetail job = JobBuilder.newJob(TrackingCleanupJob.class)
                .withIdentity("TrackingCleanupJob", JOB_GROUP_SYSTEM)
                .withDescription("Removes old tracking records").build();

        Trigger trigger = newTrigger().withIdentity("TrackingCleanupJobTrigger", JOB_GROUP_SYSTEM).startNow()
                .withSchedule(simpleSchedule().withIntervalInHours(24).repeatForever()).build();

        scheduler.scheduleJob(job, trigger);
    }

    public static void addJob(AddJobModel addjob) {
        log.log(Level.FINE, MessageFormat.format("Adding Job: {0}", addjob.getJobName()));
        try {
            JobDetail job = JobBuilder.newJob(addjob.getJobClass())
                    .withIdentity(addjob.getJobName(), addjob.getJobGroup())
                    .withDescription(addjob.getDescription()).build();

            SimpleScheduleBuilder scheduleBuilder = simpleSchedule();

            if (addjob.getHours() != null) {
                scheduleBuilder.withIntervalInHours(addjob.getHours());
            } else if (addjob.getMinutes() != null) {
                scheduleBuilder.withIntervalInMinutes(addjob.getMinutes());
            } else if (addjob.getSeconds() != null) {
                scheduleBuilder.withIntervalInSeconds(addjob.getSeconds());
            } else if (addjob.getMilliseconds() != null) {
                scheduleBuilder.withIntervalInMilliseconds(addjob.getMilliseconds());
            }

            if (addjob.isRepeatForever()) {
                scheduleBuilder.repeatForever();
            } else {
                scheduleBuilder.withRepeatCount(addjob.getRepeatCount());
            }

            Trigger trigger = newTrigger().withIdentity(addjob.getJobName() + "Trigger", addjob.getJobGroup())
                    .startNow().withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(job, trigger);
            if (addjob.isPause()) {
                scheduler.pauseTrigger(trigger.getKey());
            }
        } catch (SchedulerException se) {
            throw new OpenStorefrontRuntimeException(se);
        }
    }

    private static void addNotificationJob() throws SchedulerException {
        log.log(Level.INFO, "Adding Notification Job");

        JobDetail job = JobBuilder.newJob(NotificationJob.class).withIdentity("NotificationJob", JOB_GROUP_SYSTEM)
                .withDescription("User Message Notifications").build();

        Trigger trigger = newTrigger().withIdentity("NotificationJobTrigger", JOB_GROUP_SYSTEM).startNow()
                .withSchedule(simpleSchedule().withIntervalInMinutes(1).repeatForever()).build();

        scheduler.scheduleJob(job, trigger);
    }

    private static void addRecentChangeNotifyJob() throws SchedulerException {
        log.log(Level.INFO, "Adding Recent Change Job");

        JobDetail job = JobBuilder.newJob(RecentChangeNotifyJob.class)
                .withIdentity("RecentChangeJob", JOB_GROUP_SYSTEM).withDescription("Recent Change Notifications")
                .build();

        Trigger trigger = newTrigger().withIdentity("RecentChangeJobTrigger", JOB_GROUP_SYSTEM).startNow()
                .withSchedule(simpleSchedule().withIntervalInHours(24).repeatForever()).build();

        scheduler.scheduleJob(job, trigger);
    }

    public static void addImportJob(DirectoryScanListener directoryScanListener, String dirToWatch)
            throws SchedulerException {
        addImportJob(directoryScanListener, dirToWatch, false);
    }

    public static void addImportJob(DirectoryScanListener directoryScanListener, String dirToWatch,
            boolean activateJob) throws SchedulerException {
        String jobName = directoryScanListener.getClass().getName();
        log.log(Level.INFO,
                MessageFormat.format("Adding DIRWatch Job: {0}", directoryScanListener.getClass().getName()));

        JobDetail job = JobBuilder.newJob(DirectoryScanJob.class).withIdentity(jobName, JOB_GROUP_SYSTEM)
                .withDescription("Directory Watch Job").build();

        FileSystemManager.getDir(dirToWatch);
        job.getJobDataMap().put(DirectoryScanJob.DIRECTORY_NAME, dirToWatch);
        job.getJobDataMap().put(DirectoryScanJob.DIRECTORY_SCAN_LISTENER_NAME,
                directoryScanListener.getClass().getName());
        scheduler.getContext().put(directoryScanListener.getClass().getName(), directoryScanListener);
        Trigger trigger = newTrigger().withIdentity(jobName + "Trigger", JOB_GROUP_SYSTEM)
                .withSchedule(simpleSchedule().withIntervalInSeconds(30).repeatForever()).build();

        scheduler.scheduleJob(job, trigger);
        if (activateJob == false) {
            scheduler.pauseTrigger(trigger.getKey());
        }
    }

    public static void runJobNow(String jobName, String groupName) {
        try {
            scheduler.triggerJob(JobKey.jobKey(jobName, groupName));
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Unable to pause job", "Make sure job exists", ex);
        }
    }

    public static void pauseSystemJob(String jobName) {
        try {
            scheduler.pauseJob(JobKey.jobKey(jobName, JOB_GROUP_SYSTEM));
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Unable to pause job", "Make sure job exists", ex);
        }
    }

    public static void resumeSystemJob(String jobName) {
        try {
            scheduler.resumeJob(JobKey.jobKey(jobName, JOB_GROUP_SYSTEM));
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Unable to pause job", "Make sure job exists", ex);
        }
    }

    public static void pauseScheduler() {
        try {
            scheduler.standby();
            log.info("Job Manager in Standby");
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Unable to pause scheduler", ex);
        }
    }

    public static void resumeScheduler() {
        try {
            scheduler.start();
            log.info("Job Manager restarted");
        } catch (SchedulerException ex) {
            throw new OpenStorefrontRuntimeException("Unable to resume scheduler", ex);
        }
    }

    public static String status() {
        String status = "Running";
        try {
            if (scheduler.isInStandbyMode()) {
                status = "In Standby";
            }
        } catch (SchedulerException ex) {
            Logger.getLogger(JobManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return status;
    }

    public static List<JobModel> getAllJobs() {
        List<JobModel> jobs = new ArrayList<>();
        try {
            Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.anyGroup());
            for (JobKey jobKey : jobKeys) {
                JobModel jobModel = new JobModel();

                JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                jobModel.setJobClass(jobDetail.getJobClass().getName());
                jobModel.setJobName(jobKey.getName());
                jobModel.setGroupName(jobKey.getGroup());
                jobModel.setDescription(jobDetail.getDescription());
                jobModel.setConcurrentExectionDisallowed(jobDetail.isConcurrentExectionDisallowed());
                jobModel.setDurable(jobDetail.isDurable());
                jobModel.setPersistJobDataAfterExecution(jobDetail.isPersistJobDataAfterExecution());
                jobModel.setRequestsRecovery(jobDetail.requestsRecovery());
                StringBuilder dataMap = new StringBuilder();
                for (String dataKey : jobDetail.getJobDataMap().getKeys()) {
                    dataMap.append(dataKey).append(" : ").append(jobDetail.getJobDataMap().get(dataKey))
                            .append(" | ");
                }
                jobModel.setJobData(dataMap.toString());

                List<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);
                if (triggers.isEmpty() == false) {
                    //just grab the first trigger as we should only have one
                    Trigger trigger = triggers.get(0);
                    jobModel.setPrimaryTrigger(trigger.getKey().getName() + " - " + trigger.getKey().getGroup());
                    jobModel.setPerviousFiredTime(trigger.getPreviousFireTime());
                    jobModel.setNextFiredTime(trigger.getNextFireTime());
                    jobModel.setStatus(scheduler.getTriggerState(trigger.getKey()).toString());
                }
                jobs.add(jobModel);
            }
        } catch (SchedulerException ex) {
            Logger.getLogger(JobManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return jobs;
    }

    public static void runDynamicJob(BaseJob baseJob) {
        //TODO: Add the ability to run a temp background job
        throw new UnsupportedOperationException("Method is not supported yet");
        //      String job
        //      JobDetail job = JobBuilder.newJob(SystemCleanupJob.class)
        //            .withIdentity("DynamicJob-" + UUID.randomUUID().toString(), JOB_GROUP_SYSTEM)
        //            .build();
        //
        //      Trigger trigger = newTrigger()
        //            .withIdentity("CleanUpErrorsJobTrigger", JOB_GROUP_SYSTEM)
        //            .startNow()
        //            .withSchedule(simpleSchedule()
        //                  .withIntervalInMinutes(5)
        //                  .repeatForever())
        //            .build();
        //
        //      scheduler.scheduleJob(job, trigger);
    }

    public static void cleanup() {
        if (scheduler != null) {
            try {
                scheduler.shutdown();
            } catch (SchedulerException ex) {
                throw new OpenStorefrontRuntimeException("Failed to init quartz.", ex);
            }
        }
    }

    @Override
    public void initialize() {
        JobManager.init();
    }

    @Override
    public void shutdown() {
        JobManager.cleanup();
    }

}