@Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    JobKey jobKey = context.getJobDetail().getKey();
    LOG.debug("Executing linear job: {}", jobKey);
    JobDataMap jobDataMap = context.getMergedJobDataMap();

    if (!executionScheduleManager.continueOnMisfire(context)) {
      throw new JobExecutionException("Canceled execution based on misfire"
        + " toleration threshold, job: " + jobKey
        + ", scheduleTime = " + context.getScheduledFireTime());
    }

    Map<String, Object> properties = jobDataMap.getWrappedMap();
    boolean finalize = false;

    // Perform work and exit if failure reported
    try {
      doWork(properties);
    } catch (AmbariException e) {
      LOG.error("Exception caught on execution of job " + jobKey +
        ". Exiting linear chain...", e);

      finalize = true;
      throw new JobExecutionException(e);

    } catch (RuntimeException e) {
      LOG.error("Unexpected exception caught on execution of job " + jobKey + ". " +
          "Exiting linear chain...", e);

      finalize = true;
      throw e;

    } finally {
      // Finalize before exiting chain
      if (finalize) {
        try {
          finalizeExecution(properties);
        } catch (AmbariException e) {
          LOG.warn("Unable to finalize execution for job: " + jobKey);
        }
      }
    }

    LOG.debug("Finished linear job: {}", jobKey);

    String nextJobName = jobDataMap.getString(NEXT_EXECUTION_JOB_NAME_KEY);
    String nextJobGroup = jobDataMap.getString(NEXT_EXECUTION_JOB_GROUP_KEY);

    // If no more jobs left, finalize and return
    if (nextJobName == null || nextJobName.isEmpty()) {
      LOG.debug("End of linear job chain. Returning with success.");
      try {
        finalizeExecution(properties);
      } catch (AmbariException e) {
        LOG.warn("Unable to finalize execution for job: " + jobKey);
      }
      return;
    }

    try {
      executionScheduleManager.pauseAfterBatchIfNeeded(jobDataMap.getLong(BATCH_REQUEST_EXECUTION_ID_KEY),
          jobDataMap.getLong(BATCH_REQUEST_BATCH_ID_KEY), jobDataMap.getString(BATCH_REQUEST_CLUSTER_NAME_KEY));
    } catch (AmbariException e) {
      LOG.warn("Received exception while trying to auto pause the scheduled request execution :", e);
    }

    String status = null;
    try {
      status = executionScheduleManager.getBatchRequestStatus(jobDataMap.getLong(BATCH_REQUEST_EXECUTION_ID_KEY), jobDataMap.getString(BATCH_REQUEST_CLUSTER_NAME_KEY));
    } catch (AmbariException e) {
      LOG.warn("Unable to define the status of batch request : ", e);
    }

    if(ABORTED.name().equals(status) || PAUSED.name().equals(status)) {
      LOG.info("The linear job chain was paused or aborted, not triggering the next one");
      return;
    }


    int separationSeconds = jobDataMap.getIntValue(NEXT_EXECUTION_SEPARATION_SECONDS);
    Object failedCount = properties.get(BatchRequestJob.BATCH_REQUEST_FAILED_TASKS_KEY);
    Object totalCount = properties.get(BatchRequestJob.BATCH_REQUEST_TOTAL_TASKS_KEY);

    // Create trigger for next job execution
    // Persist counts with trigger, so that they apply to current batch only
    Trigger trigger = newTrigger()
      .forJob(nextJobName, nextJobGroup)
      .withIdentity("TriggerForJob-" + nextJobName, LINEAR_EXECUTION_TRIGGER_GROUP)
      .withSchedule(simpleSchedule().withMisfireHandlingInstructionFireNow())
      .startAt(futureDate(separationSeconds, DateBuilder.IntervalUnit.SECOND))
      .usingJobData(BatchRequestJob.BATCH_REQUEST_FAILED_TASKS_KEY,
        failedCount != null ? (Integer) failedCount : 0)
      .usingJobData(BatchRequestJob.BATCH_REQUEST_TOTAL_TASKS_KEY,
        totalCount != null ? (Integer) totalCount : 0)
      .build();

    executionScheduleManager.scheduleJob(trigger);
  }
Get the next job id from context and create a trigger to fire the next
job.
@param context
@throws JobExecutionException
ambari-server/src/main/java/org/apache/ambari/server/scheduler/AbstractLinearExecutionJob.java