Index: modules/api/src/main/java/org/jbpm/api/activity/ExternalActivityBehaviour.java =================================================================== --- modules/api/src/main/java/org/jbpm/api/activity/ExternalActivityBehaviour.java (revision 6165) +++ modules/api/src/main/java/org/jbpm/api/activity/ExternalActivityBehaviour.java (working copy) @@ -61,4 +61,5 @@ * used any more and if this is during a transaction, the transaction should be * rolled back. */ void signal(ActivityExecution execution, String signalName, Map parameters) throws Exception; + void timeout(ActivityExecution execution, String signalName) throws Exception; } Index: modules/api/src/main/java/org/jbpm/api/history/HistoryTask.java =================================================================== --- modules/api/src/main/java/org/jbpm/api/history/HistoryTask.java (revision 6165) +++ modules/api/src/main/java/org/jbpm/api/history/HistoryTask.java (working copy) @@ -37,6 +37,7 @@ public interface HistoryTask { String STATE_COMPLETED = "completed"; + String STATE_TIMEDOUT = "timed out"; /** the unique id for this task that is used as a reference in the service methods */ String getId(); Index: modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/TaskActivity.java =================================================================== --- modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/TaskActivity.java (revision 6165) +++ modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/TaskActivity.java (working copy) @@ -27,6 +27,7 @@ import org.jbpm.api.JbpmException; import org.jbpm.api.activity.ActivityExecution; import org.jbpm.api.model.Transition; +import org.jbpm.api.task.Task; import org.jbpm.pvm.internal.cal.Duration; import org.jbpm.pvm.internal.el.Expression; import org.jbpm.pvm.internal.env.EnvironmentImpl; @@ -175,6 +176,24 @@ } } + // JBPM-2537: A triggered timer does not end the task which is left + + public void timeout(ActivityExecution execution, String signalName) throws Exception { + timeout((ExecutionImpl) execution, signalName); + } + + public void timeout(ExecutionImpl execution, String signalName) throws Exception { + + DbSession taskDbSession = EnvironmentImpl .getFromCurrent(DbSession.class); + TaskImpl task = (TaskImpl) taskDbSession.findTaskByExecution(execution); + if (task!=null) { + task.setSignalling(false); + task.timeout(); + taskDbSession.delete((Task) task); + } + + } + public TaskDefinitionImpl getTaskDefinition() { return taskDefinition; } Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/job/TimerImpl.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/job/TimerImpl.java (revision 6165) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/job/TimerImpl.java (working copy) @@ -25,6 +25,8 @@ import java.util.Date; import org.jbpm.api.JbpmException; +import org.jbpm.api.activity.ActivityBehaviour; +import org.jbpm.api.activity.ExternalActivityBehaviour; import org.jbpm.api.cmd.Environment; import org.jbpm.api.job.Timer; import org.jbpm.internal.log.Log; @@ -33,6 +35,7 @@ import org.jbpm.pvm.internal.id.DbidGenerator; import org.jbpm.pvm.internal.jobexecutor.JobAddedNotification; import org.jbpm.pvm.internal.jobexecutor.JobExecutor; +import org.jbpm.pvm.internal.model.ActivityImpl; import org.jbpm.pvm.internal.model.ObservableElement; import org.jbpm.pvm.internal.session.DbSession; import org.jbpm.pvm.internal.session.TimerSession; @@ -82,6 +85,10 @@ throw new JbpmException("environment is null"); } + ActivityImpl activity = execution.getActivity(); + ExternalActivityBehaviour behaviour = (ExternalActivityBehaviour) activity.getActivityBehaviour(); + behaviour.timeout(execution, signalName); + if (signalName!=null) { if (log.isDebugEnabled()) log.debug("feeding timer signal "+signalName+" into "+execution); execution.signal(signalName); Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/task/LifeCycleState.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/task/LifeCycleState.java (revision 6165) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/task/LifeCycleState.java (working copy) @@ -41,4 +41,9 @@ Map parameters) throws Exception { execution.take(signalName); } + + @Override + public void timeout(ActivityExecution execution, String signalName) throws Exception { + // TODO: JBPM-2537 + } } Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java (revision 6165) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java (working copy) @@ -39,6 +39,7 @@ import org.jbpm.pvm.internal.history.HistoryEvent; import org.jbpm.pvm.internal.history.events.TaskComplete; import org.jbpm.pvm.internal.history.events.TaskDelete; +import org.jbpm.pvm.internal.history.events.TaskTimeout; import org.jbpm.pvm.internal.model.ExecutionImpl; import org.jbpm.pvm.internal.model.ProcessDefinitionImpl; import org.jbpm.pvm.internal.model.ScopeInstanceImpl; @@ -210,6 +211,19 @@ public void delete(String reason) { historyTaskDelete(reason); } + + public void timeout(String outcome) { + historyTaskTimeout(outcome); + + DbSession dbSession = EnvironmentImpl.getFromCurrent(DbSession.class, false); + if (dbSession != null) { + dbSession.delete(this); + } + } + + public void timeout() { + historyTaskTimeout(TaskConstants.NO_TASK_OUTCOME_SPECIFIED); + } // state //////////////////////////////////////////////////////////////////// @@ -310,6 +324,12 @@ HistoryEvent.fire(new TaskComplete(outcome), execution); } } + + public void historyTaskTimeout(String outcome) { + if (execution != null) { + HistoryEvent.fire(new TaskTimeout(outcome), execution); + } + } public void signalExecution(String signalName) { if (execution != null) { Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/usercode/UserCodeActivityBehaviour.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/usercode/UserCodeActivityBehaviour.java (revision 6165) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/usercode/UserCodeActivityBehaviour.java (working copy) @@ -49,4 +49,10 @@ public void setCustomActivityReference(UserCodeReference customActivityReference) { this.customActivityReference = customActivityReference; } + + @Override + public void timeout(ActivityExecution execution, String signalName) throws Exception { + ExternalActivityBehaviour externalActivityBehaviour = (ExternalActivityBehaviour) customActivityReference.getObject(execution); + externalActivityBehaviour.timeout(execution, signalName); + } } Index: modules/pvm/src/test/java/org/jbpm/pvm/activities/WaitState.java =================================================================== --- modules/pvm/src/test/java/org/jbpm/pvm/activities/WaitState.java (revision 6165) +++ modules/pvm/src/test/java/org/jbpm/pvm/activities/WaitState.java (working copy) @@ -43,4 +43,9 @@ execution.setVariables(parameters); execution.take(signalName); } + + @Override + public void timeout(ActivityExecution execution, String signalName) throws Exception { + //TODO: JBPM-2537 + } } Index: modules/pvm/src/test/java/org/jbpm/pvm/executionmode/embedded/WaitState.java =================================================================== --- modules/pvm/src/test/java/org/jbpm/pvm/executionmode/embedded/WaitState.java (revision 6165) +++ modules/pvm/src/test/java/org/jbpm/pvm/executionmode/embedded/WaitState.java (working copy) @@ -43,4 +43,9 @@ public void signal(ActivityExecution execution, String signalName, Map parameters) throws Exception { execution.take(signalName); } + + @Override + public void timeout(ActivityExecution execution, String signalName) throws Exception { + // JBPM-2537 + } } \ No newline at end of file