@Test(expected = MotechSchedulerException.class)
  public void shouldNotResumeJobIfItIsNotUiDefined() throws Exception {
    try {
      Map<String, Object> params = new HashMap<>();
      params.put(MotechSchedulerService.JOB_ID_KEY, "job_id");

      JobBasicInfo info =
          new JobBasicInfo(
              JobBasicInfo.ACTIVITY_ACTIVE,
              JobBasicInfo.STATUS_PAUSED,
              "test_event-job_id",
              "default",
              "start-time",
              "nex-fire-time",
              "end-time",
              JobBasicInfo.JOBTYPE_CRON,
              "test-info",
              false);

      schedulerService.scheduleJob(
          new CronSchedulableJob(new MotechEvent("test_event", params), "0 0 12 * * ?"));
      scheduler.pauseJob(new JobKey(info.getName(), info.getGroup()));

      assertEquals(PAUSED, scheduler.getTriggerState(triggerKey("test_event-job_id", "default")));

      schedulerService.resumeJob(info);
    } finally {
      assertEquals(PAUSED, scheduler.getTriggerState(triggerKey("test_event-job_id", "default")));
    }
  }
  @Test
  public void shouldPauseJobIfItIsUiDefined() throws Exception {
    Map<String, Object> params = new HashMap<>();
    params.put(MotechSchedulerService.JOB_ID_KEY, "job_id");

    JobBasicInfo info =
        new JobBasicInfo(
            JobBasicInfo.ACTIVITY_ACTIVE,
            JobBasicInfo.STATUS_OK,
            "test_event-job_id",
            "default",
            "start-time",
            "nex-fire-time",
            "end-time",
            JobBasicInfo.JOBTYPE_CRON,
            "test-info",
            false);

    CronSchedulableJob job =
        new CronSchedulableJob(new MotechEvent("test_event", params), "0 0 12 * * ?");
    job.setUiDefined(true);

    schedulerService.scheduleJob(job);

    assertEquals(NORMAL, scheduler.getTriggerState(triggerKey("test_event-job_id", "default")));

    schedulerService.pauseJob(info);

    assertEquals(PAUSED, scheduler.getTriggerState(triggerKey("test_event-job_id", "default")));
  }
  private void refreshUIState() {
    boolean enabled = false;
    String cronExpression = "";
    if (CoreSpringFactory.containsBean("schedulerFactoryBean")) {
      log.info("refreshUIState: schedulerFactoryBean found");
      final Object schedulerFactoryBean = CoreSpringFactory.getBean("schedulerFactoryBean");
      if (schedulerFactoryBean != null && schedulerFactoryBean instanceof Scheduler) {
        final Scheduler schedulerBean = (Scheduler) schedulerFactoryBean;
        int triggerState;
        try {
          triggerState =
              schedulerBean.getTriggerState("updateStatisticsTrigger", null /* trigger group */);
          enabled = (triggerState != Trigger.STATE_NONE) && (triggerState != Trigger.STATE_ERROR);
          log.info(
              "refreshUIState: updateStatisticsTrigger state was "
                  + triggerState
                  + ", enabled now: "
                  + enabled);
        } catch (final SchedulerException e) {
          log.warn(
              "refreshUIState: Got a SchedulerException while asking for the updateStatisticsTrigger's state",
              e);
        }
      }
      final CronTriggerBean triggerBean =
          (CronTriggerBean) CoreSpringFactory.getBean("updateStatisticsTrigger");
      final JobDetail jobDetail = triggerBean.getJobDetail();
      enabled &= jobDetail.getName().equals("statistics.job.enabled");
      log.info("refreshUIState: statistics.job.enabled check, enabled now: " + enabled);
      cronExpression = triggerBean.getCronExpression();
      final StatisticUpdateService statisticUpdateManager = getStatisticUpdateManager();
      if (statisticUpdateManager == null) {
        log.info("refreshUIState: statisticUpdateManager not configured");
        enabled = false;
      } else {
        enabled &= statisticUpdateManager.isEnabled();
        log.info("refreshUIState: statisticUpdateManager configured, enabled now: " + enabled);
      }
    } else {
      log.info("refreshUIState: schedulerFactoryBean not found");
    }
    if (enabled) {
      content.contextPut(
          "status",
          getTranslator().translate("statistics.status.enabled", new String[] {cronExpression}));
    } else {
      content.contextPut("status", getTranslator().translate("statistics.status.disabled"));
    }
    content.contextPut("statisticEnabled", enabled);

    recalcLastUpdated();

    updateStatisticUpdateOngoingFlag();
  }
  @RequestMapping("/listCurrentScheduledJobs")
  public ModelMap listScheduledJobs(HttpServletRequest request, HttpServletResponse response)
      throws SchedulerException {
    Locale locale = LocaleResolver.getLocale(request);
    ResourceBundleProvider.updateLocale(locale);
    ModelMap gridMap = new ModelMap();
    String[] triggerNames;

    boolean showMoreLink = false;
    if (request.getParameter("showMoreLink") != null) {
      showMoreLink = Boolean.parseBoolean(request.getParameter("showMoreLink").toString());
    } else {
      showMoreLink = true;
    }
    request.setAttribute("showMoreLink", showMoreLink + "");

    // request.setAttribute("studySubjectId",studySubjectId);
    /*SubjectIdSDVFactory tableFactory = new SubjectIdSDVFactory();
     * @RequestParam("studySubjectId") int studySubjectId,*/
    request.setAttribute("imagePathPrefix", "../");

    ArrayList<String> pageMessages = (ArrayList<String>) request.getAttribute("pageMessages");
    if (pageMessages == null) {
      pageMessages = new ArrayList<String>();
    }

    request.setAttribute("pageMessages", pageMessages);

    List<JobExecutionContext> listCurrentJobs = new ArrayList<JobExecutionContext>();
    listCurrentJobs = scheduler.getCurrentlyExecutingJobs();
    Iterator<JobExecutionContext> itCurrentJobs = listCurrentJobs.iterator();
    List<String> currentJobList = new ArrayList<String>();
    while (itCurrentJobs.hasNext()) {
      JobExecutionContext temp = itCurrentJobs.next();
      currentJobList.add(temp.getTrigger().getJobName() + temp.getTrigger().getGroup());
    }

    String[] triggerGroups = scheduler.getTriggerGroupNames();
    List<SimpleTrigger> simpleTriggers = new ArrayList<SimpleTrigger>();
    int index1 = 0;
    for (String triggerGroup : triggerGroups) {
      logger.debug("Group: " + triggerGroup + " contains the following triggers");
      triggerNames = scheduler.getTriggerNames(triggerGroup);

      for (String triggerName : triggerNames) {
        int state = scheduler.getTriggerState(triggerName, triggerGroup);
        logger.debug("- " + triggerName);
        if (state != Trigger.STATE_PAUSED) {
          simpleTriggers.add(
              index1, (SimpleTrigger) scheduler.getTrigger(triggerName, triggerGroup));
          index1++;
        }
      }
    }

    List<ScheduledJobs> jobsScheduled = new ArrayList<ScheduledJobs>();

    int index = 0;

    for (SimpleTrigger st : simpleTriggers) {
      boolean isExecuting = currentJobList.contains(st.getJobName() + st.getGroup());

      ScheduledJobs jobs = new ScheduledJobs();

      ExtractPropertyBean epBean = null;
      if (st.getJobDataMap() != null) {
        epBean = (ExtractPropertyBean) st.getJobDataMap().get(EP_BEAN);
      }

      if (epBean != null) {
        StringBuilder checkbox = new StringBuilder();
        checkbox.append("<input style='margin-right: 5px' type='checkbox'/>");

        StringBuilder actions = new StringBuilder("<table><tr><td>");
        if (isExecuting) {
          actions.append("&nbsp;");
        } else {
          String contextPath = request.getContextPath();
          StringBuilder jsCodeString =
              new StringBuilder("this.form.method='GET'; this.form.action='")
                  .append(contextPath)
                  .append("/pages/cancelScheduledJob")
                  .append("';")
                  .append("this.form.theJobName.value='")
                  .append(st.getJobName())
                  .append("';")
                  .append("this.form.theJobGroupName.value='")
                  .append(st.getJobGroup())
                  .append("';")
                  .append("this.form.theTriggerName.value='")
                  .append(st.getName())
                  .append("';")
                  .append("this.form.theTriggerGroupName.value='")
                  .append(st.getGroup())
                  .append("';")
                  .append("this.form.submit();");

          actions
              .append("<td><input type=\"submit\" class=\"button\" value=\"Cancel Job\" ")
              .append("name=\"cancelJob\" onclick=\"")
              .append(jsCodeString.toString())
              .append("\" />");
        }

        actions.append("</td></tr></table>");

        jobs.setCheckbox(checkbox.toString());
        jobs.setDatasetId(epBean.getDatasetName());
        String fireTime =
            st.getStartTime() != null ? longFormat(locale).format(st.getStartTime()) : "";
        jobs.setFireTime(fireTime);
        if (st.getNextFireTime() != null) {
          jobs.setScheduledFireTime(longFormat(locale).format(st.getNextFireTime()));
        }
        jobs.setExportFileName(epBean.getExportFileName()[0]);
        jobs.setAction(actions.toString());
        jobs.setJobStatus(isExecuting ? "Currently Executing" : "Scheduled");
        jobsScheduled.add(index, jobs);
        index++;
      }
    }
    logger.debug("totalRows" + index);

    request.setAttribute("totalJobs", index);

    request.setAttribute("jobs", jobsScheduled);

    TableFacade facade = scheduledJobTableFactory.createTable(request, response);
    String sdvMatrix = facade.render();
    gridMap.addAttribute(SCHEDULED_TABLE_ATTRIBUTE, sdvMatrix);
    return gridMap;
  }
Example #5
0
  @Test
  public void testBasicStorageFunctions() throws Exception {
    Scheduler sched = createScheduler("testBasicStorageFunctions", 2);

    // test basic storage functions of scheduler...

    JobDetail job = newJob().ofType(TestJob.class).withIdentity("j1").storeDurably().build();

    assertFalse("Unexpected existence of job named 'j1'.", sched.checkExists(jobKey("j1")));

    sched.addJob(job, false);

    assertTrue(
        "Expected existence of job named 'j1' but checkExists return false.",
        sched.checkExists(jobKey("j1")));

    job = sched.getJobDetail(jobKey("j1"));

    assertNotNull("Stored job not found!", job);

    sched.deleteJob(jobKey("j1"));

    Trigger trigger =
        newTrigger()
            .withIdentity("t1")
            .forJob(job)
            .startNow()
            .withSchedule(simpleSchedule().repeatForever().withIntervalInSeconds(5))
            .build();

    assertFalse("Unexpected existence of trigger named 't1'.", sched.checkExists(triggerKey("t1")));

    sched.scheduleJob(job, trigger);

    assertTrue(
        "Expected existence of trigger named 't1' but checkExists return false.",
        sched.checkExists(triggerKey("t1")));

    job = sched.getJobDetail(jobKey("j1"));

    assertNotNull("Stored job not found!", job);

    trigger = sched.getTrigger(triggerKey("t1"));

    assertNotNull("Stored trigger not found!", trigger);

    job = newJob().ofType(TestJob.class).withIdentity("j2", "g1").build();

    trigger =
        newTrigger()
            .withIdentity("t2", "g1")
            .forJob(job)
            .startNow()
            .withSchedule(simpleSchedule().repeatForever().withIntervalInSeconds(5))
            .build();

    sched.scheduleJob(job, trigger);

    job = newJob().ofType(TestJob.class).withIdentity("j3", "g1").build();

    trigger =
        newTrigger()
            .withIdentity("t3", "g1")
            .forJob(job)
            .startNow()
            .withSchedule(simpleSchedule().repeatForever().withIntervalInSeconds(5))
            .build();

    sched.scheduleJob(job, trigger);

    List<String> jobGroups = sched.getJobGroupNames();
    List<String> triggerGroups = sched.getTriggerGroupNames();

    assertTrue("Job group list size expected to be = 2 ", jobGroups.size() == 2);
    assertTrue("Trigger group list size expected to be = 2 ", triggerGroups.size() == 2);

    Set<JobKey> jobKeys = sched.getJobKeys(GroupMatcher.jobGroupEquals(JobKey.DEFAULT_GROUP));
    Set<TriggerKey> triggerKeys =
        sched.getTriggerKeys(GroupMatcher.triggerGroupEquals(TriggerKey.DEFAULT_GROUP));

    assertTrue("Number of jobs expected in default group was 1 ", jobKeys.size() == 1);
    assertTrue("Number of triggers expected in default group was 1 ", triggerKeys.size() == 1);

    jobKeys = sched.getJobKeys(GroupMatcher.jobGroupEquals("g1"));
    triggerKeys = sched.getTriggerKeys(GroupMatcher.triggerGroupEquals("g1"));

    assertTrue("Number of jobs expected in 'g1' group was 2 ", jobKeys.size() == 2);
    assertTrue("Number of triggers expected in 'g1' group was 2 ", triggerKeys.size() == 2);

    TriggerState s = sched.getTriggerState(triggerKey("t2", "g1"));
    assertTrue("State of trigger t2 expected to be NORMAL ", s.equals(TriggerState.NORMAL));

    sched.pauseTrigger(triggerKey("t2", "g1"));
    s = sched.getTriggerState(triggerKey("t2", "g1"));
    assertTrue("State of trigger t2 expected to be PAUSED ", s.equals(TriggerState.PAUSED));

    sched.resumeTrigger(triggerKey("t2", "g1"));
    s = sched.getTriggerState(triggerKey("t2", "g1"));
    assertTrue("State of trigger t2 expected to be NORMAL ", s.equals(TriggerState.NORMAL));

    Set<String> pausedGroups = sched.getPausedTriggerGroups();
    assertTrue("Size of paused trigger groups list expected to be 0 ", pausedGroups.size() == 0);

    sched.pauseTriggers(GroupMatcher.triggerGroupEquals("g1"));

    // test that adding a trigger to a paused group causes the new trigger to be paused also...
    job = newJob().ofType(TestJob.class).withIdentity("j4", "g1").build();

    trigger =
        newTrigger()
            .withIdentity("t4", "g1")
            .forJob(job)
            .startNow()
            .withSchedule(simpleSchedule().repeatForever().withIntervalInSeconds(5))
            .build();

    sched.scheduleJob(job, trigger);
    // TODO: nexus hack: JobStoreImpl DOES NOT "remember" paused groups
    sched.pauseJob(jobKey("j4", "g1"));

    pausedGroups = sched.getPausedTriggerGroups();
    assertTrue(
        "Size of paused trigger groups list expected to be 1: " + pausedGroups,
        pausedGroups.size() == 1);

    s = sched.getTriggerState(triggerKey("t2", "g1"));
    assertTrue("State of trigger t2 expected to be PAUSED ", s.equals(TriggerState.PAUSED));

    s = sched.getTriggerState(triggerKey("t4", "g1"));
    assertTrue("State of trigger t4 expected to be PAUSED ", s.equals(TriggerState.PAUSED));

    sched.resumeTriggers(GroupMatcher.triggerGroupEquals("g1"));
    s = sched.getTriggerState(triggerKey("t2", "g1"));
    assertTrue("State of trigger t2 expected to be NORMAL ", s.equals(TriggerState.NORMAL));
    s = sched.getTriggerState(triggerKey("t4", "g1"));
    assertTrue("State of trigger t4 expected to be NORMAL ", s.equals(TriggerState.NORMAL));
    pausedGroups = sched.getPausedTriggerGroups();
    assertTrue("Size of paused trigger groups list expected to be 0 ", pausedGroups.size() == 0);

    assertFalse(
        "Scheduler should have returned 'false' from attempt to unschedule non-existing trigger. ",
        sched.unscheduleJob(triggerKey("foasldfksajdflk")));

    assertTrue(
        "Scheduler should have returned 'true' from attempt to unschedule existing trigger. ",
        sched.unscheduleJob(triggerKey("t3", "g1")));

    jobKeys = sched.getJobKeys(GroupMatcher.jobGroupEquals("g1"));
    triggerKeys = sched.getTriggerKeys(GroupMatcher.triggerGroupEquals("g1"));

    assertTrue(
        "Number of jobs expected in 'g1' group was 1 ",
        jobKeys.size() == 2); // job should have been deleted also, because it is non-durable
    assertTrue("Number of triggers expected in 'g1' group was 1 ", triggerKeys.size() == 2);

    assertTrue(
        "Scheduler should have returned 'true' from attempt to unschedule existing trigger. ",
        sched.unscheduleJob(triggerKey("t1")));

    jobKeys = sched.getJobKeys(GroupMatcher.jobGroupEquals(JobKey.DEFAULT_GROUP));
    triggerKeys = sched.getTriggerKeys(GroupMatcher.triggerGroupEquals(TriggerKey.DEFAULT_GROUP));

    assertTrue(
        "Number of jobs expected in default group was 1 ",
        jobKeys.size() == 1); // job should have been left in place, because it is non-durable
    assertTrue("Number of triggers expected in default group was 0 ", triggerKeys.size() == 0);

    sched.shutdown(true);
  }