Hi,
I note that a custom activity has an end time before this activity is leaved.
process:
<?xml version="1.0" encoding="UTF-8"?>
<process name="HistoryServiceTest" xmlns="http://jbpm.org/4.4/jpdl">
<start name="start" g="77,144,48,48">
<transition to="custom-state" />
</start>
<custom name="custom-state" g="175,140,105,52" class="processes.classes.SimpleCustomState">
<transition to="end" />
</custom>
<end name="end" g="324,144,48,48" />
</process>
SimpleCustomState.java:
package processes.classes;
import java.util.Map;
import org.jbpm.api.activity.ActivityExecution;
import org.jbpm.api.activity.ExternalActivityBehaviour;
public class SimpleCustomState implements ExternalActivityBehaviour
{
private static final long serialVersionUID = 1L;
public void execute(ActivityExecution execution) throws Exception {
execution.waitForSignal();
}
public void signal(ActivityExecution execution, String signalName, Map<String, ?> parameters)
throws Exception {
execution.takeDefaultTransition();
}
}
test:
package services;
import org.junit.Assert.*;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipInputStream;
import org.jbpm.api.*;
import org.junit.*;
public class HistoryServiceTest
{
private HistoryService historyService;
private ExecutionService executionService;
private RepositoryService repositoryService;
@Before
public void setup() {
initEngine();
deployProcess();
}
public void initEngine() {
ProcessEngine processEngine = new Configuration().setResource("default.jbpm.cfg.xml")
.buildProcessEngine();
executionService = processEngine.getExecutionService();
historyService = processEngine.getHistoryService();
repositoryService = processEngine.getRepositoryService();
}
public void deployProcess() {
ZipInputStream zipInputStream = new ZipInputStream(getClass().getResourceAsStream("/jbpm.zip"));
repositoryService.createDeployment().addResourcesFromZipInputStream(zipInputStream).setName("test")
.setTimestamp(new Date().getTime()).deploy();
}
public String startProcess() {
ProcessInstance processInstance = executionService.startProcessInstanceByKey("HistoryServiceTest");
return processInstance.getId();
}
private boolean isRunning(String processInstanceId) {
ProcessInstance pi = executionService.findProcessInstanceById(processInstanceId);
return pi != null ? pi.isEnded() : false;
}
@Test
public void testHasEndDateForEndedCustomActivity() {
String processInstanceId = startProcess();
String activityName = "custom-state";
assertTrue(executionService.findProcessInstanceById(processInstanceId).isActive(activityName));
executionService.signalExecutionById(processInstanceId, "");
assertFalse(isRunning(processInstanceId));
HistoryActivityInstance historyActivityInstance = historyService.createHistoryActivityInstanceQuery()
.processInstanceId(processInstanceId).activityName(activityName).uniqueResult();
assertNotNull(historyActivityInstance.getEndTime());
}
@Test
public void testHasNoEndDateForActiveCustomActivity() {
String processInstanceId = startProcess();
String activityName = "custom-state";
assertTrue(executionService.findProcessInstanceById(processInstanceId).isActive(activityName));
List<HistoryActivityInstance> historyActivityInstances = historyService
.createHistoryActivityInstanceQuery().processInstanceId(processInstanceId)
.activityName(activityName).list();
if (!historyActivityInstances.isEmpty())
{
for (HistoryActivityInstance historyActivityInstance : historyActivityInstances)
assertNull(historyActivityInstance.getEndTime()); // this fail!
}
}
}
After I looking for a reason, I found something in class UserCodeActivityBehaviour:
public void execute(ActivityExecution execution) throws Exception {
ActivityBehaviour activityBehaviour = (ActivityBehaviour) customActivityReference.getObject(execution);
activityBehaviour.execute(execution);
((ExecutionImpl)execution).historyAutomatic();
}
This methode create a object of class HistoryActivityInstanceImpl and call:
public HistoryAutomaticInstanceImpl(HistoryProcessInstance historyProcessInstanceImpl, ExecutionImpl execution) {
super(historyProcessInstanceImpl, execution);
setEndTime(Clock.getTime());
}
Now I want to ask why this was not implemented like in class StateActivity?
And how to fix this bug?