private boolean testRetryCompleteTaskByProcessInstance(
      RuntimeManager manager, RuntimeEngine runtime, long piId)
      throws InterruptedException, Exception {
    boolean result = false;
    List<Status> statusses = new ArrayList<Status>();
    statusses.add(Status.InProgress);

    List<TaskSummary> tasks = null;
    tasks = runtime.getTaskService().getTasksByStatusByProcessInstanceId(piId, statusses, "en-UK");
    if (tasks.isEmpty()) {
      logger.debug("Retry : Task thread found no tasks for piId {}", piId);
      Thread.sleep(1000);
    } else {
      long taskId = tasks.get(0).getId();
      logger.debug("Retry : Completing task {} piId {}", taskId, piId);
      try {

        runtime.getTaskService().complete(taskId, "john", null);
        logger.debug("Retry : Completed task {} piId {}", taskId, piId);
        result = true;

      } catch (PermissionDeniedException e) {
        // TODO can we avoid these by doing it all in one transaction?
        logger.debug("Task thread was too late for starting task {} piId {}", taskId, piId);
      } catch (Exception e) {
        throw e;
      }
    }

    return result;
  }
  @Test
  public void testUserTaskFromKjar() {
    KieServices ks = KieServices.Factory.get();

    RuntimeEnvironment environment =
        RuntimeEnvironmentBuilder.Factory.get()
            .newDefaultBuilder(ks.newReleaseId(GROUP_ID, ARTIFACT_ID, VERSION))
            .userGroupCallback(userGroupCallback)
            .get();

    manager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(environment);
    assertNotNull(manager);

    RuntimeEngine engine = manager.getRuntimeEngine(EmptyContext.get());
    assertNotNull(engine);

    Map<String, Object> params = new HashMap<String, Object>();

    ProcessInstance processInstance = engine.getKieSession().startProcess("UserTask", params);

    List<TaskSummary> tasks =
        engine.getTaskService().getTasksAssignedAsPotentialOwner("john", "en-UK");
    assertNotNull(tasks);
    assertEquals(1, tasks.size());

    long taskId = tasks.get(0).getId();

    engine.getTaskService().start(taskId, "john");
    engine.getTaskService().complete(taskId, "john", null);

    processInstance = engine.getKieSession().getProcessInstance(processInstance.getId());
    assertNull(processInstance);

    manager.disposeRuntimeEngine(engine);
  }
 @Before
 public void init() throws Exception {
   createRuntimeManager(HUMAN_TASK, HUMAN_TASK2);
   RuntimeEngine runtimeEngine = getRuntimeEngine();
   kieSession = runtimeEngine.getKieSession();
   taskService = (SynchronizedTaskService) runtimeEngine.getTaskService();
 }
  private void testProcessStartOnManager(RuntimeEngine runtime) {

    KieSession ksession = runtime.getKieSession();
    assertNotNull(ksession);

    ProcessInstance processInstance = ksession.startProcess("UserTask");
    assertNotNull(processInstance);

    List<Status> statuses = new ArrayList<Status>();
    statuses.add(Status.Reserved);
    List<TaskSummary> tasks =
        runtime.getTaskService().getTasksOwnedByStatus("john", statuses, "en-UK");
    assertNotNull(tasks);
    assertEquals(1, tasks.size());

    runtime.getTaskService().start(tasks.get(0).getId(), "john");

    runtime.getTaskService().complete(tasks.get(0).getId(), "john", null);

    processInstance = ksession.getProcessInstance(processInstance.getId());
    assertNull(processInstance);
  }
  @Test
  @Ignore("JMS isn't working.. :/")
  public void testJmsRemoteApiHumanTaskProcess() throws Exception {
    // create JMS request
    RuntimeEngine engine =
        new RemoteJmsRuntimeEngineFactory(DEPLOYMENT_ID, getRemoteInitialContext())
            .newRuntimeEngine();
    KieSession ksession = engine.getKieSession();
    ProcessInstance processInstance = ksession.startProcess("org.jbpm.humantask");

    logger.debug(
        "Started process instance: "
            + processInstance
            + " "
            + (processInstance == null ? "" : processInstance.getId()));

    TaskService taskService = engine.getTaskService();
    List<TaskSummary> tasks = taskService.getTasksAssignedAsPotentialOwner(USER_ID, "en-UK");
    long taskId = findTaskId(processInstance.getId(), tasks);

    logger.debug("Found task " + taskId);
    Task task = taskService.getTaskById(taskId);
    logger.debug("Got task " + taskId + ": " + task);
    taskService.start(taskId, USER_ID);
    taskService.complete(taskId, USER_ID, null);

    logger.debug("Now expecting failure");
    try {
      taskService.complete(taskId, USER_ID, null);
      fail("Should not have been able to complete task " + taskId + " a second time.");
    } catch (Throwable t) {
      // do nothing
    }

    List<Status> statuses = new ArrayList<Status>();
    statuses.add(Status.Reserved);
    List<TaskSummary> taskIds =
        taskService.getTasksByStatusByProcessInstanceId(processInstance.getId(), statuses, "en-UK");
    assertEquals("Expected 2 tasks.", 2, taskIds.size());
  }
  @Test
  public void testSupportProcess() {
    DeploymentUnit deploymentUnitSupport =
        new KModuleDeploymentUnit(GROUP_ID, ARTIFACT_ID, VERSION);
    deploymentService.deploy(deploymentUnitSupport);
    units.add(deploymentUnitSupport);

    Map<String, Object> params = new HashMap<String, Object>();
    params.put("customer", "polymita");

    RuntimeManager managerSupport =
        deploymentService.getRuntimeManager(deploymentUnitSupport.getIdentifier());
    assertNotNull(managerSupport);

    RuntimeEngine engine = managerSupport.getRuntimeEngine(EmptyContext.get());
    assertNotNull(engine);
    ProcessInstance pI = engine.getKieSession().startProcess("support.process", params);
    assertNotNull(pI);
    TaskService taskService = engine.getTaskService();

    // Configure Release
    List<TaskSummary> tasksAssignedToSalaboy =
        taskService.getTasksAssignedAsPotentialOwner("salaboy", "en-UK");

    assertEquals(1, tasksAssignedToSalaboy.size());
    assertEquals("Create Support", tasksAssignedToSalaboy.get(0).getName());

    TaskSummary createSupportTask = tasksAssignedToSalaboy.get(0);

    taskService.start(createSupportTask.getId(), "salaboy");

    Map<String, Object> taskContent =
        ((InternalTaskService) taskService).getTaskContent(createSupportTask.getId());

    assertEquals("polymita", taskContent.get("input_customer"));

    Map<String, String> taskOutputMappings =
        bpmn2Service.getTaskOutputMappings(
            deploymentUnitSupport.getIdentifier(), "support.process", createSupportTask.getName());

    assertEquals(1, taskOutputMappings.size());
    assertEquals("output_customer", taskOutputMappings.values().iterator().next());

    Map<String, Object> output = new HashMap<String, Object>();

    output.put("output_customer", "polymita/redhat");
    taskService.complete(createSupportTask.getId(), "salaboy", output);

    tasksAssignedToSalaboy = taskService.getTasksAssignedAsPotentialOwner("salaboy", "en-UK");
    assertEquals(1, tasksAssignedToSalaboy.size());

    assertEquals("Resolve Support", tasksAssignedToSalaboy.get(0).getName());

    TaskSummary resolveSupportTask = tasksAssignedToSalaboy.get(0);

    taskService.start(resolveSupportTask.getId(), "salaboy");

    taskService.complete(resolveSupportTask.getId(), "salaboy", null);

    tasksAssignedToSalaboy = taskService.getTasksAssignedAsPotentialOwner("salaboy", "en-UK");
    assertEquals(1, tasksAssignedToSalaboy.size());

    assertEquals("Notify Customer", tasksAssignedToSalaboy.get(0).getName());

    TaskSummary notifySupportTask = tasksAssignedToSalaboy.get(0);

    taskService.start(notifySupportTask.getId(), "salaboy");
    output = new HashMap<String, Object>();
    output.put("output_solution", "solved today");
    taskService.complete(notifySupportTask.getId(), "salaboy", output);
  }
  @Test
  public void testSessionPerProcessInstance() throws Exception {
    RuntimeEnvironment environment =
        RuntimeEnvironmentBuilder.Factory.get()
            .newDefaultBuilder()
            .entityManagerFactory(emf)
            .userGroupCallback(userGroupCallback)
            .addAsset(
                ResourceFactory.newClassPathResource(
                    "org/jbpm/test/functional/timer/IntermediateCatchEventTimerCycleWithHT.bpmn2"),
                ResourceType.BPMN2)
            .schedulerService(globalScheduler)
            .get();

    long startTimeStamp = System.currentTimeMillis();
    long maxEndTime = startTimeStamp + maxWaitTime;

    manager = RuntimeManagerFactory.Factory.get().newPerProcessInstanceRuntimeManager(environment);
    // prepare task service with users and groups
    RuntimeEngine engine = manager.getRuntimeEngine(EmptyContext.get());
    TaskService taskService = engine.getTaskService();

    Group grouphr = TaskModelProvider.getFactory().newGroup();
    ((InternalOrganizationalEntity) grouphr).setId("HR");

    User mary = TaskModelProvider.getFactory().newUser();
    ((InternalOrganizationalEntity) mary).setId("mary");
    User john = TaskModelProvider.getFactory().newUser();
    ((InternalOrganizationalEntity) john).setId("john");

    ((InternalTaskService) taskService).addGroup(grouphr);
    ((InternalTaskService) taskService).addUser(mary);
    ((InternalTaskService) taskService).addUser(john);

    manager.disposeRuntimeEngine(engine);

    completedStart = 0;
    for (int i = 0; i < nbThreadsProcess; i++) {
      new StartProcessPerProcessInstanceRunnable(manager, i).run();
    }
    completedTask = 0;
    for (int i = 0; i < nbThreadsTask; i++) {
      new Thread(new CompleteTaskPerProcessInstanceRunnable(manager, i)).start();
    }
    while (completedStart < nbThreadsProcess || completedTask < nbThreadsTask) {
      Thread.sleep(100);
      if (System.currentTimeMillis() > maxEndTime) {
        fail("Failure, did not finish in time most likely hanging");
      }
    }
    // make sure all process instance were completed
    engine = manager.getRuntimeEngine(EmptyContext.get());
    AuditService logService = engine.getAuditService();
    // active
    List<? extends ProcessInstanceLog> logs =
        logService.findActiveProcessInstances("IntermediateCatchEvent");
    assertNotNull(logs);
    for (ProcessInstanceLog log : logs) {
      logger.debug("Left over {}", log.getProcessInstanceId());
    }
    assertEquals(0, logs.size());

    // completed
    logs = logService.findProcessInstances("IntermediateCatchEvent");
    assertNotNull(logs);
    assertEquals(nbThreadsProcess, logs.size());
    manager.disposeRuntimeEngine(engine);

    logger.debug("Done");
  }