de.viadee.camunda.kafka.pollingclient.service.polling.jdbc.CamundaJdbcPollingServiceImpl Maven / Gradle / Ivy
package de.viadee.camunda.kafka.pollingclient.service.polling.jdbc;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.viadee.camunda.kafka.event.*;
import de.viadee.camunda.kafka.pollingclient.service.polling.PollingService;
import de.viadee.camunda.kafka.pollingclient.service.polling.rest.CamundaRestPollingServiceImpl;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.camunda.bpm.engine.HistoryService;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.history.HistoricActivityInstance;
import org.camunda.bpm.engine.history.HistoricDetail;
import org.camunda.bpm.engine.history.HistoricProcessInstance;
import org.camunda.bpm.engine.history.HistoricVariableInstance;
import org.camunda.bpm.engine.impl.persistence.entity.HistoricDetailVariableInstanceUpdateEntity;
import org.camunda.bpm.engine.impl.persistence.entity.HistoricVariableInstanceEntity;
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.task.Comment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
*
* CamundaJdbcPollingServiceImpl class.
*
*
* @author viadee
* @version $Id: $Id
*/
public class CamundaJdbcPollingServiceImpl implements PollingService {
private final HistoryService historyService;
private static final Logger LOGGER = LoggerFactory.getLogger(CamundaRestPollingServiceImpl.class);
private final RepositoryService repositoryService;
private final TaskService taskService;
private final ObjectMapper objectMapper = new ObjectMapper();
/**
*
* Constructor for CamundaJdbcPollingServiceImpl.
*
*
* @param historyService
* a {@link HistoryService} object.
* @param repositoryService
* a {@link RepositoryService} object.
* @param taskService
* a {@link TaskService} object.
*/
public CamundaJdbcPollingServiceImpl(HistoryService historyService, RepositoryService repositoryService,
TaskService taskService) {
this.historyService = historyService;
this.repositoryService = repositoryService;
this.taskService = taskService;
}
/**
* {@inheritDoc}
*/
@Override
public Iterable pollFinishedProcessInstances(Date startedAfter, Date startedBefore,
Date finishedAfter) {
return historyService.createHistoricProcessInstanceQuery()
.finished()
.startedAfter(startedAfter)
.startedBefore(startedBefore)
.finishedAfter(finishedAfter)
.list()
.stream()
.filter(event -> event.getStartTime().compareTo(startedBefore) < 0) // startedBefore ist
// selected as <= by
// Camunda - thus add
// filter
.map(this::createProcessInstanceEvent)::iterator;
}
/**
* {@inheritDoc}
*/
@Override
public Iterable pollUnfinishedProcessInstances(Date startedAfter, Date startedBefore) {
return historyService.createHistoricProcessInstanceQuery()
.unfinished()
.startedAfter(startedAfter)
.startedBefore(startedBefore)
.list()
.stream()
.filter(event -> event.getStartTime().compareTo(startedBefore) < 0) // startedBefore ist
// selected as <= by
// Camunda - thus add
// filter
.map(this::createProcessInstanceEvent)::iterator;
}
/**
* {@inheritDoc}
*/
@Override
public Iterable pollFinishedActivities(String processInstanceId, Date finishedAfter,
Date finishedBefore) {
return historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.finished()
.finishedAfter(finishedAfter)
.finishedBefore(finishedBefore)
.list()
.stream()
.filter(event -> event.getEndTime().compareTo(finishedBefore) < 0) // finishedBefore ist
// selected as <= by
// Camunda - thus add
// filter
.map(this::createActivityInstanceEvent)::iterator;
}
/**
* {@inheritDoc}
*/
@Override
public Iterable pollUnfinishedActivities(String processInstanceId, Date startedAfter,
Date startedBefore) {
return historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.unfinished()
.startedAfter(startedAfter)
.startedBefore(startedBefore)
.list()
.stream()
.filter(event -> event.getStartTime().compareTo(startedBefore) < 0) // startedBefore ist
// selected as <= by
// Camunda - thus add
// filter
.map(this::createActivityInstanceEvent)::iterator;
}
/**
* {@inheritDoc}
*/
@Override
public Iterable pollCurrentVariables(String activityInstanceId) {
return historyService.createHistoricVariableInstanceQuery()
.activityInstanceIdIn(activityInstanceId)
.disableCustomObjectDeserialization()
.list()
.stream()
.map(this::createVariableUpdateEventFromInstance)::iterator;
}
/**
* {@inheritDoc}
*/
@Override
public Iterable pollVariableDetails(String activityInstanceId) {
return historyService.createHistoricDetailQuery()
.activityInstanceId(activityInstanceId)
.disableCustomObjectDeserialization()
.variableUpdates()
.list()
.stream()
.map(this::createVariableUpdateEventFromDetail)::iterator;
}
/**
* {@inheritDoc}
*/
@Override
public Iterable pollProcessDefinitions(Date deploymentAfter, Date deploymentBefore) {
// There seems to be a slight bug in Camunda SQL queries regarding deployments.
// Where the other history queries regarding time boundaries are inclusive (startedBefore, startedAfter, ...),
// deploymentBefore and deploymentAfter are implemented exclusive.
// Thus we have to slightly adjust the deploymentAfter parameter by 1 millisecond to act inclusive:
deploymentAfter = new Date(deploymentAfter.getTime() - 1);
// query deployments
List deployments = repositoryService.createDeploymentQuery()
.deploymentAfter(deploymentAfter)
.deploymentBefore(deploymentBefore)
.list();
List result = new ArrayList<>();
for (Deployment deployment : deployments) {
List processDefinitions = repositoryService.createProcessDefinitionQuery()
.deploymentId(deployment.getId())
.list();
// query proc def
for (ProcessDefinition processDefinition : processDefinitions) {
ProcessDefinitionEvent processDefinitionEvent = createProcessDefinitionEvent(deployment,
processDefinition);
// query xml
try {
String xml = IOUtils.toString(repositoryService.getProcessModel(processDefinition.getId()));
processDefinitionEvent.setXml(xml);
} catch (IOException e) {
throw new RuntimeException(
"error while reading xml for process definition "
+ processDefinition.getId(),
e);
}
result.add(processDefinitionEvent);
}
}
return result;
}
@Override
public Iterable pollComments(ActivityInstanceEvent activityInstanceEvent) {
return taskService.getTaskComments(activityInstanceEvent.getTaskId())
.stream()
.map(comment -> createCommentEventFromDetails(comment, activityInstanceEvent))::iterator;
}
private ProcessDefinitionEvent createProcessDefinitionEvent(Deployment d, ProcessDefinition pd) {
ProcessDefinitionEvent e = new ProcessDefinitionEvent();
e.setId(pd.getId());
e.setCategory(pd.getCategory());
e.setDescription(pd.getDescription());
e.setHistoryTimeToLive(pd.getHistoryTimeToLive());
e.setKey(pd.getKey());
e.setName(pd.getName());
e.setResource(pd.getResourceName());
e.setSuspended(pd.isSuspended());
e.setVersion(pd.getVersion());
e.setVersionTag(pd.getVersionTag());
e.setDeploymentId(pd.getDeploymentId());
e.setTenantId(pd.getTenantId());
e.setDeploymentTime(d.getDeploymentTime());
e.setSource(d.getSource());
return e;
}
private ProcessInstanceEvent createProcessInstanceEvent(HistoricProcessInstance historicProcessInstance) {
final ProcessInstanceEvent event = new ProcessInstanceEvent();
BeanUtils.copyProperties(historicProcessInstance, event);
return event;
}
private ActivityInstanceEvent createActivityInstanceEvent(HistoricActivityInstance historicActivityInstance) {
final ActivityInstanceEvent event = new ActivityInstanceEvent();
BeanUtils.copyProperties(historicActivityInstance, event);
event.setActivityInstanceId(event.getId());
return event;
}
private VariableUpdateEvent createVariableUpdateEventFromInstance(
HistoricVariableInstance historicVariableInstance) {
final VariableUpdateEvent event = new VariableUpdateEvent();
BeanUtils.copyProperties(historicVariableInstance, event);
event.setEventType(historicVariableInstance.getState());
event.setVariableInstanceId(historicVariableInstance.getId());
copyVariableLongValueToDoubleValue(event);
if (historicVariableInstance instanceof HistoricVariableInstanceEntity) {
final HistoricVariableInstanceEntity historicVariableInstanceEntity = (HistoricVariableInstanceEntity) historicVariableInstance;
setVariableComplexValue(event,
historicVariableInstanceEntity.getSerializerName(),
historicVariableInstanceEntity.getByteArrayValue());
}
return event;
}
private VariableUpdateEvent createVariableUpdateEventFromDetail(HistoricDetail historicDetail) {
final VariableUpdateEvent event = new VariableUpdateEvent();
BeanUtils.copyProperties(historicDetail, event);
copyVariableLongValueToDoubleValue(event);
if (historicDetail instanceof HistoricDetailVariableInstanceUpdateEntity) {
final HistoricDetailVariableInstanceUpdateEntity historicVariableDetail = (HistoricDetailVariableInstanceUpdateEntity) historicDetail;
setVariableComplexValue(event,
historicVariableDetail.getSerializerName(),
historicVariableDetail.getByteArrayValue());
}
return event;
}
private CommentEvent createCommentEventFromDetails(
Comment comment, ActivityInstanceEvent activityInstanceEvent) {
final CommentEvent event = new CommentEvent();
BeanUtils.copyProperties(activityInstanceEvent, event);
event.setId(comment.getId());
event.setUserId(comment.getUserId());
event.setTimestamp(comment.getTime());
event.setMessage(comment.getFullMessage());
return event;
}
private void setVariableComplexValue(VariableUpdateEvent event, String serializerName, byte[] value) {
if (StringUtils.contains(serializerName, "spin:") && value != null) {
try {
final Object decodedValue = this.objectMapper.readValue(value, Object.class);
if (decodedValue != null) {
event.setComplexValue(decodedValue);
}
} catch (IOException e) {
LOGGER.error("IOException found.");
}
}
}
private void copyVariableLongValueToDoubleValue(VariableUpdateEvent event) {
if (event.getLongValue() != null) {
event.setDoubleValue(event.getLongValue().doubleValue());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy