text:
/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.camunda.bpm.engine.test.api.externaltask;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.ibatis.jdbc.RuntimeSqlException;
import org.camunda.bpm.engine.BadUserRequestException;
import org.camunda.bpm.engine.ProcessEngineException;
import org.camunda.bpm.engine.exception.NotFoundException;
import org.camunda.bpm.engine.exception.NullValueException;
import org.camunda.bpm.engine.externaltask.ExternalTask;
import org.camunda.bpm.engine.externaltask.ExternalTaskQueryBuilder;
import org.camunda.bpm.engine.externaltask.LockedExternalTask;
import org.camunda.bpm.engine.history.HistoricIncident;
import org.camunda.bpm.engine.impl.history.HistoryLevel;
import org.camunda.bpm.engine.impl.test.PluggableProcessEngineTestCase;
import org.camunda.bpm.engine.impl.util.ClockUtil;
import org.camunda.bpm.engine.runtime.ActivityInstance;
import org.camunda.bpm.engine.runtime.Incident;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.engine.test.Deployment;
import org.camunda.bpm.engine.test.util.AssertUtil;
import org.camunda.bpm.engine.variable.VariableMap;
import org.camunda.bpm.engine.variable.Variables;
import org.joda.time.DateTime;
import org.junit.Assert;

import java.util.Date;
import java.util.List;

import static org.camunda.bpm.engine.test.util.ActivityInstanceAssert.assertThat;
import static org.camunda.bpm.engine.test.util.ActivityInstanceAssert.describeActivityInstanceTree;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;

/**
 * @author Thorben Lindhauer
 *
 */
public class ExternalTaskServiceTest extends PluggableProcessEngineTestCase {

  protected static final String WORKER_ID = "aWorkerId";
  protected static final long LOCK_TIME = 10000L;
  protected static final String TOPIC_NAME = "externalTaskTopic";

  protected void setUp() throws Exception {
    ClockUtil.setCurrentTime(new Date());
  }

  protected void tearDown() throws Exception {
    ClockUtil.reset();
  }

