diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ActivityInstanceEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ActivityInstanceEvent.java index 043c214..f39588c 100644 --- a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ActivityInstanceEvent.java +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ActivityInstanceEvent.java @@ -6,10 +6,10 @@ * ActivityInstanceEvent class. *

* - * - * + * + * * @author viadee - * + * * @version $Id: $Id */ public class ActivityInstanceEvent extends ScopeInstanceEvent { diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionDefinitionEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionDefinitionEvent.java new file mode 100644 index 0000000..94f3e4a --- /dev/null +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionDefinitionEvent.java @@ -0,0 +1,88 @@ +package de.viadee.camunda.kafka.event; + +import java.util.Date; + +public class DecisionDefinitionEvent extends DeploymentEvent { + + private String key; + private String category; + private Integer version; + private String resource; + private String decisionRequirementsDefinitionId; + private String decisionRequirementsDefinitionKey; + private Integer historyTimeToLive; + private String versionTag; + private String xml; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getResource() { + return resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public String getDecisionRequirementsDefinitionId() { + return decisionRequirementsDefinitionId; + } + + public void setDecisionRequirementsDefinitionId(String decisionRequirementsDefinitionId) { + this.decisionRequirementsDefinitionId = decisionRequirementsDefinitionId; + } + + public String getDecisionRequirementsDefinitionKey() { + return decisionRequirementsDefinitionKey; + } + + public void setDecisionRequirementsDefinitionKey(String decisionRequirementsDefinitionKey) { + this.decisionRequirementsDefinitionKey = decisionRequirementsDefinitionKey; + } + + public Integer getHistoryTimeToLive() { + return historyTimeToLive; + } + + public void setHistoryTimeToLive(Integer historyTimeToLive) { + this.historyTimeToLive = historyTimeToLive; + } + + public String getVersionTag() { + return versionTag; + } + + public void setVersionTag(String versionTag) { + this.versionTag = versionTag; + } + + public String getXml() { + return xml; + } + + public void setXml(String xml) { + this.xml = xml; + } +} diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionInstanceEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionInstanceEvent.java new file mode 100644 index 0000000..4a1cd21 --- /dev/null +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionInstanceEvent.java @@ -0,0 +1,164 @@ +package de.viadee.camunda.kafka.event; + +import java.util.Date; +import java.util.List; + +/** + *

+ * DecisionInstanceEvent class. + *

+ * + * + * + * @author viadee + * + * @version $Id: $Id + */ +public class DecisionInstanceEvent extends HistoryEvent { + + private String decisionDefinitionId; + private String decisionDefinitionKey; + private String decisionDefinitionName; + private Date evaluationTime; + private Date removalTime; + private String activityId; + private String activityInstanceId; + private String tenantId; + private String userId; + private String rootDecisionInstanceId; + private String rootProcessInstanceId; + private String decisionRequirementsDefinitionId; + private String decisionRequirementsDefinitionKey; + private Double collectResultValue; + private List inputs; + private List outputs; + + public String getDecisionDefinitionId() { + return decisionDefinitionId; + } + + public void setDecisionDefinitionId(String decisionDefinitionId) { + this.decisionDefinitionId = decisionDefinitionId; + } + + public String getDecisionDefinitionKey() { + return decisionDefinitionKey; + } + + public void setDecisionDefinitionKey(String decisionDefinitionKey) { + this.decisionDefinitionKey = decisionDefinitionKey; + } + + public String getDecisionDefinitionName() { + return decisionDefinitionName; + } + + public void setDecisionDefinitionName(String decisionDefinitionName) { + this.decisionDefinitionName = decisionDefinitionName; + } + + public Date getEvaluationTime() { + return evaluationTime; + } + + public void setEvaluationTime(Date evaluationTime) { + this.evaluationTime = evaluationTime; + } + + public Date getRemovalTime() { + return removalTime; + } + + public void setRemovalTime(Date removalTime) { + this.removalTime = removalTime; + } + + public String getActivityId() { + return activityId; + } + + public void setActivityId(String activityId) { + this.activityId = activityId; + } + + public String getActivityInstanceId() { + return activityInstanceId; + } + + public void setActivityInstanceId(String activityInstanceId) { + this.activityInstanceId = activityInstanceId; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getRootDecisionInstanceId() { + return rootDecisionInstanceId; + } + + public void setRootDecisionInstanceId(String rootDecisionInstanceId) { + this.rootDecisionInstanceId = rootDecisionInstanceId; + } + + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + + public void setRootProcessInstanceId(String rootProcessInstanceId) { + this.rootProcessInstanceId = rootProcessInstanceId; + } + + public String getDecisionRequirementsDefinitionId() { + return decisionRequirementsDefinitionId; + } + + public void setDecisionRequirementsDefinitionId(String decisionRequirementsDefinitionId) { + this.decisionRequirementsDefinitionId = decisionRequirementsDefinitionId; + } + + public String getDecisionRequirementsDefinitionKey() { + return decisionRequirementsDefinitionKey; + } + + public void setDecisionRequirementsDefinitionKey(String decisionRequirementsDefinitionKey) { + this.decisionRequirementsDefinitionKey = decisionRequirementsDefinitionKey; + } + + public Double getCollectResultValue() { + return collectResultValue; + } + + public void setCollectResultValue(Double collectResultValue) { + this.collectResultValue = collectResultValue; + } + + public List getInputs() { + return inputs; + } + + public void setInputs(List inputs) { + this.inputs = inputs; + } + + public List getOutputs() { + return outputs; + } + + public void setOutputs(List outputs) { + this.outputs = outputs; + } + +} diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionInstanceInputEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionInstanceInputEvent.java new file mode 100644 index 0000000..00b29b7 --- /dev/null +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionInstanceInputEvent.java @@ -0,0 +1,107 @@ +package de.viadee.camunda.kafka.event; + +import java.util.Date; +import java.util.Map; + +public class DecisionInstanceInputEvent { + + private String id; + private String decisionInstanceId; + private String clauseId; + private String clauseName; + private String errorMessage; + private String type; + private Date createTime; + private Date removalTime; + private String rootProcessInstanceId; + private String value; + private Map valueInfo; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDecisionInstanceId() { + return decisionInstanceId; + } + + public void setDecisionInstanceId(String decisionInstanceId) { + this.decisionInstanceId = decisionInstanceId; + } + + public String getClauseId() { + return clauseId; + } + + public void setClauseId(String clauseId) { + this.clauseId = clauseId; + } + + public String getClauseName() { + return clauseName; + } + + public void setClauseName(String clauseName) { + this.clauseName = clauseName; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getRemovalTime() { + return removalTime; + } + + public void setRemovalTime(Date removalTime) { + this.removalTime = removalTime; + } + + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + + public void setRootProcessInstanceId(String rootProcessInstanceId) { + this.rootProcessInstanceId = rootProcessInstanceId; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Map getValueInfo() { + return valueInfo; + } + + public void setValueInfo(Map valueInfo) { + this.valueInfo = valueInfo; + } +} diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionInstanceOutputEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionInstanceOutputEvent.java new file mode 100644 index 0000000..46043c3 --- /dev/null +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DecisionInstanceOutputEvent.java @@ -0,0 +1,135 @@ +package de.viadee.camunda.kafka.event; + +import java.util.Date; +import java.util.Map; + +public class DecisionInstanceOutputEvent { + + private String id; + private String decisionInstanceId; + private String clauseId; + private String clauseName; + private String ruleId; + private String ruleOrder; + private String errorMessage; + private String variableName; + private String type; + private Date createTime; + private Date removalTime; + private String rootProcessInstanceId; + private String value; + + private Map valueInfo = null; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDecisionInstanceId() { + return decisionInstanceId; + } + + public void setDecisionInstanceId(String decisionInstanceId) { + this.decisionInstanceId = decisionInstanceId; + } + + public String getClauseId() { + return clauseId; + } + + public void setClauseId(String clauseId) { + this.clauseId = clauseId; + } + + public String getClauseName() { + return clauseName; + } + + public void setClauseName(String clauseName) { + this.clauseName = clauseName; + } + + public String getRuleId() { + return ruleId; + } + + public void setRuleId(String ruleId) { + this.ruleId = ruleId; + } + + public String getRuleOrder() { + return ruleOrder; + } + + public void setRuleOrder(String ruleOrder) { + this.ruleOrder = ruleOrder; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getVariableName() { + return variableName; + } + + public void setVariableName(String variableName) { + this.variableName = variableName; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getRemovalTime() { + return removalTime; + } + + public void setRemovalTime(Date removalTime) { + this.removalTime = removalTime; + } + + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + + public void setRootProcessInstanceId(String rootProcessInstanceId) { + this.rootProcessInstanceId = rootProcessInstanceId; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Map getValueInfo() { + return valueInfo; + } + + public void setValueInfo(Map valueInfo) { + this.valueInfo = valueInfo; + } +} diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DeploymentEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DeploymentEvent.java index ac6b93a..a71560f 100644 --- a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DeploymentEvent.java +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DeploymentEvent.java @@ -8,10 +8,10 @@ * DeploymentEvent class. *

* - * - * + * + * * @author viadee - * + * * @version $Id: $Id */ public class DeploymentEvent { diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DetailEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DetailEvent.java index 3b6bc5a..4d1e417 100644 --- a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DetailEvent.java +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/DetailEvent.java @@ -8,10 +8,10 @@ * DetailEvent class. *

* - * - * + * + * * @author viadee - * + * * @version $Id: $Id */ public class DetailEvent extends HistoryEvent { diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/HistoryEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/HistoryEvent.java index 0577f12..a613511 100644 --- a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/HistoryEvent.java +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/HistoryEvent.java @@ -8,10 +8,10 @@ * HistoryEvent class. *

* - * - * + * + * * @author viadee - * + * * @version $Id: $Id */ @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/IncidentEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/IncidentEvent.java index 2d08d6c..26fcc27 100644 --- a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/IncidentEvent.java +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/IncidentEvent.java @@ -8,10 +8,10 @@ * IncidentEvent class. *

* - * - * + * + * * @author viadee - * + * * @version $Id: $Id */ public class IncidentEvent extends HistoryEvent { diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ProcessDefinitionEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ProcessDefinitionEvent.java index 54b5bde..fed78f0 100644 --- a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ProcessDefinitionEvent.java +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ProcessDefinitionEvent.java @@ -6,10 +6,10 @@ * ProcessDefinitionEvent class. *

* - * - * + * + * * @author viadee - * + * * @version $Id: $Id */ public class ProcessDefinitionEvent extends DeploymentEvent { diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ProcessInstanceEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ProcessInstanceEvent.java index fbc6ae5..e2683b6 100644 --- a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ProcessInstanceEvent.java +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ProcessInstanceEvent.java @@ -6,10 +6,10 @@ * ProcessInstanceEvent class. *

* - * - * + * + * * @author viadee - * + * * @version $Id: $Id */ public class ProcessInstanceEvent extends ScopeInstanceEvent { diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ScopeInstanceEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ScopeInstanceEvent.java index c7c6dd4..d9789b6 100644 --- a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ScopeInstanceEvent.java +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/ScopeInstanceEvent.java @@ -8,10 +8,10 @@ * ScopeInstanceEvent class. *

* - * - * + * + * * @author viadee - * + * * @version $Id: $Id */ public class ScopeInstanceEvent extends HistoryEvent { diff --git a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/VariableUpdateEvent.java b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/VariableUpdateEvent.java index 01a4e3a..607016c 100644 --- a/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/VariableUpdateEvent.java +++ b/camunda-kafka-model/src/main/java/de/viadee/camunda/kafka/event/VariableUpdateEvent.java @@ -6,10 +6,10 @@ * VariableUpdateEvent class. *

* - * - * + * + * * @author viadee - * + * * @version $Id: $Id */ public class VariableUpdateEvent extends DetailEvent { diff --git a/camunda-kafka-polling-client/pom.xml b/camunda-kafka-polling-client/pom.xml index 083a900..05b34c0 100644 --- a/camunda-kafka-polling-client/pom.xml +++ b/camunda-kafka-polling-client/pom.xml @@ -237,6 +237,8 @@ h2 test + + diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/config/properties/ApplicationProperties.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/config/properties/ApplicationProperties.java index 6ad2e10..f41aab7 100755 --- a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/config/properties/ApplicationProperties.java +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/config/properties/ApplicationProperties.java @@ -75,7 +75,9 @@ public enum PollingEvents { PROCESS_DEFINITION, TASK_COMMENTS, IDENTITY_LINKS_UNFINISHED_ACTIVITIES, - IDENTITY_LINKS_FINISHED_ACTIVITIES + IDENTITY_LINKS_FINISHED_ACTIVITIES, + DECISION_DEFINITION, + DECISION_INSTANCE } public long getKafkaSendTimeoutInSeconds() { diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/job/repository/RepositoryDataPollingService.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/job/repository/RepositoryDataPollingService.java index 4315987..13c077c 100755 --- a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/job/repository/RepositoryDataPollingService.java +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/job/repository/RepositoryDataPollingService.java @@ -1,5 +1,6 @@ package de.viadee.camunda.kafka.pollingclient.job.repository; +import de.viadee.camunda.kafka.event.DecisionDefinitionEvent; import de.viadee.camunda.kafka.event.ProcessDefinitionEvent; import de.viadee.camunda.kafka.pollingclient.config.properties.ApplicationProperties; import de.viadee.camunda.kafka.pollingclient.service.event.EventService; @@ -63,6 +64,15 @@ public void run() { LOGGER.info("Finished polling repository data: {}", pollingTimeslice); } + private void pollDecisionDefinitions(PollingTimeslice pollingTimeslice) { + if (properties.getPollingEvents().contains(ApplicationProperties.PollingEvents.DECISION_DEFINITION)) { + for (final DecisionDefinitionEvent decisionDefinitionEvent : pollingService.pollDecisionDefinitions(pollingTimeslice.getStartTime(), + pollingTimeslice.getEndTime())) { + eventService.sendEvent(decisionDefinitionEvent); + } + } + } + private void pollProcessDefinitions(final PollingTimeslice pollingTimeslice) { if (properties.getPollingEvents().contains(ApplicationProperties.PollingEvents.PROCESS_DEFINITION)) { for (final ProcessDefinitionEvent processDefinitionEvent : pollingService diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/job/runtime/RuntimeDataPollingService.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/job/runtime/RuntimeDataPollingService.java index 7963980..3cd87f8 100755 --- a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/job/runtime/RuntimeDataPollingService.java +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/job/runtime/RuntimeDataPollingService.java @@ -9,6 +9,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.FileWriter; +import java.io.IOException; import java.util.Date; /** @@ -184,10 +186,23 @@ private void pollFinishedActivities(final String processInstanceId, final Pollin && activityInstanceEvent.getActivityType().equals("userTask")) { pollIdentityLinks(activityInstanceEvent); } + + if (properties.getPollingEvents() + .contains(ApplicationProperties.PollingEvents.DECISION_INSTANCE) + && activityInstanceEvent.getActivityType().equals("businessRuleTask")) { + pollDecisionInstances(activityInstanceEvent.getActivityInstanceId()); + } } } } + private void pollDecisionInstances(final String activityInstanceId) { + for (final DecisionInstanceEvent decisionInstanceEvent : pollingService + .pollDecisionInstances(activityInstanceId)) { + eventService.sendEvent(decisionInstanceEvent); + } + } + private void pollCurrentVariables(final String activityInstanceId) { for (final VariableUpdateEvent variableUpdateEvent : pollingService .pollCurrentVariables(activityInstanceId)) { diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/PollingService.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/PollingService.java index c6289c0..2b13161 100755 --- a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/PollingService.java +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/PollingService.java @@ -115,4 +115,23 @@ Iterable pollUnfinishedActivities(String processInstanceI * @return a {@link java.lang.Iterable} object. */ Iterable pollIdentityLinks(ActivityInstanceEvent activityInstanceEvent); + + /** + * Poll decision definitions + * + * @param deploymentAfter + * inclusive + * @param deploymentBefore + * exclusive + * @return a {@link java.lang.Iterable} object. + */ + Iterable pollDecisionDefinitions(Date deploymentAfter, Date deploymentBefore); + + /** + * Poll decision instances for businessRuleTask + * + * @param activityInstanceId + * @return a {@link java.lang.Iterable} object. + */ + Iterable pollDecisionInstances(String activityInstanceId); } diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/jdbc/CamundaJdbcPollingServiceImpl.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/jdbc/CamundaJdbcPollingServiceImpl.java index 32dc240..8bc0b7f 100755 --- a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/jdbc/CamundaJdbcPollingServiceImpl.java +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/jdbc/CamundaJdbcPollingServiceImpl.java @@ -12,6 +12,7 @@ import org.camunda.bpm.engine.history.*; import org.camunda.bpm.engine.impl.persistence.entity.HistoricDetailVariableInstanceUpdateEntity; import org.camunda.bpm.engine.impl.persistence.entity.HistoricVariableInstanceEntity; +import org.camunda.bpm.engine.repository.DecisionDefinition; import org.camunda.bpm.engine.repository.Deployment; import org.camunda.bpm.engine.repository.ProcessDefinition; import org.camunda.bpm.engine.task.Comment; @@ -20,9 +21,11 @@ import org.springframework.beans.BeanUtils; import java.io.IOException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; /** *

@@ -236,6 +239,108 @@ public Iterable pollIdentityLinks(ActivityInstanceEvent activ .map(historicIdentityLinkLog -> createIdentityLinkEventFromDetails(historicIdentityLinkLog))::iterator; } + @Override + public Iterable pollDecisionDefinitions(Date deploymentAfter, Date deploymentBefore) { + 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 decisionDefinitions = repositoryService.createDecisionDefinitionQuery() + .deploymentId(deployment.getId()) + .list(); + + // query decision definitions + for (DecisionDefinition decisionDefinition : decisionDefinitions) { + DecisionDefinitionEvent decisionDefinitionEvent = createDecisionDefinitionEvent(deployment, + decisionDefinition); + + // query xml + try { + String xml = IOUtils.toString(repositoryService.getResourceAsStream(decisionDefinition.getDeploymentId(), + decisionDefinition.getResourceName())); + decisionDefinitionEvent.setXml(xml); + } catch (IOException e) { + throw new RuntimeException("error while reading xml for decision definition" + + decisionDefinition.getId(), e); + } + result.add(decisionDefinitionEvent); + } + } + return result; + } + + @Override + public Iterable pollDecisionInstances(String activityInstanceId) { + return historyService.createHistoricDecisionInstanceQuery() + .activityInstanceIdIn(activityInstanceId) + .includeInputs() + .includeOutputs() + .disableCustomObjectDeserialization() + .list() + .stream() + .map(this::createDecisionInstanceEvent)::iterator; + } + + private DecisionInstanceEvent createDecisionInstanceEvent(HistoricDecisionInstance historicDecisionInstance) { + + DecisionInstanceEvent event = new DecisionInstanceEvent(); + BeanUtils.copyProperties(historicDecisionInstance, event); + + event.setInputs(historicDecisionInstance.getInputs() + .stream() + .map(this::createDecisionInstanceInputEvent) + .collect(Collectors.toList())); + + event.setOutputs(historicDecisionInstance.getOutputs() + .stream() + .map(this::createDecisionInstanceOutputEvent) + .collect(Collectors.toList())); + + return event; + } + + private DecisionInstanceInputEvent createDecisionInstanceInputEvent(HistoricDecisionInputInstance historicDecisionInputInstance) { + + DecisionInstanceInputEvent event = new DecisionInstanceInputEvent(); + BeanUtils.copyProperties(historicDecisionInputInstance, event); + // Since camunda returns strings in lowercase for this attribute, the type string is formatted to match + // the REST responses + event.setType(formatString(historicDecisionInputInstance.getTypeName())); + event.setValue(String.valueOf(historicDecisionInputInstance.getTypedValue().getValue())); + + return event; + } + + private DecisionInstanceOutputEvent createDecisionInstanceOutputEvent(HistoricDecisionOutputInstance historicDecisionOutputInstance) { + + DecisionInstanceOutputEvent event = new DecisionInstanceOutputEvent(); + BeanUtils.copyProperties(historicDecisionOutputInstance, event); + // Since camunda returns strings in lowercase for this attribute, the type string is formatted to match + // the REST responses + event.setType(formatString(historicDecisionOutputInstance.getTypeName())); + event.setValue(String.valueOf(historicDecisionOutputInstance.getTypedValue().getValue())); + + return event; + } + + private String formatString(String string) { + return string.substring(0, 1).toUpperCase() + string.substring(1); + } + + private DecisionDefinitionEvent createDecisionDefinitionEvent(Deployment d, DecisionDefinition dd) { + DecisionDefinitionEvent event = new DecisionDefinitionEvent(); + BeanUtils.copyProperties(d, event); + BeanUtils.copyProperties(dd, event); + return event; + } + private ProcessDefinitionEvent createProcessDefinitionEvent(Deployment d, ProcessDefinition pd) { ProcessDefinitionEvent e = new ProcessDefinitionEvent(); diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/CamundaRestPollingServiceImpl.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/CamundaRestPollingServiceImpl.java index bc0609b..6ae8bc2 100755 --- a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/CamundaRestPollingServiceImpl.java +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/CamundaRestPollingServiceImpl.java @@ -40,6 +40,7 @@ public class CamundaRestPollingServiceImpl implements PollingService { private static final String PROCESS_DEFINITION_ID = "processDefinitionId"; private static final String DEPLOYMENT_ID = "deploymentId"; private static final String TASK_ID = "taskId"; + private static final String DECISION_DEFINITION_ID = "decisionDefinitionId"; private final ObjectMapper objectMapper; @@ -232,6 +233,41 @@ public Iterable pollUnfinishedActivities(String processIn } } + @Override + public Iterable pollDecisionInstances(String activityInstanceId) { + + final String url = camundaProperties.getUrl() + + "history/decision-instance?disableCustomObjectDeserialization=true&includeInputs=true&includeOutputs=true&activityInstanceIdIn={activityInstanceId}"; + try { + final Map variables = new HashMap<>(); + variables.put(ACTIVITY_INSTANCE_ID, activityInstanceId); + + LOGGER.debug("Polling decision instances from {} ({})", url, variables); + + List result = this.restTemplate + .exchange(url, + HttpMethod.GET, + null, + new ParameterizedTypeReference>() { + + }, + variables) + .getBody(); + + if (result == null) { + return new ArrayList<>(); + } + + LOGGER.debug("Found {} decision instances from {} ({})", result.size(), url, variables); + + return result + .stream() + .map(this::createDecisionInstanceEvent)::iterator; + } catch (RestClientException e) { + throw new RuntimeException("Error requesting Camunda REST API (" + url + ") for decision instances", e); + } + } + /** {@inheritDoc} */ @Override public Iterable pollCurrentVariables(String activityInstanceId) { @@ -330,7 +366,7 @@ public Iterable pollProcessDefinitions(final Date startT /** * {@inheritDoc} - * + * * @param activityInstanceEvent */ @Override @@ -405,6 +441,93 @@ public Iterable pollIdentityLinks(final ActivityInstanceEvent } } + /** + * {@inheritDoc} + */ + @Override + public Iterable pollDecisionDefinitions(final Date startTime, final Date endTime) { + + List deploymentList = getDeployments(startTime, endTime); + List decisionDefinitionList = new ArrayList<>(); + + for (GetDeploymentResponse deployment : deploymentList) { + decisionDefinitionList.addAll(getDecisionDefinitions(deployment)); + } + + for (DecisionDefinitionEvent decisionDefinitionEvent : decisionDefinitionList) { + GetDecisionDefinitionXmlResponse decisionDefinitionXML = getDecisionDefinitionXml(decisionDefinitionEvent.getId()); + + if (decisionDefinitionXML != null) { + decisionDefinitionEvent.setXml(decisionDefinitionXML.getDmnXml()); + } + } + + return decisionDefinitionList.stream()::iterator; + } + + private List getDecisionDefinitions(GetDeploymentResponse deploymentResponse) { + final String url = camundaProperties.getUrl() + "decision-definition?deploymentId={deploymentId}"; + + List decisionDefinitions = new ArrayList<>(); + try { + final Map variables = new HashMap<>(); + variables.put("deploymentId", deploymentResponse.getId()); + LOGGER.debug("Polling decision definitions from {} ({})", url, variables); + + decisionDefinitions = this.restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference>() { + }, variables) + .getBody(); + + if (decisionDefinitions == null) { + decisionDefinitions = new ArrayList<>(); + } + + LOGGER.debug("Found {} decision definitions from {} ({})", decisionDefinitions.size(), url, variables); + } catch (RestClientException e) { + throw new RuntimeException("Error requesting Camunda REST API (" + url + ") for decision definitions", e); + } + + return decisionDefinitions.stream() + .map(response -> createDecisionDefinitionEvent(response, deploymentResponse)) + .collect(Collectors.toList()); + } + + private DecisionDefinitionEvent createDecisionDefinitionEvent(GetDecisionDefinitionResponse resp, + final GetDeploymentResponse deploymentResponse) { + final DecisionDefinitionEvent event = new DecisionDefinitionEvent(); + BeanUtils.copyProperties(deploymentResponse, event); + BeanUtils.copyProperties(resp, event); + return event; + } + + private GetDecisionDefinitionXmlResponse getDecisionDefinitionXml(String decisionDefinitionId) { + final String url = camundaProperties.getUrl() + "decision-definition/{decisionDefinitionId}/xml"; + + GetDecisionDefinitionXmlResponse resp; + try { + final Map variables = new HashMap<>(); + variables.put(DECISION_DEFINITION_ID, decisionDefinitionId); + + LOGGER.debug("Polling decision definition xml from {} ({})", url, variables); + + resp = this.restTemplate.exchange(url, HttpMethod.GET, null, GetDecisionDefinitionXmlResponse.class, + variables) + .getBody(); + + if (resp != null) { + LOGGER.debug("Found decision definition xml from {} ({})", url, variables); + } else { + LOGGER.debug("No decision definition xml found from {} ({})", url, variables); + } + } catch (RestClientException e) { + throw new RuntimeException("Error requesting Camunda REST API (" + url + ") for decision definition xml", + e); + } + + return resp; + } + private GetProcessDefinitionXmlResponse getProcessDefinitionXML(String processDefinitionId) { final String url = camundaProperties.getUrl() + "process-definition/{processDefinitionId}/xml"; @@ -537,6 +660,40 @@ private ActivityInstanceEvent createActivityInstanceEvent( return event; } + private DecisionInstanceEvent createDecisionInstanceEvent(GetHistoricDecisionInstanceResponse getHistoricDecisionInstanceResponse) { + + final DecisionInstanceEvent event = new DecisionInstanceEvent(); + BeanUtils.copyProperties(getHistoricDecisionInstanceResponse, event); + + event.setInputs(getHistoricDecisionInstanceResponse.getInputs() + .stream() + .map(this::createDecisionInstanceInputEvent) + .collect(Collectors.toList())); + + event.setOutputs(getHistoricDecisionInstanceResponse.getOutputs() + .stream() + .map(this::createDecisionInstanceOutputEvent) + .collect(Collectors.toList())); + + return event; + } + + private DecisionInstanceInputEvent createDecisionInstanceInputEvent(GetHistoricDecisionInstanceInputResponse getHistoricDecisionInstanceInputResponse) { + + final DecisionInstanceInputEvent event = new DecisionInstanceInputEvent(); + BeanUtils.copyProperties(getHistoricDecisionInstanceInputResponse, event); + + return event; + } + + private DecisionInstanceOutputEvent createDecisionInstanceOutputEvent(GetHistoricDecisionInstanceOutputResponse getHistoricDecisionInstanceOutputResponse) { + + final DecisionInstanceOutputEvent event = new DecisionInstanceOutputEvent(); + BeanUtils.copyProperties(getHistoricDecisionInstanceOutputResponse, event); + + return event; + } + private VariableUpdateEvent createVariableUpdateEventFromInstance( GetHistoricVariableInstancesResponse getHistoricVariableInstancesResponse, Date pollingTimestamp) { diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetDecisionDefinitionResponse.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetDecisionDefinitionResponse.java new file mode 100644 index 0000000..cdc5451 --- /dev/null +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetDecisionDefinitionResponse.java @@ -0,0 +1,119 @@ +package de.viadee.camunda.kafka.pollingclient.service.polling.rest.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +/** + * Response structure of Camunda REST API GET /decision-definition + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class GetDecisionDefinitionResponse { + + private String id; + private String key; + private String category; + private String name; + private Integer version; + private String resource; + private String deploymentId; + private String tenantId; + private String decisionRequirementsDefinitionId; + private String decisionRequirementsDefinitionKey; + private Integer historyTimeToLive; + private String versionTag; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getResource() { + return resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public String getDeploymentId() { + return deploymentId; + } + + public void setDeploymentId(String deploymentId) { + this.deploymentId = deploymentId; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public String getDecisionRequirementsDefinitionId() { + return decisionRequirementsDefinitionId; + } + + public void setDecisionRequirementsDefinitionId(String decisionRequirementsDefinitionId) { + this.decisionRequirementsDefinitionId = decisionRequirementsDefinitionId; + } + + public String getDecisionRequirementsDefinitionKey() { + return decisionRequirementsDefinitionKey; + } + + public void setDecisionRequirementsDefinitionKey(String decisionRequirementsDefinitionKey) { + this.decisionRequirementsDefinitionKey = decisionRequirementsDefinitionKey; + } + + public Integer getHistoryTimeToLive() { + return historyTimeToLive; + } + + public void setHistoryTimeToLive(Integer historyTimeToLive) { + this.historyTimeToLive = historyTimeToLive; + } + + public String getVersionTag() { + return versionTag; + } + + public void setVersionTag(String versionTag) { + this.versionTag = versionTag; + } +} diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetDecisionDefinitionXmlResponse.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetDecisionDefinitionXmlResponse.java new file mode 100644 index 0000000..ffb9e86 --- /dev/null +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetDecisionDefinitionXmlResponse.java @@ -0,0 +1,26 @@ +package de.viadee.camunda.kafka.pollingclient.service.polling.rest.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class GetDecisionDefinitionXmlResponse { + + private String id; + private String dmnXml; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDmnXml() { + return dmnXml; + } + + public void setDmnXml(String dmnXml) { + this.dmnXml = dmnXml; + } +} diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetHistoricDecisionInstanceInputResponse.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetHistoricDecisionInstanceInputResponse.java new file mode 100644 index 0000000..af044b7 --- /dev/null +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetHistoricDecisionInstanceInputResponse.java @@ -0,0 +1,130 @@ +// Generated by delombok at Fri Jan 04 11:18:40 CET 2019 +package de.viadee.camunda.kafka.pollingclient.service.polling.rest.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.Date; +import java.util.Map; + +/** + * Response structure of Camunda REST API GET /history/decision-instance + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class GetHistoricDecisionInstanceInputResponse { + + private String id; + private String decisionInstanceId; + private String clauseId; + private String clauseName; + private String errorMessage; + private String type; + private Date createTime; + private Date removalTime; + private String rootProcessInstanceId; + private String value; + private Map valueInfo; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDecisionInstanceId() { + return decisionInstanceId; + } + + public void setDecisionInstanceId(String decisionInstanceId) { + this.decisionInstanceId = decisionInstanceId; + } + + public String getClauseId() { + return clauseId; + } + + public void setClauseId(String clauseId) { + this.clauseId = clauseId; + } + + public String getClauseName() { + return clauseName; + } + + public void setClauseName(String clauseName) { + this.clauseName = clauseName; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getRemovalTime() { + return removalTime; + } + + public void setRemovalTime(Date removalTime) { + this.removalTime = removalTime; + } + + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + + public void setRootProcessInstanceId(String rootProcessInstanceId) { + this.rootProcessInstanceId = rootProcessInstanceId; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Map getValueInfo() { + return valueInfo; + } + + public void setValueInfo(Map valueInfo) { + this.valueInfo = valueInfo; + } + + @Override + public String toString() { + return "GetHistoricDecisionInstanceInputResponse{" + + "id='" + id + '\'' + + ", decisionInstanceId='" + decisionInstanceId + '\'' + + ", clauseId='" + clauseId + '\'' + + ", clauseName='" + clauseName + '\'' + + ", errorMessage='" + errorMessage + '\'' + + ", type='" + type + '\'' + + ", createTime='" + createTime + '\'' + + ", removalTime='" + removalTime + '\'' + + ", rootProcessInstanceId='" + rootProcessInstanceId + '\'' + + ", value='" + value + '\'' + + '}'; + } +} diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetHistoricDecisionInstanceOutputResponse.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetHistoricDecisionInstanceOutputResponse.java new file mode 100755 index 0000000..3d20e41 --- /dev/null +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetHistoricDecisionInstanceOutputResponse.java @@ -0,0 +1,161 @@ +// Generated by delombok at Fri Jan 04 11:18:40 CET 2019 +package de.viadee.camunda.kafka.pollingclient.service.polling.rest.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.Date; +import java.util.Map; + +/** + * Response structure of Camunda REST API GET /history/decision-instance + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class GetHistoricDecisionInstanceOutputResponse { + + private String id; + private String decisionInstanceId; + private String clauseId; + private String clauseName; + private String ruleId; + private String ruleOrder; + private String errorMessage; + private String variableName; + private String type; + private Date createTime; + private Date removalTime; + private String rootProcessInstanceId; + private String value; + + private Map valueInfo; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDecisionInstanceId() { + return decisionInstanceId; + } + + public void setDecisionInstanceId(String decisionInstanceId) { + this.decisionInstanceId = decisionInstanceId; + } + + public String getClauseId() { + return clauseId; + } + + public void setClauseId(String clauseId) { + this.clauseId = clauseId; + } + + public String getClauseName() { + return clauseName; + } + + public void setClauseName(String clauseName) { + this.clauseName = clauseName; + } + + public String getRuleId() { + return ruleId; + } + + public void setRuleId(String ruleId) { + this.ruleId = ruleId; + } + + public String getRuleOrder() { + return ruleOrder; + } + + public void setRuleOrder(String ruleOrder) { + this.ruleOrder = ruleOrder; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getVariableName() { + return variableName; + } + + public void setVariableName(String variableName) { + this.variableName = variableName; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getRemovalTime() { + return removalTime; + } + + public void setRemovalTime(Date removalTime) { + this.removalTime = removalTime; + } + + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + + public void setRootProcessInstanceId(String rootProcessInstanceId) { + this.rootProcessInstanceId = rootProcessInstanceId; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Map getValueInfo() { + return valueInfo; + } + + public void setValueInfo(Map valueInfo) { + this.valueInfo = valueInfo; + } + + @Override + public String toString() { + return "GetHistoricDecisionInstanceOutputResponse{" + + "id='" + id + '\'' + + ", decisionInstanceId='" + decisionInstanceId + '\'' + + ", clauseId='" + clauseId + '\'' + + ", clauseName='" + clauseName + '\'' + + ", ruleId='" + ruleId + '\'' + + ", ruleOrder='" + ruleOrder + '\'' + + ", errorMessage='" + errorMessage + '\'' + + ", variableName='" + variableName + '\'' + + ", type='" + type + '\'' + + ", createTime='" + createTime + '\'' + + ", removalTime='" + removalTime + '\'' + + ", rootProcessInstanceId='" + rootProcessInstanceId + '\'' + + ", value='" + value + '\'' + + '}'; + } +} diff --git a/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetHistoricDecisionInstanceResponse.java b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetHistoricDecisionInstanceResponse.java new file mode 100755 index 0000000..daec55a --- /dev/null +++ b/camunda-kafka-polling-client/src/main/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/response/GetHistoricDecisionInstanceResponse.java @@ -0,0 +1,251 @@ +// Generated by delombok at Fri Jan 04 11:18:40 CET 2019 +package de.viadee.camunda.kafka.pollingclient.service.polling.rest.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.Date; +import java.util.List; + +/** + * Response structure of Camunda REST API GET /history/decision-instance + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class GetHistoricDecisionInstanceResponse { + + private String id; + private String decisionDefinitionId; + private String decisionDefinitionKey; + private String decisionDefinitionName; + private Date evaluationTime; + private Date removalTime; + private String processDefinitionId; + private String processDefinitionKey; + private String processInstanceId; + private String caseDefinitionId; + private String caseDefinitionKey; + private String caseInstanceId; + private String activityId; + private String activityInstanceId; + private String tenantId; + private String userId; + private List inputs; + private List outputs; + private String collectResultValue; + private String rootDecisionInstanceId; + private String rootProcessInstanceId; + private String decisionRequirementsDefinitionId; + private String decisionRequirementsDefinitionKey; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDecisionDefinitionId() { + return decisionDefinitionId; + } + + public void setDecisionDefinitionId(String decisionDefinitionId) { + this.decisionDefinitionId = decisionDefinitionId; + } + + public String getDecisionDefinitionKey() { + return decisionDefinitionKey; + } + + public void setDecisionDefinitionKey(String decisionDefinitionKey) { + this.decisionDefinitionKey = decisionDefinitionKey; + } + + public String getDecisionDefinitionName() { + return decisionDefinitionName; + } + + public void setDecisionDefinitionName(String decisionDefinitionName) { + this.decisionDefinitionName = decisionDefinitionName; + } + + public Date getEvaluationTime() { + return evaluationTime; + } + + public void setEvaluationTime(Date evaluationTime) { + this.evaluationTime = evaluationTime; + } + + public Date getRemovalTime() { + return removalTime; + } + + public void setRemovalTime(Date removalTime) { + this.removalTime = removalTime; + } + + public String getProcessDefinitionId() { + return processDefinitionId; + } + + public void setProcessDefinitionId(String processDefinitionId) { + this.processDefinitionId = processDefinitionId; + } + + public String getProcessDefinitionKey() { + return processDefinitionKey; + } + + public void setProcessDefinitionKey(String processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public void setProcessInstanceId(String processInstanceId) { + this.processInstanceId = processInstanceId; + } + + public String getCaseDefinitionId() { + return caseDefinitionId; + } + + public void setCaseDefinitionId(String caseDefinitionId) { + this.caseDefinitionId = caseDefinitionId; + } + + public String getCaseDefinitionKey() { + return caseDefinitionKey; + } + + public void setCaseDefinitionKey(String caseDefinitionKey) { + this.caseDefinitionKey = caseDefinitionKey; + } + + public String getCaseInstanceId() { + return caseInstanceId; + } + + public void setCaseInstanceId(String caseInstanceId) { + this.caseInstanceId = caseInstanceId; + } + + public String getActivityId() { + return activityId; + } + + public void setActivityId(String activityId) { + this.activityId = activityId; + } + + public String getActivityInstanceId() { + return activityInstanceId; + } + + public void setActivityInstanceId(String activityInstanceId) { + this.activityInstanceId = activityInstanceId; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public List getInputs() { + return inputs; + } + + public void setInputs(List inputs) { + this.inputs = inputs; + } + + public List getOutputs() { + return outputs; + } + + public void setOutputs(List ouputs) { + this.outputs = ouputs; + } + + public String getCollectResultValue() { + return collectResultValue; + } + + public void setCollectResultValue(String collectResultValue) { + this.collectResultValue = collectResultValue; + } + + public String getRootDecisionInstanceId() { + return rootDecisionInstanceId; + } + + public void setRootDecisionInstanceId(String rootDecisionInstanceId) { + this.rootDecisionInstanceId = rootDecisionInstanceId; + } + + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + + public void setRootProcessInstanceId(String rootProcessInstanceId) { + this.rootProcessInstanceId = rootProcessInstanceId; + } + + public String getDecisionRequirementsDefinitionId() { + return decisionRequirementsDefinitionId; + } + + public void setDecisionRequirementsDefinitionId(String decisionRequirementsDefinitionId) { + this.decisionRequirementsDefinitionId = decisionRequirementsDefinitionId; + } + + public String getDecisionRequirementsDefinitionKey() { + return decisionRequirementsDefinitionKey; + } + + public void setDecisionRequirementsDefinitionKey(String decisionRequirementsDefinitionKey) { + this.decisionRequirementsDefinitionKey = decisionRequirementsDefinitionKey; + } + + @Override + public String toString() { + return "GetHistoricDecisionInstanceResponse{" + + "id='" + id + '\'' + + ", decisionDefinitionId='" + decisionDefinitionId + '\'' + + ", decisionDefinitionKey='" + decisionDefinitionKey + '\'' + + ", decisionDefinitionName='" + decisionDefinitionName + '\'' + + ", evaluationTime='" + evaluationTime + '\'' + + ", removalTime='" + removalTime + '\'' + + ", processDefinitionId='" + processDefinitionId + '\'' + + ", processDefinitionKey='" + processDefinitionKey + '\'' + + ", processInstanceId='" + processInstanceId + '\'' + + ", caseDefinitionId='" + caseDefinitionId + '\'' + + ", caseDefinitionKey='" + caseDefinitionKey + '\'' + + ", caseInstanceId='" + caseInstanceId + '\'' + + ", activityId='" + activityId + '\'' + + ", activityInstanceId='" + activityInstanceId + '\'' + + ", tenantId='" + tenantId + '\'' + + ", userId='" + userId + '\'' + + ", inputs='" + inputs + '\'' + + ", outputs='" + outputs + '\'' + + ", collectResultValue='" + collectResultValue + '\'' + + ", rootDecisionInstanceId='" + rootDecisionInstanceId + '\'' + + ", rootProcessInstanceId='" + rootProcessInstanceId + '\'' + + ", decisionRequirementsDefinitionId='" + decisionRequirementsDefinitionId + '\'' + + ", decisionRequirementsDefinitionKey='" + decisionRequirementsDefinitionKey + '\'' + + '}'; + } +} diff --git a/camunda-kafka-polling-client/src/main/resources/application-rest.properties b/camunda-kafka-polling-client/src/main/resources/application-rest.properties index a6ec816..b9167a9 100644 --- a/camunda-kafka-polling-client/src/main/resources/application-rest.properties +++ b/camunda-kafka-polling-client/src/main/resources/application-rest.properties @@ -2,4 +2,4 @@ polling.camunda.rest.url=${CAMUNDA_REST_URL:} polling.camunda.rest.username=${CAMUNDA_REST_USERNAME:} polling.camunda.rest.password=${CAMUNDA_REST_PASSWORD:} polling.camunda.rest.source-time-zone=${CAMUNDA_REST_SOURCE_TIME_ZONE:} -polling.camunda.rest.date-format-pattern=${CAMUNDA_REST_DATE_FORMAT_PATERN:} \ No newline at end of file +polling.camunda.rest.date-format-pattern=${CAMUNDA_REST_DATE_FORMAT_PATERN:} diff --git a/camunda-kafka-polling-client/src/main/resources/application.properties b/camunda-kafka-polling-client/src/main/resources/application.properties index 8172fd7..028096f 100755 --- a/camunda-kafka-polling-client/src/main/resources/application.properties +++ b/camunda-kafka-polling-client/src/main/resources/application.properties @@ -10,7 +10,7 @@ polling.runtime-data.enabled=true polling.runtime-data.initial-timestamp=${POLLING_RUNTIME_DATA_INITIAL_TIMESTAMP:} polling.runtime-data.interval-in-ms=30000 polling.runtime-data.backward-offset-in-ms=60000 -polling.runtime-data.last-polled-file=./lastPolled-runtime.properties +polling.runtime-data.last-polled-file=./lastPolled-runtime.properties polling.polling-events[0]=PROCESS_INSTANCE_UNFINISHED polling.polling-events[1]=PROCESS_INSTANCE_FINISHED @@ -22,7 +22,8 @@ polling.polling-events[6]=PROCESS_DEFINITION polling.polling-events[7]=TASK_COMMENTS polling.polling-events[8]=IDENTITY_LINKS_UNFINISHED_ACTIVITIES polling.polling-events[9]=IDENTITY_LINKS_FINISHED_ACTIVITIES - +polling.polling-events[10]=DECISION_DEFINITION +polling.polling-events[11]=DECISION_INSTANCE spring.kafka.producer.bootstrap-servers=${KAFKA_BOOTSTRAP_SERVERS:} spring.kafka.producer.client-id=camunda-kafka-polling-client diff --git a/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/job/runtime/RuntimeDataPollingServiceTest.java b/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/job/runtime/RuntimeDataPollingServiceTest.java index 0a02aeb..c63efca 100755 --- a/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/job/runtime/RuntimeDataPollingServiceTest.java +++ b/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/job/runtime/RuntimeDataPollingServiceTest.java @@ -2,10 +2,14 @@ import de.viadee.camunda.kafka.event.ActivityInstanceEvent; import de.viadee.camunda.kafka.event.CommentEvent; -import de.viadee.camunda.kafka.event.IdentityLinkEvent; +import de.viadee.camunda.kafka.event.DecisionInstanceEvent; +import de.viadee.camunda.kafka.event.DecisionInstanceInputEvent; +import de.viadee.camunda.kafka.event.DecisionInstanceOutputEvent; import de.viadee.camunda.kafka.event.HistoryEvent; +import de.viadee.camunda.kafka.event.IdentityLinkEvent; import de.viadee.camunda.kafka.event.ProcessInstanceEvent; import de.viadee.camunda.kafka.pollingclient.config.properties.ApplicationProperties; +import de.viadee.camunda.kafka.pollingclient.model.Car; import de.viadee.camunda.kafka.pollingclient.service.event.EventService; import de.viadee.camunda.kafka.pollingclient.service.lastpolled.LastPolledService; import de.viadee.camunda.kafka.pollingclient.service.lastpolled.PollingTimeslice; @@ -14,14 +18,23 @@ import org.camunda.bpm.engine.HistoryService; import org.camunda.bpm.engine.ProcessEngine; import org.camunda.bpm.engine.ProcessEngineConfiguration; +import org.camunda.bpm.engine.ProcessEngines; import org.camunda.bpm.engine.TaskService; +import org.camunda.bpm.engine.history.HistoricDecisionInputInstance; +import org.camunda.bpm.engine.history.HistoricDecisionInstance; +import org.camunda.bpm.engine.history.HistoricDecisionOutputInstance; import org.camunda.bpm.engine.history.HistoricIdentityLinkLog; +import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin; import org.camunda.bpm.engine.impl.util.ClockUtil; import org.camunda.bpm.engine.runtime.ProcessInstance; import org.camunda.bpm.engine.task.Comment; import org.camunda.bpm.engine.task.Task; +import org.camunda.bpm.engine.variable.VariableMap; +import org.camunda.bpm.engine.variable.Variables; import org.camunda.bpm.model.bpmn.Bpmn; import org.camunda.bpm.model.bpmn.BpmnModelInstance; +import org.camunda.spin.plugin.impl.SpinProcessEnginePlugin; import org.junit.jupiter.api.*; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -75,12 +88,19 @@ enum PointOfTime { @BeforeEach void setup() { LogFactory.useSlf4jLogging(); - processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration() - .setJobExecutorActivate(false) - .setHistory(ProcessEngineConfiguration.HISTORY_FULL) - .setDatabaseSchemaUpdate( - ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP) - .buildProcessEngine(); + SpinProcessEnginePlugin spinProcessEnginePlugin = new SpinProcessEnginePlugin(); + + ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration() + .setJobExecutorActivate(false) + .setHistory(ProcessEngineConfiguration.HISTORY_FULL) + .setDatabaseSchemaUpdate( + ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP); + + spinProcessEnginePlugin.preInit((ProcessEngineConfigurationImpl) configuration); + + processEngine = configuration.buildProcessEngine(); + + spinProcessEnginePlugin.postInit((ProcessEngineConfigurationImpl) configuration); lastPolledService = mock(LastPolledService.class); eventSendService = mock(EventService.class); @@ -605,6 +625,79 @@ static Stream pollIdentityLinks() { // @formatter:on } + @DisplayName("Polling of decision instances") + @Test + void pollDecisionInstances() { + + // initiate process + setCurrentTime(BEFORE_CUTOFF); + processEngine.getRepositoryService() + .createDeployment() + .addClasspathResource("dmn/dmnTest.bpmn") + .addClasspathResource("dmn/dmnTest.dmn") + .deploy(); + + // create object + Car car = new Car("Twingo", 200); + + // create input + VariableMap variables = Variables.createVariables() + .putValue("car", car); + + // start process instance with dmn table + setCurrentTime(START_TIME); + processEngine.getRuntimeService() + .startProcessInstanceByKey("simpleDmn", variables); + + // expected result + HistoryService historyService = processEngine.getHistoryService(); + List expectedDecisionInstances = historyService + .createHistoricDecisionInstanceQuery() + .includeOutputs() + .includeInputs() + .disableCustomObjectDeserialization() + .list(); + + HistoricDecisionInputInstance expectedDecisionInputInstance = expectedDecisionInstances.get(0) + .getInputs() + .get(0); + HistoricDecisionOutputInstance expectedDecisionOutputInstance = expectedDecisionInstances.get(0) + .getOutputs() + .get(0); + + // retrieve results (start polling) + when(lastPolledService.getPollingTimeslice()) + .thenReturn(new PollingTimeslice(CUTOFF_TIME.date, START_TIME.date, + END_TIME.date)); + + // perform polling + pollingService.run(); + + // Verify decision instance event + final ArgumentCaptor decisionInstanceEventCaptor = ArgumentCaptor.forClass(HistoryEvent.class); + verify(eventSendService, atLeastOnce()).sendEvent(decisionInstanceEventCaptor.capture()); + + final List polledDecisionInstances = decisionInstanceEventCaptor.getAllValues() + .stream() + .filter(event -> event instanceof DecisionInstanceEvent) + .map(event -> ((DecisionInstanceEvent) event)) + .collect(toList()); + + DecisionInstanceEvent polledDecisionInstance = polledDecisionInstances.get(0); + DecisionInstanceInputEvent polledDecisionInputInstance = polledDecisionInstance.getInputs().get(0); + DecisionInstanceOutputEvent polledDecisionOutputInstance = polledDecisionInstance.getOutputs().get(0); + + // assert formatting + assert Character.isLowerCase(expectedDecisionOutputInstance.getTypeName().charAt(0)); + assert Character.isUpperCase(polledDecisionOutputInstance.getType().charAt(0)); + assert Character.isLowerCase(expectedDecisionInputInstance.getTypeName().charAt(0)); + assert Character.isUpperCase(polledDecisionInputInstance.getType().charAt(0)); + + // assert polling + assertEquals(expectedDecisionOutputInstance.getValue(), + Boolean.valueOf(polledDecisionOutputInstance.getValue())); + } + private static void setCurrentTime(PointOfTime time) { ClockUtil.setCurrentTime(time.date); } diff --git a/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/model/Car.java b/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/model/Car.java new file mode 100644 index 0000000..a231f82 --- /dev/null +++ b/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/model/Car.java @@ -0,0 +1,30 @@ +package de.viadee.camunda.kafka.pollingclient.model; + +import java.io.Serializable; + +public class Car implements Serializable { + + private String model; + private int value; + + public Car(String model, int value) { + this.model = model; + this.value = value; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } +} diff --git a/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/CamundaRestPollingServiceImplTest.java b/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/CamundaRestPollingServiceImplTest.java index e85960b..d170f97 100755 --- a/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/CamundaRestPollingServiceImplTest.java +++ b/camunda-kafka-polling-client/src/test/java/de/viadee/camunda/kafka/pollingclient/service/polling/rest/CamundaRestPollingServiceImplTest.java @@ -1,8 +1,9 @@ package de.viadee.camunda.kafka.pollingclient.service.polling.rest; +import de.viadee.camunda.kafka.event.DecisionInstanceEvent; import de.viadee.camunda.kafka.event.ProcessInstanceEvent; import de.viadee.camunda.kafka.pollingclient.config.properties.CamundaRestPollingProperties; -import de.viadee.camunda.kafka.pollingclient.service.polling.rest.response.GetHistoricProcessInstanceResponse; +import de.viadee.camunda.kafka.pollingclient.service.polling.rest.response.*; import org.junit.jupiter.api.Test; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.ResponseEntity; @@ -92,6 +93,59 @@ void pollFinishedProcessInstances() { assertFalse(iter.hasNext()); } + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Test + void pollDecisionInstances() { + + // create CamundaRestPollingProperties + CamundaRestPollingProperties prop = new CamundaRestPollingProperties(); + prop.setPassword("XY"); + prop.setUrl("XY"); + prop.setUsername("XY"); + + Date startTime = parseDate("2009-11-02T09:45:00.000UTC+00:00"); + + GetHistoricActivityInstanceRespone a = new GetHistoricActivityInstanceRespone(); + a.setActivityId("1"); + a.setStartTime(startTime); + + List inputList = new ArrayList<>(); + GetHistoricDecisionInstanceInputResponse i = new GetHistoricDecisionInstanceInputResponse(); + i.setId("1"); + i.setValue("100"); + inputList.add(i); + + List outputList = new ArrayList<>(); + GetHistoricDecisionInstanceOutputResponse o = new GetHistoricDecisionInstanceOutputResponse(); + o.setId("1"); + o.setValue("true"); + outputList.add(o); + + List decisionInstanceList = new ArrayList(); + GetHistoricDecisionInstanceResponse d = new GetHistoricDecisionInstanceResponse(); + d.setId("123"); + d.setActivityId(a.getActivityId()); + d.setInputs(inputList); + d.setOutputs(outputList); + decisionInstanceList.add(d); + + // mocking + ResponseEntity mockedResponseEntity = mock(ResponseEntity.class); + when(mockedResponseEntity.getBody()).thenReturn(decisionInstanceList); + when(mockedRestTemplate.exchange(any(), any(), any(), (ParameterizedTypeReference) any(), + (Map) any())).thenReturn(mockedResponseEntity); + + // call functions + CamundaRestPollingServiceImpl c = new CamundaRestPollingServiceImpl(prop, mockedRestTemplate); + Iterable pieIterator = c.pollDecisionInstances(a.getActivityId()); + + Iterator iter = pieIterator.iterator(); + + assertEquals("123", iter.next().getId()); + assertFalse(iter.hasNext()); + + } + @SuppressWarnings({ "rawtypes", "unchecked" }) @Test void diffSourceTimeZone() throws ParseException { diff --git a/camunda-kafka-polling-client/src/test/resources/dmn/dmnTest.bpmn b/camunda-kafka-polling-client/src/test/resources/dmn/dmnTest.bpmn new file mode 100644 index 0000000..036ccbb --- /dev/null +++ b/camunda-kafka-polling-client/src/test/resources/dmn/dmnTest.bpmn @@ -0,0 +1,40 @@ + + + + + Flow_1vt00hy + + + Flow_0xfqpdc + + + + + + Flow_1vt00hy + Flow_0xfqpdc + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/camunda-kafka-polling-client/src/test/resources/dmn/dmnTest.dmn b/camunda-kafka-polling-client/src/test/resources/dmn/dmnTest.dmn new file mode 100644 index 0000000..a84f9d1 --- /dev/null +++ b/camunda-kafka-polling-client/src/test/resources/dmn/dmnTest.dmn @@ -0,0 +1,68 @@ + + + + + + + car.value + + + + + + [0..100[ + + + true + + + + + [100..200[ + + + true + + + + + [200..300[ + + + true + + + + + [400..500[ + + + false + + + + + [600..700[ + + + false + + + + + > 700 + + + false + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 27c3a27..bf8d4d8 100644 --- a/pom.xml +++ b/pom.xml @@ -228,6 +228,18 @@ ${junit.version} + + org.camunda.bpm.dmn + camunda-engine-dmn + test + + + + org.camunda.bpm.dmn + camunda-engine-dmn-bom + test + + org.mockito mockito-core