@Deployment(resources = {"org/camunda/bpm/engine/test/jobexecutor/simpleAsyncProcess.bpmn20.xml"})
  public void testJobExecutorOnlyAcquiresActiveJobs() {

    // given suspended job definition:
    managementService.suspendJobDefinitionByProcessDefinitionKey("simpleAsyncProcess");

    // if I start a new instance
    runtimeService.startProcessInstanceByKey("simpleAsyncProcess");

    // then the new job executor will not acquire the job:
    AcquiredJobs acquiredJobs = acquireJobs();
    assertEquals(0, acquiredJobs.size());

    // -------------------------

    // given a active job definition:
    managementService.activateJobDefinitionByProcessDefinitionKey("simpleAsyncProcess", true);

    // then the new job executor will not acquire the job:
    acquiredJobs = acquireJobs();
    assertEquals(1, acquiredJobs.size());

    // clean up log
    TestHelper.clearOpLog(processEngineConfiguration);
  }
  @Deployment
  public void testExclusiveJobs() {

    JobDefinition jobDefinition =
        managementService.createJobDefinitionQuery().activityIdIn("task2").singleResult();

    // given that the second task is suspended
    managementService.suspendJobDefinitionById(jobDefinition.getId());

    // if I start a process instance
    runtimeService.startProcessInstanceByKey("testProcess");

    waitForJobExecutorToProcessAllJobs(6000);

    // then the second task is not executed
    assertEquals(1, runtimeService.createProcessInstanceQuery().count());
    // there is a suspended job instance
    Job job = managementService.createJobQuery().singleResult();
    assertEquals(job.getJobDefinitionId(), jobDefinition.getId());
    assertTrue(job.isSuspended());

    // if I unsuspend the job definition, the job is executed:
    managementService.activateJobDefinitionById(jobDefinition.getId(), true);

    waitForJobExecutorToProcessAllJobs(5000);

    assertEquals(0, runtimeService.createProcessInstanceQuery().count());

    // clean up log
    TestHelper.clearOpLog(processEngineConfiguration);
  }
  public void testSetJobRetriesUnlocksInconsistentJob() {
    // case 1
    // given an inconsistent job that is never again picked up by a job executor
    createJob(0, "owner", ClockUtil.getCurrentTime());

    // when the job retries are reset
    JobEntity job = (JobEntity) managementService.createJobQuery().singleResult();
    managementService.setJobRetries(job.getId(), 3);

    // then the job can be picked up again
    job = (JobEntity) managementService.createJobQuery().singleResult();
    assertNotNull(job);
    assertNull(job.getLockOwner());
    assertNull(job.getLockExpirationTime());
    assertEquals(3, job.getRetries());

    deleteJobAndIncidents(job);

    // case 2
    // given an inconsistent job that is never again picked up by a job executor
    createJob(2, "owner", null);

    // when the job retries are reset
    job = (JobEntity) managementService.createJobQuery().singleResult();
    managementService.setJobRetries(job.getId(), 3);

    // then the job can be picked up again
    job = (JobEntity) managementService.createJobQuery().singleResult();
    assertNotNull(job);
    assertNull(job.getLockOwner());
    assertNull(job.getLockExpirationTime());
    assertEquals(3, job.getRetries());

    deleteJobAndIncidents(job);

    // case 3
    // given a consistent job
    createJob(2, "owner", ClockUtil.getCurrentTime());

    // when the job retries are reset
    job = (JobEntity) managementService.createJobQuery().singleResult();
    managementService.setJobRetries(job.getId(), 3);

    // then the lock owner and expiration should not change
    job = (JobEntity) managementService.createJobQuery().singleResult();
    assertNotNull(job);
    assertNotNull(job.getLockOwner());
    assertNotNull(job.getLockExpirationTime());
    assertEquals(3, job.getRetries());

    deleteJobAndIncidents(job);

    TestHelper.clearOpLog(processEngineConfiguration);
  }
 public void testInvalidProcessDefinition() {
   try {
     String resource =
         TestHelper.getBpmnProcessDefinitionResource(getClass(), "testInvalidProcessDefinition");
     repositoryService.createDeployment().name(resource).addClasspathResource(resource).deploy();
     fail();
   } catch (ProcessEngineException e) {
     assertTextPresent("cvc-complex-type.3.2.2:", e.getMessage());
     assertTextPresent("invalidAttribute", e.getMessage());
     assertTextPresent("process", e.getMessage());
   }
 }
 public void testInvalidSubProcessWithTimerStartEvent() {
   try {
     String resource =
         TestHelper.getBpmnProcessDefinitionResource(
             getClass(), "testInvalidSubProcessWithTimerStartEvent");
     repositoryService.createDeployment().name(resource).addClasspathResource(resource).deploy();
     fail(
         "Exception expected: Process definition could be parsed, although the sub process contains a timer start event.");
   } catch (ProcessEngineException e) {
     assertTextPresent(
         "timerEventDefinition is not allowed on start event within a subprocess", e.getMessage());
   }
 }
 public void testInvalidSubProcessWithMessageStartEvent() {
   try {
     String resource =
         TestHelper.getBpmnProcessDefinitionResource(
             getClass(), "testInvalidSubProcessWithMessageStartEvent");
     repositoryService.createDeployment().name(resource).addClasspathResource(resource).deploy();
     fail(
         "Process definition could be parsed, although the sub process contains not a blanco start event.");
   } catch (ProcessEngineException e) {
     assertTextPresent(
         "messageEventDefinition only allowed on start event if subprocess is an event subprocess",
         e.getMessage());
   }
 }
  @Deployment(resources = {"org/camunda/bpm/engine/test/jobexecutor/simpleAsyncProcess.bpmn20.xml"})
  public void testCreateJobInstanceSuspended() {

    // given suspended job definition:
    managementService.suspendJobDefinitionByProcessDefinitionKey("simpleAsyncProcess");

    // if I start a new instance
    runtimeService.startProcessInstanceByKey("simpleAsyncProcess");

    // then the new job instance is created as suspended:
    assertNotNull(managementService.createJobQuery().suspended().singleResult());
    assertNull(managementService.createJobQuery().active().singleResult());

    // clean up log
    TestHelper.clearOpLog(processEngineConfiguration);
  }
  @Deployment(resources = {"org/camunda/bpm/engine/test/jobexecutor/simpleAsyncProcess.bpmn20.xml"})
  public void testSuspendJobDuringAcquisition() {

    runtimeService.startProcessInstanceByKey("simpleAsyncProcess");

    // given a waiting acquisition and a waiting suspension
    JobAcquisitionThread acquisitionThread = new JobAcquisitionThread();
    acquisitionThread.startAndWaitUntilControlIsReturned();

    JobSuspensionThread jobSuspensionThread = new JobSuspensionThread("simpleAsyncProcess");
    jobSuspensionThread.startAndWaitUntilControlIsReturned();

    // first complete suspension:
    jobSuspensionThread.proceedAndWaitTillDone();
    acquisitionThread.proceedAndWaitTillDone();

    // then the acquisition will not fail with optimistic locking
    assertNull(jobSuspensionThread.exception);
    assertNull(acquisitionThread.exception);
    // but the job will also not be acquired
    assertEquals(0, acquisitionThread.acquiredJobs.size());

    // --------------------------------------------

    // given a waiting acquisition and a waiting suspension
    acquisitionThread = new JobAcquisitionThread();
    acquisitionThread.startAndWaitUntilControlIsReturned();

    jobSuspensionThread = new JobSuspensionThread("simpleAsyncProcess");
    jobSuspensionThread.startAndWaitUntilControlIsReturned();

    // first complete acquisition:
    acquisitionThread.proceedAndWaitTillDone();
    jobSuspensionThread.proceedAndWaitTillDone();

    // then there are no optimistic locking exceptions
    assertNull(jobSuspensionThread.exception);
    assertNull(acquisitionThread.exception);

    // clean up log
    TestHelper.clearOpLog(processEngineConfiguration);
  }
  @Deployment(resources = {"org/camunda/bpm/engine/test/jobexecutor/simpleAsyncProcess.bpmn20.xml"})
  public void testSuspendJobDuringExecution() {

    runtimeService.startProcessInstanceByKey("simpleAsyncProcess");
    Job job = managementService.createJobQuery().singleResult();

    // given a waiting execution and a waiting suspension
    JobExecutionThread executionthread = new JobExecutionThread(job.getId());
    executionthread.startAndWaitUntilControlIsReturned();

    JobSuspensionThread jobSuspensionThread = new JobSuspensionThread("simpleAsyncProcess");
    jobSuspensionThread.startAndWaitUntilControlIsReturned();

    // first complete suspension:
    jobSuspensionThread.proceedAndWaitTillDone();
    executionthread.proceedAndWaitTillDone();

    // then the execution will fail with optimistic locking
    assertNull(jobSuspensionThread.exception);
    assertNotNull(executionthread.exception);

    // --------------------------------------------

    // given a waiting execution and a waiting suspension
    executionthread = new JobExecutionThread(job.getId());
    executionthread.startAndWaitUntilControlIsReturned();

    jobSuspensionThread = new JobSuspensionThread("simpleAsyncProcess");
    jobSuspensionThread.startAndWaitUntilControlIsReturned();

    // first complete execution:
    executionthread.proceedAndWaitTillDone();
    jobSuspensionThread.proceedAndWaitTillDone();

    // then there are no optimistic locking exceptions
    assertNull(jobSuspensionThread.exception);
    assertNull(executionthread.exception);

    // clean up log
    TestHelper.clearOpLog(processEngineConfiguration);
  }
 public void tearDown() throws Exception {
   TestHelper.clearOpLog(processEngineConfiguration);
 }