  public void testFailOnMalformedpriorityInput() {
    try {
      repositoryService
        .createDeployment()
        .addClasspathResource("org/camunda/bpm/engine/test/api/externaltask/externalTaskInvalidPriority.bpmn20.xml")
        .deploy();
      fail("deploying a process with malformed priority should not succeed");
    } catch (ProcessEngineException e) {
      assertTextPresentIgnoreCase("value 'NOTaNumber' for attribute 'taskPriority' "
          + "is not a valid number", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetch() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then
    assertEquals(1, externalTasks.size());

    LockedExternalTask task = externalTasks.get(0);
    assertNotNull(task.getId());
    assertEquals(processInstance.getId(), task.getProcessInstanceId());
    assertEquals(processInstance.getProcessDefinitionId(), task.getProcessDefinitionId());
    assertEquals("externalTask", task.getActivityId());
    assertEquals("oneExternalTaskProcess", task.getProcessDefinitionKey());
    assertEquals(TOPIC_NAME, task.getTopicName());

    ActivityInstance activityInstance = runtimeService
      .getActivityInstance(processInstance.getId())
      .getActivityInstances("externalTask")[0];

    assertEquals(activityInstance.getId(), task.getActivityInstanceId());
    assertEquals(activityInstance.getExecutionIds()[0], task.getExecutionId());

    AssertUtil.assertEqualsSecondPrecision(nowPlus(LOCK_TIME), task.getLockExpirationTime());

    assertEquals(WORKER_ID, task.getWorkerId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskWithPriorityProcess.bpmn20.xml")
  public void testFetchWithPriority() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("twoExternalTaskWithPriorityProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID, true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then
    assertEquals(1, externalTasks.size());

    LockedExternalTask task = externalTasks.get(0);
    assertNotNull(task.getId());
    assertEquals(processInstance.getId(), task.getProcessInstanceId());
    assertEquals(processInstance.getProcessDefinitionId(), task.getProcessDefinitionId());
    assertEquals("externalTaskWithPrio", task.getActivityId());
    assertEquals("twoExternalTaskWithPriorityProcess", task.getProcessDefinitionKey());
    assertEquals(TOPIC_NAME, task.getTopicName());
    assertEquals(7, task.getPriority());

    ActivityInstance activityInstance = runtimeService
      .getActivityInstance(processInstance.getId())
      .getActivityInstances("externalTaskWithPrio")[0];

    assertEquals(activityInstance.getId(), task.getActivityInstanceId());
    assertEquals(activityInstance.getExecutionIds()[0], task.getExecutionId());

    AssertUtil.assertEqualsSecondPrecision(nowPlus(LOCK_TIME), task.getLockExpirationTime());

    assertEquals(WORKER_ID, task.getWorkerId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/externalTaskPriorityProcess.bpmn20.xml")
  public void testFetchProcessWithPriority() {
    // given
    runtimeService.startProcessInstanceByKey("twoExternalTaskWithPriorityProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(2, WORKER_ID, true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(2, externalTasks.size());

    // then
    //task with no prio gets prio defined by process
    assertEquals(9, externalTasks.get(0).getPriority());
    //task with own prio overrides prio defined by process
    assertEquals(7, externalTasks.get(1).getPriority());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/externalTaskPriorityExpressionProcess.bpmn20.xml")
  public void testFetchProcessWithPriorityExpression() {
    // given
    runtimeService.startProcessInstanceByKey("twoExternalTaskWithPriorityProcess",
                                             Variables.createVariables().putValue("priority", 18));

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(2, WORKER_ID, true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(2, externalTasks.size());

    // then
    //task with no prio gets prio defined by process
    assertEquals(18, externalTasks.get(0).getPriority());
    //task with own prio overrides prio defined by process
    assertEquals(7, externalTasks.get(1).getPriority());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/externalTaskPriorityExpression.bpmn20.xml")
  public void testFetchWithPriorityExpression() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("twoExternalTaskWithPriorityProcess",
                                                        Variables.createVariables().putValue("priority", 18));
    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID, true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then
    assertEquals(1, externalTasks.size());

    LockedExternalTask task = externalTasks.get(0);
    assertNotNull(task.getId());
    assertEquals(processInstance.getId(), task.getProcessInstanceId());
    assertEquals(processInstance.getProcessDefinitionId(), task.getProcessDefinitionId());
    assertEquals("externalTaskWithPrio", task.getActivityId());
    assertEquals("twoExternalTaskWithPriorityProcess", task.getProcessDefinitionKey());
    assertEquals(TOPIC_NAME, task.getTopicName());
    assertEquals(18, task.getPriority());

    ActivityInstance activityInstance = runtimeService
      .getActivityInstance(processInstance.getId())
      .getActivityInstances("externalTaskWithPrio")[0];

    assertEquals(activityInstance.getId(), task.getActivityInstanceId());
    assertEquals(activityInstance.getExecutionIds()[0], task.getExecutionId());

    AssertUtil.assertEqualsSecondPrecision(nowPlus(LOCK_TIME), task.getLockExpirationTime());

    assertEquals(WORKER_ID, task.getWorkerId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskWithPriorityProcess.bpmn20.xml")
  public void testFetchWithPriorityOrdering() {
    // given
    runtimeService.startProcessInstanceByKey("twoExternalTaskWithPriorityProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(2, WORKER_ID, true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then
    assertEquals(2, externalTasks.size());
    assertTrue(externalTasks.get(0).getPriority() > externalTasks.get(1).getPriority());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskWithPriorityProcess.bpmn20.xml")
  public void testFetchNextWithPriority() {
    // given
    runtimeService.startProcessInstanceByKey("twoExternalTaskWithPriorityProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID, true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then the task is locked
    assertEquals(1, externalTasks.size());

    LockedExternalTask task = externalTasks.get(0);
    long firstPrio = task.getPriority();
    AssertUtil.assertEqualsSecondPrecision(nowPlus(LOCK_TIME), task.getLockExpirationTime());

    // another task with next higher priority can be claimed
    externalTasks = externalTaskService.fetchAndLock(1, "anotherWorkerId", true)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();
    assertEquals(1, externalTasks.size());
    assertTrue(firstPrio >= externalTasks.get(0).getPriority());

    // the expiration time expires
    ClockUtil.setCurrentTime(new DateTime(ClockUtil.getCurrentTime()).plus(LOCK_TIME * 2).toDate());

    //first can be claimed
    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID, true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(1, externalTasks.size());
    assertEquals(firstPrio, externalTasks.get(0).getPriority());
  }

  @Deployment
  public void testFetchTopicSelection() {
    // given
    runtimeService.startProcessInstanceByKey("twoTopicsProcess");

    // when
    List<LockedExternalTask> topic1Tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic("topic1", LOCK_TIME)
        .execute();

    List<LockedExternalTask> topic2Tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic("topic2", LOCK_TIME)
        .execute();

    // then
    assertEquals(1, topic1Tasks.size());
    assertEquals("topic1", topic1Tasks.get(0).getTopicName());

    assertEquals(1, topic2Tasks.size());
    assertEquals("topic2", topic2Tasks.get(0).getTopicName());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchWithoutTopicName() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    try {
      externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(null, LOCK_TIME)
        .execute();
      fail("expected exception");
    } catch (ProcessEngineException e) {
      assertTextPresent("topicName is null", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchNullWorkerId() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    try {
      externalTaskService.fetchAndLock(1, null)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();
      fail("expected exception");
    } catch (ProcessEngineException e) {
      assertTextPresent("workerId is null", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchNegativeNumberOfTasks() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    try {
      externalTaskService.fetchAndLock(-1, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();
      fail("expected exception");
    } catch (ProcessEngineException e) {
      assertTextPresent("maxResults is not greater than or equal to 0", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchLessTasksThanExist() {
    // given
    for (int i = 0; i < 10; i++) {
      runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    }

    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    assertEquals(5, externalTasks.size());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchNegativeLockTime() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    try {
      externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, -1L)
        .execute();
      fail("expected exception");
    } catch (ProcessEngineException e) {
      assertTextPresent("lockTime is not greater than 0", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchZeroLockTime() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    try {
      externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, 0L)
        .execute();
      fail("expected exception");
    } catch (ProcessEngineException e) {
      assertTextPresent("lockTime is not greater than 0", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchNoTopics() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .execute();

    // then
    assertEquals(0, tasks.size());
  }

  @Deployment
  public void testFetchVariables() {
    // given
    runtimeService.startProcessInstanceByKey("subProcessExternalTask",
          Variables.createVariables().putValue("processVar1", 42).putValue("processVar2", 43));

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .variables("processVar1", "subProcessVar", "taskVar")
      .execute();

    // then
    LockedExternalTask task = externalTasks.get(0);
    VariableMap variables = task.getVariables();
    assertEquals(3, variables.size());

    assertEquals(42, variables.get("processVar1"));
    assertEquals(44L, variables.get("subProcessVar"));
    assertEquals(45L, variables.get("taskVar"));

  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/ExternalTaskServiceTest.testFetchVariables.bpmn20.xml")
  public void testFetchAllVariables() {
    // given
    runtimeService.startProcessInstanceByKey("subProcessExternalTask",
        Variables.createVariables()
            .putValue("processVar1", 42)
            .putValue("processVar2", 43));

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    // then
    LockedExternalTask task = externalTasks.get(0);
    verifyVariables(task);

    runtimeService.startProcessInstanceByKey("subProcessExternalTask",
        Variables.createVariables()
            .putValue("processVar1", 42)
            .putValue("processVar2", 43));

    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .variables((String[]) null)
        .execute();

    task = externalTasks.get(0);
    verifyVariables(task);

    runtimeService.startProcessInstanceByKey("subProcessExternalTask",
        Variables.createVariables()
            .putValue("processVar1", 42)
            .putValue("processVar2", 43));

    List<String> list = null;
    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .variables(list)
        .execute();

    task = externalTasks.get(0);
    verifyVariables(task);
  }

  private void verifyVariables(LockedExternalTask task) {
    VariableMap variables = task.getVariables();
    assertEquals(4, variables.size());

    assertEquals(42, variables.get("processVar1"));
    assertEquals(43, variables.get("processVar2"));
    assertEquals(44L, variables.get("subProcessVar"));
    assertEquals(45L, variables.get("taskVar"));
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchNonExistingVariable() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .variables("nonExistingVariable")
      .execute();

    LockedExternalTask task = tasks.get(0);

    // then
    assertTrue(task.getVariables().isEmpty());
  }

  @Deployment
  public void testFetchMultipleTopics() {
    // given a process instance with external tasks for topics "topic1", "topic2", and "topic3"
    runtimeService.startProcessInstanceByKey("parallelExternalTaskProcess");

    // when fetching tasks for two topics
    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
      .topic("topic1", LOCK_TIME)
      .topic("topic2", LOCK_TIME * 2)
      .execute();

    // then those two tasks are locked
    assertEquals(2, tasks.size());
    LockedExternalTask topic1Task = "topic1".equals(tasks.get(0).getTopicName()) ? tasks.get(0) : tasks.get(1);
    LockedExternalTask topic2Task = "topic2".equals(tasks.get(0).getTopicName()) ? tasks.get(0) : tasks.get(1);

    assertEquals("topic1", topic1Task.getTopicName());
    AssertUtil.assertEqualsSecondPrecision(nowPlus(LOCK_TIME), topic1Task.getLockExpirationTime());

    assertEquals("topic2", topic2Task.getTopicName());
    AssertUtil.assertEqualsSecondPrecision(nowPlus(LOCK_TIME * 2), topic2Task.getLockExpirationTime());

    // and the third task can still be fetched
    tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
      .topic("topic1", LOCK_TIME)
      .topic("topic2", LOCK_TIME * 2)
      .topic("topic3", LOCK_TIME * 3)
      .execute();

    assertEquals(1, tasks.size());

    LockedExternalTask topic3Task = tasks.get(0);
    assertEquals("topic3", topic3Task.getTopicName());
    AssertUtil.assertEqualsSecondPrecision(nowPlus(LOCK_TIME * 3), topic3Task.getLockExpirationTime());
  }

  @Deployment
  public void testFetchMultipleTopicsWithVariables() {
    // given a process instance with external tasks for topics "topic1" and "topic2"
    // both have local variables "var1" and "var2"
    runtimeService.startProcessInstanceByKey("parallelExternalTaskProcess",
        Variables.createVariables().putValue("var1", 0).putValue("var2", 0));

    // when
    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
      .topic("topic1", LOCK_TIME).variables("var1", "var2")
      .topic("topic2", LOCK_TIME).variables("var1")
      .execute();

    LockedExternalTask topic1Task = "topic1".equals(tasks.get(0).getTopicName()) ? tasks.get(0) : tasks.get(1);
    LockedExternalTask topic2Task = "topic2".equals(tasks.get(0).getTopicName()) ? tasks.get(0) : tasks.get(1);

    assertEquals("topic1", topic1Task.getTopicName());
    assertEquals("topic2", topic2Task.getTopicName());

    // then the correct variables have been fetched
    VariableMap topic1Variables = topic1Task.getVariables();
    assertEquals(2, topic1Variables.size());
    assertEquals(1L, topic1Variables.get("var1"));
    assertEquals(1L, topic1Variables.get("var2"));

    VariableMap topic2Variables = topic2Task.getVariables();
    assertEquals(1, topic2Variables.size());
    assertEquals(2L, topic2Variables.get("var1"));

  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/ExternalTaskServiceTest.testFetchMultipleTopics.bpmn20.xml")
  public void testFetchMultipleTopicsMaxTasks() {
    // given
    for (int i = 0; i < 10; i++) {
      runtimeService.startProcessInstanceByKey("parallelExternalTaskProcess");
    }

    // when
    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic("topic1", LOCK_TIME)
        .topic("topic2", LOCK_TIME)
        .topic("topic3", LOCK_TIME)
        .execute();

    // then 5 tasks were returned in total, not per topic
    assertEquals(5, tasks.size());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchSuspendedTask() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when suspending the process instance
    runtimeService.suspendProcessInstanceById(processInstance.getId());

    // then the external task cannot be fetched
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    assertEquals(0, externalTasks.size());

    // when activating the process instance
    runtimeService.activateProcessInstanceById(processInstance.getId());

    // then the task can be fetched
    externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    assertEquals(1, externalTasks.size());
  }

  /**
   * Note: this does not test a hard API guarantee, i.e. the test is stricter than the API (Javadoc).
   * Its purpose is to ensure that the API implementation is less error-prone to use.
   *
   * Bottom line: if there is good reason to change behavior such that this test breaks, it may
   * be ok to change the test.
   */
  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testFetchAndLockWithInitialBuilder() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    ExternalTaskQueryBuilder initialBuilder = externalTaskService.fetchAndLock(1, WORKER_ID);
    initialBuilder.topic(TOPIC_NAME, LOCK_TIME);

    // should execute regardless whether the initial builder is used or the builder returned by the
    // #topic invocation
    List<LockedExternalTask> tasks = initialBuilder.execute();

    // then
    assertEquals(1, tasks.size());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskProcess.bpmn20.xml")
  public void testComplete() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("twoExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    externalTaskService.complete(externalTasks.get(0).getId(), WORKER_ID);

    // then
    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(0, externalTasks.size());

    ActivityInstance activityInstance = runtimeService.getActivityInstance(processInstance.getId());
    assertThat(activityInstance).hasStructure(
        describeActivityInstanceTree(processInstance.getProcessDefinitionId())
          .activity("afterExternalTask")
        .done());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskProcess.bpmn20.xml")
  public void testCompleteWithVariables() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("twoExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    externalTaskService.complete(
        externalTasks.get(0).getId(),
        WORKER_ID,
        Variables.createVariables().putValue("var", 42));

    // then
    ActivityInstance activityInstance = runtimeService.getActivityInstance(processInstance.getId());
    assertThat(activityInstance).hasStructure(
        describeActivityInstanceTree(processInstance.getProcessDefinitionId())
          .activity("afterExternalTask")
        .done());

    assertEquals(42, runtimeService.getVariable(processInstance.getId(), "var"));
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskProcess.bpmn20.xml")
  public void testCompleteWithWrongWorkerId() {
    // given
    runtimeService.startProcessInstanceByKey("twoExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then it is not possible to complete the task with a different worker id
    try {
      externalTaskService.complete(externalTasks.get(0).getId(), "someCrazyWorkerId");
      fail("exception expected");
    } catch (BadUserRequestException e) {
      assertTextPresent("cannot be completed by worker 'someCrazyWorkerId'. It is locked by worker '" + WORKER_ID + "'.", e.getMessage());
    }
  }

  public void testCompleteNonExistingTask() {
    try {
      externalTaskService.complete("nonExistingTaskId", WORKER_ID);
      fail("exception expected");
    } catch (NotFoundException e) {
      // not found exception lets client distinguish this from other failures
      assertTextPresent("Cannot find external task with id nonExistingTaskId", e.getMessage());
    }
  }

  public void testCompleteNullTaskId() {
    try {
      externalTaskService.complete(null, WORKER_ID);
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("Cannot find external task with id " + null, e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testCompleteNullWorkerId() {
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    LockedExternalTask task = tasks.get(0);

    try {
      externalTaskService.complete(task.getId(), null);
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("workerId is null", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testCompleteSuspendedTask() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    LockedExternalTask task = externalTasks.get(0);

    // when suspending the process instance
    runtimeService.suspendProcessInstanceById(processInstance.getId());

    // then the external task cannot be completed
    try {
      externalTaskService.complete(task.getId(), WORKER_ID);
      fail("expected exception");
    } catch (ProcessEngineException e) {
      assertTextPresent("ExternalTask with id '" + task.getId() + "' is suspended", e.getMessage());
    }

    assertProcessNotEnded(processInstance.getId());

    // when activating the process instance again
    runtimeService.activateProcessInstanceById(processInstance.getId());

    // then the task can be completed
    externalTaskService.complete(task.getId(), WORKER_ID);

    assertProcessEnded(processInstance.getId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testLocking() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then the task is locked
    assertEquals(1, externalTasks.size());

    LockedExternalTask task = externalTasks.get(0);
    AssertUtil.assertEqualsSecondPrecision(nowPlus(LOCK_TIME), task.getLockExpirationTime());

    // and cannot be retrieved by another query
    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();
    assertEquals(0, externalTasks.size());

    // unless the expiration time expires
    ClockUtil.setCurrentTime(new DateTime(ClockUtil.getCurrentTime()).plus(LOCK_TIME * 2).toDate());

    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(1, externalTasks.size());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testCompleteLockExpiredTask() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // and the lock expires without the task being reclaimed
    ClockUtil.setCurrentTime(new DateTime(ClockUtil.getCurrentTime()).plus(LOCK_TIME * 2).toDate());

    // then the task can successfully be completed
    externalTaskService.complete(externalTasks.get(0).getId(), WORKER_ID);

    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(0, externalTasks.size());
    assertProcessEnded(processInstance.getId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testCompleteReclaimedLockExpiredTask() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // and the lock expires
    ClockUtil.setCurrentTime(new DateTime(ClockUtil.getCurrentTime()).plus(LOCK_TIME * 2).toDate());

    // and it is reclaimed by another worker
    List<LockedExternalTask> reclaimedTasks = externalTaskService.fetchAndLock(1, "anotherWorkerId")
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then the first worker cannot complete the task
    try {
      externalTaskService.complete(externalTasks.get(0).getId(), WORKER_ID);
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("cannot be completed by worker '" + WORKER_ID + "'. It is locked by worker 'anotherWorkerId'.", e.getMessage());
    }

    // and the second worker can
    externalTaskService.complete(reclaimedTasks.get(0).getId(), "anotherWorkerId");

    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(0, externalTasks.size());
    assertProcessEnded(processInstance.getId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testDeleteProcessInstance() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    runtimeService.deleteProcessInstance(processInstance.getId(), null);

    // then
    assertEquals(0, externalTaskService.fetchAndLock(5, WORKER_ID).topic(TOPIC_NAME, LOCK_TIME).execute().size());
    assertProcessEnded(processInstance.getId());
  }

  @Deployment
  public void testExternalTaskExecutionTreeExpansion() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("boundaryExternalTaskProcess");

    List<LockedExternalTask> tasks = externalTaskService
      .fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    LockedExternalTask externalTask = tasks.get(0);

    // when a non-interrupting boundary event is triggered meanwhile
    // such that the execution tree is expanded
    runtimeService.correlateMessage("Message");

    // then the external task can still be completed
    externalTaskService.complete(externalTask.getId(), WORKER_ID);

    ActivityInstance activityInstance = runtimeService.getActivityInstance(processInstance.getId());
    assertThat(activityInstance).hasStructure(
        describeActivityInstanceTree(processInstance.getProcessDefinitionId())
          .activity("afterBoundaryTask")
        .done());

    Task afterBoundaryTask = taskService.createTaskQuery().singleResult();
    taskService.complete(afterBoundaryTask.getId());

    assertProcessEnded(processInstance.getId());
  }

  @Deployment
  public void testExternalTaskExecutionTreeCompaction() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("concurrentExternalTaskProcess");

    List<LockedExternalTask> tasks = externalTaskService
      .fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    LockedExternalTask externalTask = tasks.get(0);

    Task userTask = taskService.createTaskQuery().singleResult();

    // when the user task completes meanwhile, thereby trigger execution tree compaction
    taskService.complete(userTask.getId());

    // then the external task can still be completed
    externalTaskService.complete(externalTask.getId(), WORKER_ID);

    tasks = externalTaskService
        .fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();
    assertEquals(0, tasks.size());

    assertProcessEnded(processInstance.getId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testUnlock() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    LockedExternalTask task = externalTasks.get(0);

    // when unlocking the task
    externalTaskService.unlock(task.getId());

    // then it can be acquired again
    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    assertEquals(1, externalTasks.size());
    LockedExternalTask reAcquiredTask = externalTasks.get(0);
    assertEquals(task.getId(), reAcquiredTask.getId());
  }

  public void testUnlockNullTaskId() {
    try {
      externalTaskService.unlock(null);
      fail("expected exception");
    } catch (ProcessEngineException e) {
      assertTextPresent("externalTaskId is null", e.getMessage());
    }
  }

  public void testUnlockNonExistingTask() {
    try {
      externalTaskService.unlock("nonExistingId");
      fail("expected exception");
    } catch (NotFoundException e) {
      // not found exception lets client distinguish this from other failures
      assertTextPresent("Cannot find external task with id nonExistingId", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailure() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    LockedExternalTask task = tasks.get(0);

    // when submitting a failure (after a simulated processing time of three seconds)
    ClockUtil.setCurrentTime(nowPlus(3000L));

    String errorMessage = "errorMessage";
    externalTaskService.handleFailure(task.getId(), WORKER_ID, errorMessage, 5, 3000L);

    // then the task cannot be immediately acquired again
    tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();
    assertEquals(0, tasks.size());

    // and no incident exists because there are still retries left
    assertEquals(0, runtimeService.createIncidentQuery().count());

    // but when the retry time expires, the task is available again
    ClockUtil.setCurrentTime(nowPlus(4000L));

    tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();
    assertEquals(1, tasks.size());

    // and the retries and error message are accessible
    task = tasks.get(0);
    assertEquals(errorMessage, task.getErrorMessage());
    assertEquals(5, (int) task.getRetries());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureWithErrorDetails() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    LockedExternalTask task = tasks.get(0);

    // when submitting a failure (after a simulated processing time of three seconds)
    ClockUtil.setCurrentTime(nowPlus(3000L));

    String errorMessage;
    String exceptionStackTrace;
    try {
      RuntimeSqlException cause = new RuntimeSqlException("test cause");
      for (int i = 0; i < 10; i++) {
        cause = new RuntimeSqlException(cause);
      }
      throw cause;
    } catch (RuntimeException e) {
      exceptionStackTrace = ExceptionUtils.getStackTrace(e);
      errorMessage = e.getMessage();
      while (errorMessage.length() < 1000) {
        errorMessage = errorMessage + ":" + e.getMessage();
      }
    }
    Assert.assertThat(exceptionStackTrace,is(notNullValue()));
//  make sure that stack trace is longer then errorMessage DB field length
    Assert.assertThat(exceptionStackTrace.length(),is(greaterThan(4000)));
    externalTaskService.handleFailure(task.getId(), WORKER_ID, errorMessage, exceptionStackTrace, 5, 3000L);
    ClockUtil.setCurrentTime(nowPlus(4000L));
    tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();
    Assert.assertThat(tasks.size(), is(1));

    // verify that exception is accessible properly
    task = tasks.get(0);
    Assert.assertThat(task.getErrorMessage(),is(errorMessage.substring(0,666)));
    Assert.assertThat(task.getRetries(),is(5));
    Assert.assertThat(externalTaskService.getExternalTaskErrorDetails(task.getId()),is(exceptionStackTrace));
    Assert.assertThat(task.getErrorDetails(),is(exceptionStackTrace));
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureZeroRetries() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    LockedExternalTask task = tasks.get(0);

    // when reporting a failure and setting retries to 0
    ClockUtil.setCurrentTime(nowPlus(3000L));

    String errorMessage = "errorMessage";
    externalTaskService.handleFailure(task.getId(), WORKER_ID, errorMessage, 0, 3000L);

    // then the task cannot be fetched anymore even when the lock expires
    ClockUtil.setCurrentTime(nowPlus(4000L));

    tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();
    assertEquals(0, tasks.size());

    // and an incident has been created
    Incident incident = runtimeService.createIncidentQuery().singleResult();

    assertNotNull(incident);
    assertNotNull(incident.getId());
    assertEquals(errorMessage, incident.getIncidentMessage());
    assertEquals(task.getExecutionId(), incident.getExecutionId());
    assertEquals("externalTask", incident.getActivityId());
    assertEquals(incident.getId(), incident.getCauseIncidentId());
    assertEquals("failedExternalTask", incident.getIncidentType());
    assertEquals(task.getProcessDefinitionId(), incident.getProcessDefinitionId());
    assertEquals(task.getProcessInstanceId(), incident.getProcessInstanceId());
    assertEquals(incident.getId(), incident.getRootCauseIncidentId());
    AssertUtil.assertEqualsSecondPrecision(nowMinus(4000L), incident.getIncidentTimestamp());
    assertEquals(task.getId(), incident.getConfiguration());
    assertNull(incident.getJobDefinitionId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureAndDeleteProcessInstance() {
    // given a failed external task with incident
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    LockedExternalTask task = tasks.get(0);

    externalTaskService.handleFailure(task.getId(), WORKER_ID, "someError", 0, LOCK_TIME);

    // when
    runtimeService.deleteProcessInstance(processInstance.getId(), null);

    // then
    assertProcessEnded(processInstance.getId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureThenComplete() {
    // given a failed external task with incident
    runtimeService.startProcessInstanceByKey("twoExternalTaskProcess");

    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(5, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    LockedExternalTask task = tasks.get(0);

    externalTaskService.handleFailure(task.getId(), WORKER_ID, "someError", 0, LOCK_TIME);

    // when
    externalTaskService.complete(task.getId(), WORKER_ID);

    // then the task has been completed nonetheless
    Task followingTask = taskService.createTaskQuery().singleResult();
    assertNotNull(followingTask);
    assertEquals("afterExternalTask", followingTask.getTaskDefinitionKey());

  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureWithWrongWorkerId() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then it is not possible to complete the task with a different worker id
    try {
      externalTaskService.handleFailure(externalTasks.get(0).getId(), "someCrazyWorkerId", "error", 5, LOCK_TIME);
      fail("exception expected");
    } catch (BadUserRequestException e) {
      assertTextPresent("Failure of External Task " + externalTasks.get(0).getId()
          + " cannot be reported by worker 'someCrazyWorkerId'. It is locked by worker '" + WORKER_ID + "'.",
        e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureNonExistingTask() {
    try {
      externalTaskService.handleFailure("nonExistingTaskId", WORKER_ID, "error", 5, LOCK_TIME);
      fail("exception expected");
    } catch (NotFoundException e) {
      // not found exception lets client distinguish this from other failures
      assertTextPresent("Cannot find external task with id nonExistingTaskId", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureNullTaskId() {
    try {
      externalTaskService.handleFailure(null, WORKER_ID, "error", 5, LOCK_TIME);
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("Cannot find external task with id " + null, e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureNullWorkerId() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then
    try {
      externalTaskService.handleFailure(externalTasks.get(0).getId(), null, "error", 5, LOCK_TIME);
      fail("exception expected");
    } catch (NullValueException e) {
      assertTextPresent("workerId is null", e.getMessage());
    }

  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureNegativeLockDuration() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then
    try {
      externalTaskService.handleFailure(externalTasks.get(0).getId(), WORKER_ID, "error", 5, - LOCK_TIME);
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("retryDuration is not greater than or equal to 0", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureNegativeRetries() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then
    try {
      externalTaskService.handleFailure(externalTasks.get(0).getId(), WORKER_ID, "error", -5, LOCK_TIME);
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("retries is not greater than or equal to 0", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureNullErrorMessage() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // when
    externalTaskService.handleFailure(externalTasks.get(0).getId(), WORKER_ID, null, 5, LOCK_TIME);

    // then the failure was reported successfully and the error message is null
    ExternalTask task = externalTaskService.createExternalTaskQuery().singleResult();

    assertEquals(5, (int) task.getRetries());
    assertNull(task.getErrorMessage());
    assertNull(externalTaskService.getExternalTaskErrorDetails(task.getId()));
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleFailureSuspendedTask() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    LockedExternalTask task = externalTasks.get(0);

    // when suspending the process instance
    runtimeService.suspendProcessInstanceById(processInstance.getId());

    // then a failure cannot be reported
    try {
      externalTaskService.handleFailure(externalTasks.get(0).getId(), WORKER_ID, "error", 5, LOCK_TIME);
      fail("expected exception");
    } catch (ProcessEngineException e) {
      assertTextPresent("ExternalTask with id '" + task.getId() + "' is suspended", e.getMessage());
    }

    assertProcessNotEnded(processInstance.getId());

    // when activating the process instance again
    runtimeService.activateProcessInstanceById(processInstance.getId());

    // then the failure can be reported successfully
    externalTaskService.handleFailure(externalTasks.get(0).getId(), WORKER_ID, "error", 5, LOCK_TIME);

    ExternalTask updatedTask = externalTaskService.createExternalTaskQuery().singleResult();
    assertEquals(5, (int) updatedTask.getRetries());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testSetRetries() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    // when
    externalTaskService.setRetries(externalTasks.get(0).getId(), 5);

    // then
    ExternalTask task = externalTaskService.createExternalTaskQuery().singleResult();

    assertEquals(5, (int) task.getRetries());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testSetRetriesResolvesFailureIncident() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    LockedExternalTask lockedTask = externalTasks.get(0);
    externalTaskService.handleFailure(lockedTask.getId(), WORKER_ID, "error", 0, LOCK_TIME);

    Incident incident = runtimeService.createIncidentQuery().singleResult();

    // when
    externalTaskService.setRetries(lockedTask.getId(), 5);

    // then the incident is resolved
    assertEquals(0, runtimeService.createIncidentQuery().count());

    if (processEngineConfiguration.getHistoryLevel().getId() >= HistoryLevel.HISTORY_LEVEL_FULL.getId()) {

      HistoricIncident historicIncident = historyService.createHistoricIncidentQuery().singleResult();
      assertNotNull(historicIncident);
      assertEquals(incident.getId(), historicIncident.getId());
      assertTrue(historicIncident.isResolved());
    }

    // and the task can be fetched again
    ClockUtil.setCurrentTime(nowPlus(LOCK_TIME + 3000L));

    externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    assertEquals(1, externalTasks.size());
    assertEquals(lockedTask.getId(), externalTasks.get(0).getId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testSetRetriesToZero() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    LockedExternalTask lockedTask = externalTasks.get(0);

    // when
    externalTaskService.setRetries(lockedTask.getId(), 0);

    // then
    Incident incident = runtimeService.createIncidentQuery().singleResult();
    assertNotNull(incident);
    assertEquals(lockedTask.getId(), incident.getConfiguration());

    // and resetting the retries removes the incident again
    externalTaskService.setRetries(lockedTask.getId(), 5);

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

  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testSetRetriesNegative() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    try {
      // when
      externalTaskService.setRetries(externalTasks.get(0).getId(), -5);
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("retries is not greater than or equal to 0", e.getMessage());
    }
  }

  public void testSetRetriesNonExistingTask() {
    try {
      externalTaskService.setRetries("someExternalTaskId", 5);
      fail("expected exception");
    } catch (NotFoundException e) {
      // not found exception lets client distinguish this from other failures
      assertTextPresent("externalTask is null", e.getMessage());
    }
  }

  public void testSetRetriesNullTaskId() {
    try {
      externalTaskService.setRetries(null, 5);
      fail("expected exception");
    } catch (NullValueException e) {
      assertTextPresent("externalTaskId is null", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testSetPriority() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    // when
    externalTaskService.setPriority(externalTasks.get(0).getId(), 5);

    // then
    ExternalTask task = externalTaskService.createExternalTaskQuery().singleResult();

    assertEquals(5, (int) task.getPriority());
  }

  public void testSetPriorityNonExistingTask() {
    try {
      externalTaskService.setPriority("someExternalTaskId", 5);
      fail("expected exception");
    } catch (NotFoundException e) {
      // not found exception lets client distinguish this from other failures
      assertTextPresent("externalTask is null", e.getMessage());
    }
  }

  public void testSetPriorityNullTaskId() {
    try {
      externalTaskService.setPriority(null, 5);
      fail("expected exception");
    } catch (NullValueException e) {
      assertTextPresent("externalTaskId is null", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskWithPriorityProcess.bpmn20.xml")
  public void testAfterSetPriorityFetchHigherTask() {
    // given
    runtimeService.startProcessInstanceByKey("twoExternalTaskWithPriorityProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(2, WORKER_ID, true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(2, externalTasks.size());
    LockedExternalTask task = externalTasks.get(1);
    assertEquals(0, task.getPriority());
    externalTaskService.setPriority(task.getId(), 9);
    // and the lock expires without the task being reclaimed
    ClockUtil.setCurrentTime(new DateTime(ClockUtil.getCurrentTime()).plus(LOCK_TIME * 2).toDate());

    // then
    externalTasks = externalTaskService.fetchAndLock(1, "anotherWorkerId", true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(externalTasks.get(0).getPriority(), 9);
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testSetPriorityLockExpiredTask() {
    // given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // and the lock expires without the task being reclaimed
    ClockUtil.setCurrentTime(new DateTime(ClockUtil.getCurrentTime()).plus(LOCK_TIME * 2).toDate());

    // then the priority can be set
    externalTaskService.setPriority(externalTasks.get(0).getId(), 9);

    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID, true)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(1, externalTasks.size());
    assertEquals(externalTasks.get(0).getPriority(), 9);
  }

  @Deployment
  public void testCancelExternalTaskWithBoundaryEvent() {
    // given
    runtimeService.startProcessInstanceByKey("boundaryExternalTaskProcess");
    assertEquals(1, externalTaskService.createExternalTaskQuery().count());

    // when the external task is cancelled by a boundary event
    runtimeService.correlateMessage("Message");

    // then the external task instance has been removed
    assertEquals(0, externalTaskService.createExternalTaskQuery().count());

    Task afterBoundaryTask = taskService.createTaskQuery().singleResult();
    assertNotNull(afterBoundaryTask);
    assertEquals("afterBoundaryTask", afterBoundaryTask.getTaskDefinitionKey());

  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskProcess.bpmn20.xml")
  public void testHandleBpmnError() {
    //given
    runtimeService.startProcessInstanceByKey("twoExternalTaskProcess");
    // when
    List<LockedExternalTask> externalTasks = helperHandleBpmnError(1, WORKER_ID, TOPIC_NAME, LOCK_TIME,  "ERROR-OCCURED");
    //then
    assertEquals(0, externalTasks.size());
    assertEquals(0, externalTaskService.createExternalTaskQuery().count());
    Task afterBpmnError = taskService.createTaskQuery().singleResult();
    assertNotNull(afterBpmnError);
    assertEquals(afterBpmnError.getTaskDefinitionKey(), "afterBpmnError");
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleBpmnErrorWithoutDefinedBoundary() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    //when
    List<LockedExternalTask> externalTasks = helperHandleBpmnError(1, WORKER_ID, TOPIC_NAME, LOCK_TIME,  "ERROR-OCCURED");

    //then
    assertEquals(0, externalTasks.size());
    assertEquals(0, externalTaskService.createExternalTaskQuery().count());
    Task afterBpmnError = taskService.createTaskQuery().singleResult();
    assertNull(afterBpmnError);
    assertProcessEnded(processInstance.getId());
  }

  /**
   * Helper method to handle a bmpn error on an external task, which is fetched with the given parameters.
   *
   * @param taskCount the count of task to fetch
   * @param workerID the worker id
   * @param topicName the topic name of the external task
   * @param lockTime the lock time for the fetch
   * @param errorCode the error code of the bpmn error
   * @return returns the locked external tasks after the bpmn error was handled
   */
  public  List<LockedExternalTask> helperHandleBpmnError(int taskCount, String workerID, String topicName, long lockTime, String errorCode) {
    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(taskCount, workerID)
      .topic(topicName, lockTime)
      .execute();

    externalTaskService.handleBpmnError(externalTasks.get(0).getId(), workerID, errorCode);

    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    return externalTasks;
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskProcess.bpmn20.xml")
  public void testHandleBpmnErrorLockExpiredTask() {
    //given
    runtimeService.startProcessInstanceByKey("twoExternalTaskProcess");
    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // and the lock expires without the task being reclaimed
    ClockUtil.setCurrentTime(new DateTime(ClockUtil.getCurrentTime()).plus(LOCK_TIME * 2).toDate());

    externalTaskService.handleBpmnError(externalTasks.get(0).getId(), WORKER_ID, "ERROR-OCCURED");

    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    assertEquals(0, externalTasks.size());
    assertEquals(0, externalTaskService.createExternalTaskQuery().count());
    Task afterBpmnError = taskService.createTaskQuery().singleResult();
    assertNotNull(afterBpmnError);
    assertEquals(afterBpmnError.getTaskDefinitionKey(), "afterBpmnError");
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleBpmnErrorReclaimedLockExpiredTaskWithoutDefinedBoundary() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    handleBpmnErrorReclaimedLockExpiredTask();
    assertProcessEnded(processInstance.getId());
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/twoExternalTaskProcess.bpmn20.xml")
  public void testHandleBpmnErrorReclaimedLockExpiredTaskWithBoundary() {
    // given
    runtimeService.startProcessInstanceByKey("twoExternalTaskProcess");
    //then
    handleBpmnErrorReclaimedLockExpiredTask();
  }

  /**
   * Helpher method which reclaims an external task after the lock is expired.
   */
  public void handleBpmnErrorReclaimedLockExpiredTask() {
    // when
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // and the lock expires
    ClockUtil.setCurrentTime(new DateTime(ClockUtil.getCurrentTime()).plus(LOCK_TIME * 2).toDate());

    // and it is reclaimed by another worker
    List<LockedExternalTask> reclaimedTasks = externalTaskService.fetchAndLock(1, "anotherWorkerId")
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();

    // then the first worker cannot complete the task
    try {
      externalTaskService.handleBpmnError(externalTasks.get(0).getId(), WORKER_ID, "ERROR-OCCURED");
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("Bpmn error of External Task " + externalTasks.get(0).getId() + " cannot be reported by worker '" + WORKER_ID + "'. It is locked by worker 'anotherWorkerId'.", e.getMessage());
    }

    // and the second worker can
    externalTaskService.complete(reclaimedTasks.get(0).getId(), "anotherWorkerId");

    externalTasks = externalTaskService.fetchAndLock(1, WORKER_ID)
      .topic(TOPIC_NAME, LOCK_TIME)
      .execute();
    assertEquals(0, externalTasks.size());
  }

  public void testHandleBpmnErrorNonExistingTask() {
    try {
      externalTaskService.handleBpmnError("nonExistingTaskId", WORKER_ID, "ERROR-OCCURED");
      fail("exception expected");
    } catch (NotFoundException e) {
      // not found exception lets client distinguish this from other failures
      assertTextPresent("Cannot find external task with id nonExistingTaskId", e.getMessage());
    }
  }

  public void testHandleBpmnNullTaskId() {
    try {
      externalTaskService.handleBpmnError(null, WORKER_ID, "ERROR-OCCURED");
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("Cannot find external task with id " + null, e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleBpmnNullErrorCode() {
    //given
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    //when
    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    //then
    LockedExternalTask task = tasks.get(0);
    try {
      externalTaskService.handleBpmnError(task.getId(), WORKER_ID, null);
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("errorCode is null", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleBpmnErrorNullWorkerId() {
    runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");

    List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(1, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    LockedExternalTask task = tasks.get(0);

    try {
      externalTaskService.handleBpmnError(task.getId(), null,"ERROR-OCCURED");
      fail("exception expected");
    } catch (ProcessEngineException e) {
      assertTextPresent("workerId is null", e.getMessage());
    }
  }

  @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml")
  public void testHandleBpmnErrorSuspendedTask() {
    // given
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess");
    List<LockedExternalTask> externalTasks = externalTaskService.fetchAndLock(5, WORKER_ID)
        .topic(TOPIC_NAME, LOCK_TIME)
        .execute();

    LockedExternalTask task = externalTasks.get(0);

    // when suspending the process instance
    runtimeService.suspendProcessInstanceById(processInstance.getId());

    // then the external task cannot be completed
    try {
      externalTaskService.handleBpmnError(task.getId(), WORKER_ID, "ERROR-OCCURED");
      fail("expected exception");
    } catch (ProcessEngineException e) {
      assertTextPresent("ExternalTask with id '" + task.getId() + "' is suspended", e.getMessage());
    }
  }

  protected Date nowPlus(long millis) {
    return new Date(ClockUtil.getCurrentTime().getTime() + millis);
  }

  protected Date nowMinus(long millis) {
    return new Date(ClockUtil.getCurrentTime().getTime() - millis);
  }
}

redpajama_set_name: RedPajamaGithub


Country Treks is a sister company to Top Adventures. For Pony Camp our children use the log cabins located adjacent to the house, with a separate Teenagers cabin and for our younger members the rooms are located in the main block.
Unlike most adventure centres we only take one residential booking on each of our sites at any time. This means you get sole use of all the facilities on each site without the worry of other users.
The main centre is based in the village of Stottesdon, with the main building dating from 1830. The property has been in the owners' family since 1966 and is still the home to the owners and their family. This is where the centre has its office and is the home to its team of permanent staff.
The centre has a permanent chef who prides himself in delicious home cooked meals and our adults in particular always want to take him home!
The main site also offers a large hall for games/meetings, 3 acres of grounds, a drying room, tuck and souvenir shop.
The main site also houses a newly equipped training room with state of the art media and audio-visual facilities. This can be used by groups, for meetings and closed courses.
Normal residential bookings run from a Monday to a Friday or a weekend. We can also offer short breaks.


Aloha! My name is Aram. I'm a designer, teacher, and entrepreneur on Maui. I was an interaction designer at IDEO, then taught design thinking to executives in Hong Kong at the Fung Academy, and now have returned to Maui to work with local educators, students, and entrepreneurs on innovation (design thinking) and digital literacy.
How might we create awareness around safe drinking water in the classroom with scientific inquiry and easily available sensor technology?


vertical roller mill in cement industry for sale, wholesale various high quality vertical roller mill in cement industry for sale products from global vertical roller mill in cement industry for sale suppliers and vertical roller mill in cement industry for sale factory,importer,exporter at alibaba.com.
grinding mill for cement production · in all these products production, cement mill will be used, raymond vertical cement grinding mill design in india for sale the famous vertical cement .
vertical cement mill for sale – grinding mill china. vertical cement mill for sale mill china. vertical cement roller mill for sale – rock crusher vertical cement grinding mill design in india for sale.
nelson mach . unuesd vertical cement mill for sale specializing in the sale of second hand cement plant equipment, and complete used cement plants.
purchase new and used vertical mill or milling machines for sale commonly referred to as a new vertical knee mill, bridgeport mill, used vertical knee mill, new bridgeport mill, used vertical milling machine, used knee mill, new knee mill are for sale at worldwide machine tool.
how they work. scarifiers, also called surface planers or milling machines, remove concrete faster and more aggressively than grinders. that's because they use the pummeling action of multi tipped cutting wheels, or flails, that rotate at high speeds to chip away at the concrete surface.


Regarding transport investments, the Connecting Europe Facility (CEF) has been recognised as delivering European added value and the EU continues to invest in connectivity and in connecting Europe.
The future programme will deliver connected, smart, sustainable, inclusive, safe and secure mobility. The proposed budget for CEF Transport is €30.6 billion including a general envelope of €12.8 bn, and a cohesion fund allocation of €11.3 bn. In addition, the Commission proposes that the Union enhance its strategic transport infrastructures to make them fit for military mobility. A dedicated budget of €6.5 billion is foreseen through the Connecting Europe Facility.


text:
Einosuke Moriyama (森山 栄之助, Nagasaki, 10 juli 1820 – aldaar, 4 mei 1872) was samoerai in de tijd van het Tokugawa-shogunaat. In Nagasaki was hij een van de beste Hollandse tolken. Hij speelde een hoofdrol in de overgang van het Nederlands naar het Engels als belangrijkste taal in het contact van Japan met de buitenwereld.

Moriyama leerde Nederlands en vernederlandst Engels van de Nederlanders op Dejima. Eind 1848, begin 1849 leerde hij Amerikaans Engels spreken van de eerste native speaker van die taal in Japan, Ranald MacDonald, een walvisvaarder die zich met opzet had laten stranden in het hoge noorden van Japan en als gevangene naar Nagasaki was overgebracht.

Als "Chief Dutch Interpreter" werd Moriyama vervolgens een van de belangrijkste, zo niet dé belangrijkste tolk tijdens de onderhandelingen tussen de commodore Matthew Calbraith Perry van de Verenigde Staten van Amerika en vertegenwoordigers van het Tokugawa-shogunaat in 1854 over de opening van Japan voor de buitenwereld, met name voor de Verenigde Staten van Amerika.

In de jaren vijftig van de negentiende eeuw speelde Moriyama voorts een belangrijke rol in besprekingen met vertegenwoordigers van Rusland en het Verenigd Koninkrijk. In 1862 was hij lid van de eerste Japanse missie naar Europa.

Moriyama is begraven bij de Honrenji-tempel in Nagasaki, maar zijn resten zijn later overgebracht naar de Honmyō-ji-tempel in Tokio. De grafsteen in Nagasaki is niet verwijderd. Het graf in Tokio wordt door zijn familie in ere gehouden als, ten onrechte, het graf van 'Japans eerste tolk'.

Einosuke
Persoon in de 19e eeuw
Japans-Nederlandse betrekkingen
Tolk

redpajama_set_name: RedPajamaWikipedia


Spotless, bright, gorgeous south facing views await you in this very spacious 1 owner suite located in the Casa Bella Complex. This wonderful suite offers a 17 x 12 master bedroom suite, 9 ft ceilings, oversized windows overlooking landscaped tranquil gardens, Olympic Mountains, serenity pond, two water features and meandering walking paths. Top quality features include 6 appliances with Kitchen Aid stainless steel appliances in kitchen, full size front loading washer and dryer, granite counter tops, fireplace, and more. Free gym access in the separate gym with 18 ft glass windows and vaulted ceilings with beautiful views of the park like setting. Private and community function room. Underground secure parking and storage, close to all amenities yet in a quiet residential area away from busy streets. This is an awesome suite come see for yourself.


text:
When Was the Apostasy?
by Administration | Jan 6, 2014 | 8 comments
by David W. T. Brattston
The State of the Question ((Except where otherwise indicated, all patristic quotations are as translated in The Ante-Nicene Fathers: Translations of the Writings of the Fathers down to A.D. 325 ed. Alexander Roberts and James Donaldson. American Reprint of the Edinburgh ed. by A. Cleveland Coxe (Buffalo, N.Y.: Christian Literature Publishing Co., 1885-96; continuously reprinted Edinburgh: T & T Clark; Grand Rapids, Mich.: Wm. B. Eerdmans; Peabody, Mass.: Hendrickson), herein abbreviated "ANF".
Quotations from Eusebius Ecclesiastical History are as translated in Nicene and Post-Nicene Fathers Second Series vol. 1 (New York: Christian Literature Co.; Oxford and London: Parker, 1890; reprinted Edinburgh: T & T Clark; Grand Rapids, MI: Eerdmans, l986).))
"Aha! Aha! Apostasy!" Television and the internet abound with people who claim to find the fulfillment of Bible prophecies in our day, including the apostasy or falling away from Christianity predicted in Matthew 24.10 and 2 Thessalonians 2.3. Many such people identify as apostasy any recent changes in the church do not like, especially ones initiated by Christian leaders of whom they are envious.
In teaching about the Second Coming of Jesus and the end of the world, 2 Thessalonians 2.3 prophesies: "that day shall not come, except there come a falling away first, and that man of sin be revealed, the son of perdition", i.e. the Antichrist. Matthew 24.10 is to a similar effect. Some Christians are ever ready to point to the deeds of other Christians in their own times and categorize them as this falling away. In identifying the supposed fulfillment of these and other Bible prophecies, these people say they read with the Scriptures in one hand and a newspaper in the other. This is probably true; it is certain they do not use a history book. They assume—without considering that there may be equally valid alternatives—that all end-times prophecies will be fulfilled in their own eras, e.g. the twenty-first century for the current crop of televangelists, tract writers, and internet preachers. Not knowing church history, they do not avert to the possibility that such prophecies may have been fulfilled in the past, even centuries ago. Based on nothing more than unconscious assumption, they believe New Testament predictions can relate only to the present day. My opinion is that fulfillment in early Christian centuries is more in keeping with the doctrine that Scripture is a message to all humanity in all time periods, and gives Christians in every age something to point back to as the realization of prophecy and therefore a confirmation of their faith. In interpreting events, we should look for an early date in church history, instead of implying that passages of Holy Writ held no meaning and were beyond the understanding of believers for almost two millennia.
Like the Latter-day Saints, the present article sees the Apostasy as having happened very long ago. According to Joseph Smith's account, his prayer in 1820 about which denomination to join was answered with:
join none of them, for they were all wrong; and the Personage who addressed me said that all their creeds were an abomination in his sight; that those professors were all corrupt; that: they draw near to me with their lips, but their hearts are far from me, they teach for doctrines the commandments of men, having a form of godliness, but they deny the power thereof.
Thus, corruption of Christianity need not be something new, or necessarily confined to our own century, or a process that people must be able to see happening with their own eyes.
But what is apostasy? We need to know the exact meaning of the term in order to ascertain the era in which Matthew 24.10 and 2 Thessalonians 2.3 were fulfilled, if it does not still lie sometime in the future. Dictionaries indicate that "apostasy" is the complete renunciation or abandonment of a religion, and refusal to have further connection with it. It is not merely a change within a religion, such as introduction of new doctrines or practices, when the innovators see themselves as continuing or restoring the original faith. Members who introduce a radical change within a religion but still hold to the original name and organization are more correctly termed "heretics" rather than "apostates." Note that the word "apostate" does not occur in the answer to Joseph Smith's prayer. Its language is more indicative of heresy or gross distortion rather than of outright renunciation of Christianity.
Indeed, the New Testament's use of the Greek word for "apostasy" or "falling away" indicates nothing less than transferring from one religion to another. It appears only twice in the sacred text, once in 2 Thessalonians 2.3 and once in Acts 21.21. The latter case deals with allegations that the Apostle Paul had taught Jews to abandon circumcision and Jewish traditions, and otherwise "forsake Moses." This implies a total change from the Jewish religion to the Christian, not an internal development within Judaism as if Paul wished to continue well inside the older faith. Muslims fit the proper description of "apostate" perfectly, for they abandon the name "Christian" and follow another religion.
Individual Apostasy
Apostasy by individual Christians was fairly common in the first two and a half centuries AD. At least this is the impression from the large number of warnings and comments about it in Matthew 10.33, Mark, Luke 12.9, 2 Timothy 3.5, Hebrews 6.6, 2 Peter 2.1 and 3.17, and Jude 4. These were continued in the second century by the Letter of Barnabas 5.4, The Shepherd of Hermas, ((Shepherd of Hermas Vision 3.6.5; Similitude 8.8.2, 8.8.4, 8.91.)) Martyrdom of Justin and Companions 4, and the Revelation of Peter 23f. Centuries later, Barnabas and Hermas were so highly regarded that they were given places in some versions of the New Testament.
Tertullian, Origen, and the author(s) of the Didascalia are also to be included among Christians who wrote and preached about apostasy before the Persecution of AD 249 to 251. Tertullian was centered in Carthage in what is now Tunisia. He is of double value in the study of Christianity in the late second and early third century because he wrote both from inside the majority/mainstream church, and later after he had joined a rigorous, apocalyptic denomination. Indicating that apostasy was a continuing and frequent phenomenon in his day are De Corona 11; On Idolatry 22; and On Modesty 9, 19, and 22. The same is true of Origen's books and sermons in Egypt and Palestine: Commentary on Matthew 14.16; De Principiis 1.4.1, 3.1.17; Exhortation to Martyrdom 7, 18, 36f, 40, 48; Homilies on Ezekiel 12.1.2; Homilies on Judges 2.1, 7.2; Homilies on Numbers 19.2.1; and Homily on Psalm 82. ((Homily on Psalm 82 is found only in Eusebius Ecclesiastical History 6.38.)) Origen is our best source for the study of church conditions in the first half of the third century because he traveled frequently as a theological consultant at the invitation of local bishops throughout the eastern Mediterranean, and thus could observe any difference in Christian practice from place to place. His repeated comments on falling away indicate that it was widespread and common. The Didascalia, a manual of church and individual Christian life compiled in the first three decades of the third century, devotes most of Chapter 19 to apostasy.
Reasons for Apostasy
Apostasy and Christian writers' preoccupation with it were to be expected because of the periodic persecutions that Christians could escape only by publicly denying their faith. Besides fear of death in a persecution, some Christians apostatized to pagan philosophy or Judaism because they made more sense from the point of view of pure logic, and provided a more realistic way of life as regards ethics and self-denial. ((Robin Lane Fox, Pagans and Christians: Religion and the Religious Life from the Second to the Fourth Century AD (New York: Alfred A. Knopf, 1987) pp. 270f.)) Having observed pagan freewheeling sexuality and freedom from considering the needs of anyone but themselves, other Christians apostatized because they found their faith just too demanding and arduous. Christianity burdened its adherents with a comparatively rigorous and exacting morality and self-sacrificing generosity. The Christian life was oppressive and highly restrictive in contrast to the relatively bright and breezy lifestyle of the surrounding culture. Hence Christ's counsel in Luke 14.28-33 to count the cost of discipleship before conversion.
An example. Written sometime between AD 198 and 220, Tertullian's treatise on idolatry furnishes an example of apostasy that could occur in everyday life, when references to pagan deities were in common speech, such as well-wishing and expressions like "by Jove":
To be blessed in the name of the gods of the nations is to be cursed in the name of God. If I have given an alms, or shown any kindness, and the recipient pray that his gods may be propitious to me, my oblation or act will immediately be an honour to idols, in whose name he returns me the favour of blessing. But why should he not know that I have done it for God's sake; that God may rather be glorified, and demons may not be honoured in that which I have done for the sake of God? If God sees that I have done it for His sake, He equally sees that I have been unwilling to show that I did it for His sake, and have in a manner made His precept a sacrifice to idols. I think a Christian ought not to deny himself. For whoever dissembles in any cause whatever, by being held as a heathen, does deny; and, of course, all denial is idolatry, just as all idolatry is denial, whether in deeds or in words. ((Tertullian On Idolatry 22; ANF 3.74-75.))
It must be noted that Matthew 24 and 2 Thessalonians 2 do not say the entire church or even a large part of it would apostatize, merely that there would be "a falling away," without specifying the proportion of believers involved.
Mass Apostasies
Apostasy AD 98 to 117. Some present-day Christians, who hold that Matthew 24.10 and 2 Thessalonians 2.3 predict a mass apostasy that would not occur until the twenty-first century, should consider the account of Hegesippus, a churchman who died in AD 180. He visited churches in many parts of the Roman Empire and learned much of events in Christendom from independent but corroborating sources. Recording events in the time of the Emperor Trajan (AD 98 to 117), he noted:
the Church up to that time had remained a pure and uncorrupted virgin, since, if there were any that attempted to corrupt the sound norm of the preaching of salvation, they lay until then concealed in obscure darkness. But when the sacred college of apostles had suffered death in various forms, and the generation of those that had been deemed worthy to hear the inspired wisdom with their own ears had passed away, then the league of godless error took its rise as a result of the folly of heretical teachers, who, because none of the apostles was still living, attempted henceforth, with a bold face, to proclaim, in opposition to the preaching of the truth, the "knowledge which is falsely so-called." ((Eusebius Ecclesiastical History 3.32.7-8, trans. in A Select Library of Nicene and Post-Nicene Fathers of the Christian Church vol. 1 p. 164.))
Pliny the Younger was Roman governor of Bithynia in AD 112, within the period Hegesippus described. Among his duties was to search out Christians and persecute them. Pliny reported to the emperor that many people had confessed to having been members of the church, but had left it before his time. Many of them told him they had abandoned Christianity a long time before, some as long as twenty years. ((Letter 10.96, To Trajan.))
Thus, twenty years after the apostles there occurred a widespread departure from the true and original Christian teaching, if this is what "apostasy" means.
Apostasy ca. AD 100. Many believers in our time assign an earlier period for the falling away: the penning of the last word of the Revelation of John (about AD 100). They hold that it was the last New Testament book to be written, and that the entire worldwide church then sank immediately into utter corruption all at once, after which all Christian writings are full of error and are worthless as a guide to the original Christian teaching, which they believe went extinct or underground so thoroughly that it left no trace in the ensuing historical record. This theory conveniently rationalizes why early Christian writings after the Apostle John cannot be construed to agree with what some of these modern groups now teach. However, it fails to take into account that The First Letter of Clement, and probably the church manual The Didache, were written by churchmen before Revelation and some other books in the present New Testament. Even if they do not believe in a first-century apostasy, today's leading Bible scholars date the Second Letter of Peter after the writings of the church fathers Barnabas, Ignatius, Polycarp, and Aristides—all of whom depict a Christianity different from that hypothesized and practiced by some (but not all) denominations of our time that purport to have restored the pre-apostasy doctrines and practices. If we draw the cut-off point at the time of 2 Peter was written, the New Testament might include in the Revelation of Peter and other books bearing the names of apostles that almost found a place there.
Apostasy AD 249-251. Examining history books in addition to the Bible and daily newspaper, we can identify events in the middle of the third century AD as the most likely fulfillment of Matthew 24.10 and 2 Thessalonians 2.3.
In December AD 249 the Roman Emperor Decius launched the first systematic and Empire-wide persecution against the general Christian population. There had been previous persecutions, but none had been as efficient or as thoroughgoing. The most recent crackdown had occurred in AD 235-238, but it was directed only against clergy. The latest persecution against all Christians had ended in AD 206, and was thus beyond the memory of most people of Decius' time. Indeed, Origen had noted shortly before AD 249 that Christians were "not being persecuted by the authorities as in old times." ((Origen Against Celsus 3.15; ANF 4.470)) Christians were not prepared for a persecution of any sort, let alone the worst to date.
Under Decius, a government edict required everyone in the Empire to sacrifice to the gods of Rome, an act Christians had always considered idolatry and a disavowal of the divine lordship of Christ. Refusal to perform the pagan rite was long the main reason for government execution of the faithful. The only ways of avoiding torture and death were sacrifice, long-term hiding, or producing a certificate from a corrupt government official falsely stating that the bearer had performed the rite.
The Emperor's program was highly successful. It weakened the churches and threw them into internal chaos, leading to an apostasy of unprecedented numbers. A contemporary account by Bishop Cyprian of Carthage, in what is now Tunisia, describes how the majority of Christians traded their religious convictions for earthly considerations:
Immediately at the first words of the threatening foe, the greatest number of the brethren betrayed their faith, and were cast down, not by the onset of persecution, but cast themselves down by voluntary lapse. …. Nor did they even leave it to be said for them, that they seemed to sacrifice to idols unwillingly. They ran to the market-place of their own accord; freely they hastened to [spiritual] death, as if they had formerly wished it, as if they would embrace an opportunity now given which they had always desired. . . . But to many their own destruction was not sufficient. With mutual exhortations, people were urged to their [spiritual] ruin. And that nothing might be wanting to aggravate the crime, infants also, in the arms of their parents, either carried or conducted, lost, while yet little ones, what in the very first beginning of their nativity they had gained. ((Cyprian of Carthage On the Lapsed 7-8; ANF 5.439.))
The Persecution in Egypt was described by Dionysius of Alexandria, who had become bishop of the city in AD 246. Dionysius recorded the categories of reactions to the Emperor's decree that everyone must sacrifice: "a large number . . . speedily accommodated themselves to the decree in fear," "others, who were engaged in public service, were drawn into compliance," "others were dragged on to it by their friends," "others yielded pale and trembling," and "others . . . hurried up to the altars with greater alacrity, stoutly asserting that they had never been Christians at all." ((Dionysius of Alexandria Letter to Fabius, Bishop of Antioch; ANF 6.98-99.))
There were so many intending apostates that in some places government officials had to ask them to come back and sacrifice on another day. Not satisfied with renouncing their own faith, some Christians urged others to sacrifice.
A great many members of the church were clearly not equal to its tradition of martyrdom for Christ or to observing the important Christian precept against worshipping or doing homage to other gods. No previous persecution involved such large numbers or as large a percentage of the Christian population.
The present article identifies at least three probable fulfillments of the prophecy in Matthew and 2 Thessalonians of a falling-away from the Christian faith, and should give pause to people who identify it only with events in our own day, and should prompt them to read church history before they do so.
Darren	on January 22, 2014 at 3:47 pm
I thoroughly enjoyed the historical background of the article.
My simple question is that, since the church Jesus Christ established obviously had living revelation to guide it, by rejecting living revelation, would not the members of that church be following another religion? If so, then would not in and of itself justify the label of "apostasy"?
Jan	on January 12, 2014 at 8:52 pm
Critics of the LDS religion say there was no Apostasy, and there is no proof of an Apostasy, that Joseph Smith made the Apostasy up (because Smith was a charlatan and a liar and deceitful).
It is a mind numbing exercise to try to talk to LDS critics. Of course the critics already have their minds made up about the LDS religion and so they are closed minded and will not look at any information that counters their arguments.
This article answered questions I had about the Apostasy, so thank you! (I like the footnotes because it gives me more sources to read and be aware of)
Roger	on January 7, 2014 at 6:08 pm
I found much to agree with in this article. I noted with interest that the author dated 2 Peter as a late-appearing addition to the canon. It has been my impression that LDS authorities have generally been disinclined to accept that many of the New Testament scriptures may be pseudonymous and that the Epistle of James was originated or at least derived from the brother of Jesus as opposed to the apostle who formed part of a "First Presidency" with Peter and John.
Perhaps, you or your readers can inform me or disabuse me of any mistaken notions.
James Sneak	on January 7, 2014 at 5:02 pm
This is a great question to ask and excellent historical research. I am unconvinced that the persecution noted in the article was successful in causing an apostasy. The Christian church certainly remained in other geographic areas and prospered. The edict of Milan in 313 made it illegal to persecute people for their religion and was primarily aimed at protecting Christians. Was their any priesthood authority on the earth at this time? Did Constantine received a vision? Was his mother a committed Christian? This was a fascinating time period and one that deserves more research and writing.
merrill clark	on January 7, 2014 at 3:44 pm
In trying to time the apoatasy, I heard something that caused me to significantly move up my apostasy date. We know that the Twelve to operate, they need to act as a quorum and that a majority or seven may constitute a quorum. Thus when the Twelve Apostles numbered less than seven and stopped acting as a quorum is in my mind when the apostasy accelerated forward.
George Joseph DeMetz	on January 7, 2014 at 1:28 am
The great apostasy from the primitive church lasted 1260 years (see Revelation 12:6 and JST Revelation 12:5). Obviously, since the church was restored to public ministry in 1830 AD, the great apostasy began in 570 AD, probably with the Lombard invasion. No doubt the church's public ministry was in steady decline before that time, the invasion probably was the single factor that totally drove it into obscurity. However, it is technically incorrect to state that it was taken from the earth since there were still translated beings who held priesthood keys and authority during that time.
Russell Spencer	on January 30, 2014 at 1:54 pm
That's an interesting perspective. Using 1260 years as the measurement for duration of the Great Apostasy might offer other insights as well. Latter-day Apostles and Prophets have often described the Great Apostasy as a gradual process, and the Restoration in the same way (including the great Reformers in that work)–like sunset followed, in time, by sunrise. Focusing on that analogy, between sunset and dusk, when darkness falls, there is a diminishing twilight; between dawn, when darkness is taken, and sunrise there is also a growing twilight.
Extending our analogy, perhaps dawn came long before the First Vision, maybe with the first of the great Reformers–John Wycliffe in Oxford, about 1376 AD. Moving back 1260 years, we'd find sunset at about 116 AD, a likely time-frame for the martyrdom of the apostles in the primitive church. The First Vision then becomes the beginning of sunrise, with the restoration of the apostleship by Peter, James, and John in 1829 or 1830 perhaps culminating that rise. Moving back 1260 years, this corresponds well to the heightened proliferation of schisms and creeds in the latter part of the 6th Century (which changed the ordinances, fundamentally altered man's understanding of the nature of God, etc.). In Joseph Smith's account of the First Vision, it is the creeds that are the abomination, not the people.
Ty	on January 6, 2014 at 4:16 pm
My question is, how can an apostasy be imposed from outside an organization? Certainly the persecutions experienced by the early Christians is far worse than I've ever experienced, and many fell away because of it, but a full apostasy of an organization can't occur without the consent of those running the church, right? Even if large numbers of Christians leave (or leave this mortal realm), as long as there is a small body of true believers there is still a true church, (i think).
To me, the apostasy occurred whenever the ordinances were changed. Any idea when that happened?
Leave a Reply to Russell Spencer Cancel reply
Teachings and Testimony of the First Vision: President James E. Faust Teaches and Testifies of the First Vision
A Critical Text
Teachings and Testimony of the First Vision: Some Doctrinal Teachings about the First Vision
Teachings and Testimony of the First Vision: Introduction
The Kinshasa DR Congo Temple: A Personal Perspective Part 4: Vignettes of Joy and Gratitude from the Kinshasa Temple Open House
The Kinshasa DR Congo Temple: A Personal Perspective Part 2: Media Session of the Kinshasa Temple Open House
The Kinshasa DR Congo Temple: A Personal Perspective Part 1: Preparing for the Kinshasa Temple Open House
The Ezekiel Mural at Dura Europos and the Mysteries of Aaron, Moses, and Melchizedek
DNA Helps Solve a Historical Question about Joseph Smith
A Review of the Annotated Edition of the Book of Mormon (Postscript)

redpajama_set_name: RedPajamaCommonCrawl


text:
Macrotrachela inermis är en hjuldjursart som beskrevs av Donner 1965. Macrotrachela inermis ingår i släktet Macrotrachela och familjen Philodinidae. Inga underarter finns listade i Catalogue of Life.

Källor

Bdelloider
inermis


text:
Roll Up Your Sleeves is an Irish documentary about do-it-yourself counterculture directed by Dylan Haskins. It also examines the relationship between DIY culture and the need for autonomous social spaces, looking at various projects across Europe and how these compare with the situation in Ireland.

Outline

Roll Up Your Sleeves was shot over a two-year period by Haskins and his friends. The film begins by focusing on the non-profit all-ages gigs in his Haskins' own home "The Hideaway House" in Ireland leads him to drive US folk punk band Ghost Mice on their European tour and to the conclusion that this is all about much more than music.

Interviewees include Ian MacKaye of alternative bands Fugazi and Minor Threat; Ellen Lupton, author of DIY: Design it Yourself and Curator of Contemporary Design at the Cooper-Hewitt National Design Museum in New York; Ellie and Louise Macnamara of Irish band Heathers; and members of long-running Dutch experimental punk band The Ex.

Funding

The film received BCI Sound & Vision funding. It was produced by Project Arts Centre for DCTV.

Reception

Roll Up Your Sleeves premiered at the 2009 Stranger Than Fiction Festival in the IFI in Dublin.

In January 2011, the film was made available free online, garnering international media attention.

External links
Roll Up Your Sleeves on Vimeo

References

2008 films
Irish documentary films
Documentary films about music and musicians
2008 documentary films
2000s English-language films