private void when_all_jobs_within_X_days_are_executed(int days) {
    Date date = DateTime.now().plus(Days.days(days)).toDate();
    Job job = managementService.createJobQuery().duedateLowerThan(date).singleResult();

    assertThat(job, notNullValue());
    managementService.executeJob(job.getId());
  }
  @Deployment
  public void testExpression() {
    // Set the clock fixed
    HashMap<String, Object> variables1 = new HashMap<String, Object>();
    variables1.put("dueDate", new Date());

    HashMap<String, Object> variables2 = new HashMap<String, Object>();
    variables2.put("dueDate", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(new Date()));

    // After process start, there should be timer created
    ProcessInstance pi1 =
        runtimeService.startProcessInstanceByKey("intermediateTimerEventExample", variables1);
    ProcessInstance pi2 =
        runtimeService.startProcessInstanceByKey("intermediateTimerEventExample", variables2);

    assertEquals(1, managementService.createJobQuery().processInstanceId(pi1.getId()).count());
    assertEquals(1, managementService.createJobQuery().processInstanceId(pi2.getId()).count());

    // After setting the clock to one second in the future the timers should fire
    List<Job> jobs = managementService.createJobQuery().executable().list();
    assertEquals(2, jobs.size());
    for (Job job : jobs) {
      managementService.executeJob(job.getId());
    }

    assertEquals(0, managementService.createJobQuery().processInstanceId(pi1.getId()).count());
    assertEquals(0, managementService.createJobQuery().processInstanceId(pi2.getId()).count());

    assertProcessEnded(pi1.getProcessInstanceId());
    assertProcessEnded(pi2.getProcessInstanceId());
  }
  @Deployment(
      resources = {
        "org/activiti/examples/bpmn/event/timer/BoundaryTimerEventTest.testInterruptingTimerDuration.bpmn"
      })
  @Test
  public void testInterruptingTimerDuration() {

    // Start process instance
    RuntimeService runtimeService = activitiRule.getRuntimeService();
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("escalationExample");

    // There should be one task, with a timer : first line support
    TaskService taskService = activitiRule.getTaskService();
    Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
    assertEquals("First line support", task.getName());

    // Manually execute the job
    ManagementService managementService = activitiRule.getManagementService();
    Job timer = managementService.createJobQuery().singleResult();
    managementService.executeJob(timer.getId());

    // The timer has fired, and the second task (secondlinesupport) now exists
    task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
    assertEquals("Second line support", task.getName());
  }
  protected void removeObsoleteTimers(ProcessDefinitionEntity processDefinition) {

    List<Job> jobsToDelete = null;

    if (processDefinition.getTenantId() != null
        && !ProcessEngineConfiguration.NO_TENANT_ID.equals(processDefinition.getTenantId())) {
      jobsToDelete =
          Context.getCommandContext()
              .getJobEntityManager()
              .findJobsByTypeAndProcessDefinitionKeyAndTenantId(
                  TimerStartEventJobHandler.TYPE,
                  processDefinition.getKey(),
                  processDefinition.getTenantId());
    } else {
      jobsToDelete =
          Context.getCommandContext()
              .getJobEntityManager()
              .findJobsByTypeAndProcessDefinitionKeyNoTenantId(
                  TimerStartEventJobHandler.TYPE, processDefinition.getKey());
    }

    if (jobsToDelete != null) {
      for (Job job : jobsToDelete) {
        new CancelJobsCmd(job.getId()).execute(Context.getCommandContext());
      }
    }
  }
  /** Test create, update and delete events of jobs entities. */
  @Deployment
  public void testJobEntityEvents() throws Exception {
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("testJobEvents");
    Job theJob =
        managementService
            .createJobQuery()
            .processInstanceId(processInstance.getId())
            .singleResult();
    assertNotNull(theJob);

    // Check if create-event has been dispatched
    assertEquals(1, listener.getEventsReceived().size());
    ActivitiEvent event = listener.getEventsReceived().get(0);
    assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType());
    checkEventContext(event, theJob, false);

    listener.clearEventsReceived();

    // Update the job-entity. Check if update event is dispatched with update job entity
    managementService.setJobRetries(theJob.getId(), 5);
    assertEquals(1, listener.getEventsReceived().size());
    event = listener.getEventsReceived().get(0);
    assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType());
    Job updatedJob = (Job) ((ActivityEntityEvent) event).getEntity();
    assertEquals(5, updatedJob.getRetries());
    checkEventContext(event, theJob, true);

    listener.clearEventsReceived();

    // Force timer to fire
    Calendar tomorrow = Calendar.getInstance();
    tomorrow.add(Calendar.DAY_OF_YEAR, 1);
    ClockUtil.setCurrentTime(tomorrow.getTime());
    waitForJobExecutorToProcessAllJobs(2000, 100);

    // Check delete-event has been dispatched
    assertEquals(3, listener.getEventsReceived().size());

    // First, a timer fired event has been dispatched
    event = listener.getEventsReceived().get(0);
    assertEquals(ActivitiEventType.TIMER_FIRED, event.getType());
    checkEventContext(event, theJob, true);

    // Next, a delete event has been dispatched
    event = listener.getEventsReceived().get(1);
    assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType());
    checkEventContext(event, theJob, true);

    // Finally, a complete event has been dispatched
    event = listener.getEventsReceived().get(2);
    assertEquals(ActivitiEventType.JOB_EXECUTION_SUCCESS, event.getType());
    checkEventContext(event, theJob, true);
  }
  @Deployment
  public void testLoopWithCycle() {
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("testLoop");

    // After looping 3 times, the process should end. Cycle should NOT repeat itself
    for (int i = 0; i < 3; i++) {
      Job timer = managementService.createJobQuery().singleResult();
      managementService.executeJob(timer.getId());
    }

    assertProcessEnded(processInstance.getId());
  }
  public void testSignalStartEventFromProcesAsync() {

    // Deploy test processes
    repositoryService
        .createDeployment()
        .addClasspathResource(
            "org/activiti/engine/test/bpmn/event/signal/SignalEventTest.testSignalStartEventAsync.bpmn20.xml")
        .deploy();

    // Starting the process that fires the signal should start 1 process instance that are listening
    // on that signal, the others are done async
    runtimeService.startProcessInstanceByKey("processWithSignalThrow");

    // Verify
    assertEquals(0, runtimeService.createProcessInstanceQuery().count());
    assertEquals(0, taskService.createTaskQuery().count());

    assertEquals(3, managementService.createJobQuery().count());
    for (Job job : managementService.createJobQuery().list()) {
      managementService.executeJob(job.getId());
    }
    assertEquals(3, runtimeService.createProcessInstanceQuery().count());
    assertEquals(3, taskService.createTaskQuery().count());

    List<Task> tasks = taskService.createTaskQuery().orderByTaskName().asc().list();
    List<String> names = Arrays.asList("A", "B", "C");
    for (int i = 0; i < tasks.size(); i++) {
      assertEquals("Task in process " + names.get(i), tasks.get(i).getName());
    }

    // Start a process with a signal boundary event
    runtimeService.startProcessInstanceByKey("processWithSignalCatch");
    assertEquals(4, runtimeService.createProcessInstanceQuery().count());
    assertEquals(4, taskService.createTaskQuery().count());
    assertEquals(1, taskService.createTaskQuery().taskName("Task in process D").count());

    // Firing again
    runtimeService.startProcessInstanceByKey("processWithSignalThrow");

    assertEquals(4, managementService.createJobQuery().count());
    for (Job job : managementService.createJobQuery().list()) {
      managementService.executeJob(job.getId());
    }
    assertEquals(7, runtimeService.createProcessInstanceQuery().count());
    assertEquals(7, taskService.createTaskQuery().count());
    assertEquals(1, taskService.createTaskQuery().taskName("Task after signal").count());

    // Cleanup
    for (org.activiti.engine.repository.Deployment deployment :
        repositoryService.createDeploymentQuery().list()) {
      repositoryService.deleteDeployment(deployment.getId(), true);
    }
  }
  protected void checkEventContext(
      ActivitiEvent event, Job entity, boolean scopeExecutionExpected) {
    assertEquals(entity.getProcessInstanceId(), event.getProcessInstanceId());
    assertEquals(entity.getProcessDefinitionId(), event.getProcessDefinitionId());
    if (scopeExecutionExpected) {
      assertEquals(entity.getExecutionId(), event.getExecutionId());
    } else {
      assertEquals(entity.getProcessInstanceId(), event.getExecutionId());
    }

    assertTrue(event instanceof ActivityEntityEvent);
    ActivityEntityEvent entityEvent = (ActivityEntityEvent) event;
    assertTrue(entityEvent.getEntity() instanceof Job);
    assertEquals(entity.getId(), ((Job) entityEvent.getEntity()).getId());
  }
  /** Test create, update and delete events of jobs entities. */
  @Deployment
  public void testJobEntityEventsException() throws Exception {
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("testJobEvents");
    Job theJob =
        managementService
            .createJobQuery()
            .processInstanceId(processInstance.getId())
            .singleResult();
    assertNotNull(theJob);

    // Set retries to 1, to prevent multiple chains of events being thrown
    managementService.setJobRetries(theJob.getId(), 1);

    listener.clearEventsReceived();

    // Force timer to fire
    Calendar tomorrow = Calendar.getInstance();
    tomorrow.add(Calendar.DAY_OF_YEAR, 1);
    ClockUtil.setCurrentTime(tomorrow.getTime());
    waitForJobExecutorToProcessAllJobs(2000, 100);

    // Check delete-event has been dispatched
    assertEquals(4, listener.getEventsReceived().size());

    // First, the job-entity was deleted, as the job was executed
    ActivitiEvent event = listener.getEventsReceived().get(0);
    assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType());
    checkEventContext(event, theJob, true);

    // Next, a job failed event is dispatched
    event = listener.getEventsReceived().get(1);
    assertEquals(ActivitiEventType.JOB_EXECUTION_FAILURE, event.getType());
    checkEventContext(event, theJob, true);

    // Finally, an update-event is received and the job count is decremented
    event = listener.getEventsReceived().get(2);
    assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType());
    checkEventContext(event, theJob, true);

    event = listener.getEventsReceived().get(3);
    assertEquals(ActivitiEventType.JOB_RETRIES_DECREMENTED, event.getType());
    assertEquals(0, ((Job) ((ActivityEntityEvent) event).getEntity()).getRetries());
    checkEventContext(event, theJob, true);
  }
 public LegacyJobResponse(Job job) {
   setId(job.getId());
   setExecutionId(job.getExecutionId());
   setProcessInstanceId(job.getProcessInstanceId());
   setDueDate(RequestUtil.dateToString(job.getDuedate()));
   setRetries(job.getRetries());
   setExceptionMessage(job.getExceptionMessage());
 }
  @Deployment(
      resources = {
        "org/activiti/rest/api/management/JobCollectionResourceTest.testTimerProcess.bpmn20.xml"
      })
  public void testGetJobs() throws Exception {
    Calendar hourAgo = Calendar.getInstance();
    hourAgo.add(Calendar.HOUR, -1);

    Calendar inAnHour = Calendar.getInstance();
    inAnHour.add(Calendar.HOUR, 1);

    // Start process, forcing error on job-execution
    ProcessInstance processInstance =
        runtimeService.startProcessInstanceByKey(
            "timerProcess", Collections.singletonMap("error", (Object) Boolean.TRUE));

    Job timerJob =
        managementService
            .createJobQuery()
            .processInstanceId(processInstance.getId())
            .timers()
            .singleResult();
    assertNotNull(timerJob);

    for (int i = 0; i < timerJob.getRetries(); i++) {
      // Force execution of job until retries are exhausted
      try {
        managementService.executeJob(timerJob.getId());
        fail();
      } catch (ActivitiException expected) {
        // Ignore, we expect the exception
      }
    }
    timerJob =
        managementService
            .createJobQuery()
            .processInstanceId(processInstance.getId())
            .timers()
            .singleResult();
    assertEquals(0, timerJob.getRetries());

    // Fetch the async-job (which has retries left)
    Job asyncJob =
        managementService
            .createJobQuery()
            .processInstanceId(processInstance.getId())
            .withRetriesLeft()
            .singleResult();

    // Test fetching all jobs
    String url = RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION);
    assertResultsPresentInDataResponse(url, asyncJob.getId(), timerJob.getId());

    // Fetch using job-id
    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION) + "?id=" + asyncJob.getId();
    assertResultsPresentInDataResponse(url, asyncJob.getId());

    // Fetch using processInstanceId
    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?processInstanceId="
            + processInstance.getId();
    assertResultsPresentInDataResponse(url, asyncJob.getId(), timerJob.getId());

    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?processInstanceId=unexisting";
    assertResultsPresentInDataResponse(url);

    // Fetch using executionId
    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?executionId="
            + asyncJob.getExecutionId();
    assertResultsPresentInDataResponse(url, asyncJob.getId());

    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?executionId="
            + timerJob.getExecutionId();
    assertResultsPresentInDataResponse(url, timerJob.getId());

    // Fetch using processDefinitionId
    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?processDefinitionId="
            + processInstance.getProcessDefinitionId();
    assertResultsPresentInDataResponse(url, asyncJob.getId(), timerJob.getId());

    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?processDefinitionId=unexisting";
    assertResultsPresentInDataResponse(url);

    // Fetch using withRetriesLeft
    url = RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION) + "?withRetriesLeft=true";
    assertResultsPresentInDataResponse(url, asyncJob.getId());

    // Fetch using executable
    url = RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION) + "?executable=true";
    assertResultsPresentInDataResponse(url, asyncJob.getId());

    // Fetch using timers only
    url = RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION) + "?timersOnly=true";
    assertResultsPresentInDataResponse(url, timerJob.getId());

    // Combining messagesOnly with timersOnly should result in exception
    ClientResource client =
        getAuthenticatedClient(
            RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
                + "?timersOnly=true&messagesOnly=true");
    try {
      client.get();
      fail("Exception expected");
    } catch (ResourceException expected) {
      assertEquals(Status.CLIENT_ERROR_BAD_REQUEST, expected.getStatus());
      assertEquals(
          "Only one of 'timersOnly' or 'messagesOnly' can be provided.",
          expected.getStatus().getDescription());
    }

    // Fetch using dueBefore
    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?dueBefore="
            + getISODateString(inAnHour.getTime());
    assertResultsPresentInDataResponse(url, timerJob.getId());

    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?dueBefore="
            + getISODateString(hourAgo.getTime());
    assertResultsPresentInDataResponse(url);

    // Fetch using dueAfter
    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?dueAfter="
            + getISODateString(hourAgo.getTime());
    assertResultsPresentInDataResponse(url, timerJob.getId());

    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?dueAfter="
            + getISODateString(inAnHour.getTime());
    assertResultsPresentInDataResponse(url);

    // Fetch using withException
    url = RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION) + "?withException=true";
    assertResultsPresentInDataResponse(url, timerJob.getId());

    // Fetch with exceptionMessage
    url =
        RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION)
            + "?exceptionMessage="
            + timerJob.getExceptionMessage();
    assertResultsPresentInDataResponse(url, timerJob.getId());

    // Fetch with empty exceptionMessage
    url = RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB_COLLECTION) + "?exceptionMessage=";
    assertResultsPresentInDataResponse(url);
  }